First Commit

This commit is contained in:
2025-12-18 16:28:50 +07:00
commit 8c3e4f491f
9974 changed files with 396488 additions and 0 deletions

1
features/roomdetails/impl/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,83 @@
import extension.setupDependencyInjection
import extension.testCommonDependencies
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023, 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.
*/
plugins {
id("io.element.android-compose-library")
id("kotlin-parcelize")
}
android {
namespace = "io.element.android.features.roomdetails.impl"
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}
setupDependencyInjection()
dependencies {
implementation(projects.appconfig)
implementation(projects.libraries.core)
implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.matrixui)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.uiStrings)
implementation(projects.libraries.androidutils)
implementation(projects.libraries.mediapickers.api)
implementation(projects.libraries.mediaupload.api)
implementation(projects.libraries.mediaviewer.api)
implementation(projects.libraries.featureflag.api)
implementation(projects.libraries.permissions.api)
implementation(projects.libraries.preferences.api)
implementation(projects.libraries.testtags)
api(projects.features.roomdetails.api)
api(projects.libraries.usersearch.api)
api(projects.services.apperror.api)
implementation(libs.coil.compose)
implementation(projects.features.call.api)
implementation(projects.features.startchat.api)
implementation(projects.features.leaveroom.api)
implementation(projects.features.userprofile.shared)
implementation(projects.services.analytics.compose)
implementation(projects.features.poll.api)
implementation(projects.features.messages.api)
implementation(projects.features.roomcall.api)
implementation(projects.features.knockrequests.api)
implementation(projects.features.verifysession.api)
implementation(projects.features.reportroom.api)
implementation(projects.features.roommembermoderation.api)
implementation(projects.features.rolesandpermissions.api)
implementation(projects.features.securityandprivacy.api)
implementation(projects.features.invitepeople.api)
testCommonDependencies(libs, true)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.mediaupload.test)
testImplementation(projects.libraries.mediapickers.test)
testImplementation(projects.libraries.mediaviewer.test)
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.preferences.test)
testImplementation(projects.libraries.usersearch.test)
testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.features.call.test)
testImplementation(projects.features.rolesandpermissions.test)
testImplementation(projects.features.securityandprivacy.test)
testImplementation(projects.features.knockrequests.test)
testImplementation(projects.features.messages.test)
testImplementation(projects.features.poll.test)
testImplementation(projects.features.reportroom.test)
testImplementation(projects.features.startchat.test)
testImplementation(projects.features.verifysession.test)
testImplementation(projects.services.analytics.test)
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint.InitialTarget
import io.element.android.features.roomdetails.impl.RoomDetailsFlowNode.NavTarget
import io.element.android.libraries.architecture.createNode
@ContributesBinding(AppScope::class)
class DefaultRoomDetailsEntryPoint : RoomDetailsEntryPoint {
override fun createNode(
parentNode: Node,
buildContext: BuildContext,
params: RoomDetailsEntryPoint.Params,
callback: RoomDetailsEntryPoint.Callback,
): Node {
return parentNode.createNode<RoomDetailsFlowNode>(
buildContext = buildContext,
plugins = listOf(params, callback)
)
}
}
internal fun InitialTarget.toNavTarget() = when (this) {
is InitialTarget.RoomDetails -> NavTarget.RoomDetails
is InitialTarget.RoomMemberDetails -> NavTarget.RoomMemberDetails(roomMemberId)
is InitialTarget.RoomNotificationSettings -> NavTarget.RoomNotificationSettings(showUserDefinedSettingStyle = true)
InitialTarget.RoomMemberList -> NavTarget.RoomMemberList
}

View File

@@ -0,0 +1,14 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
sealed interface RoomDetailsAction {
data object Edit : RoomDetailsAction
data object AddTopic : RoomDetailsAction
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
sealed interface RoomDetailsEvent {
data class LeaveRoom(val needsConfirmation: Boolean) : RoomDetailsEvent
data object MuteNotification : RoomDetailsEvent
data object UnmuteNotification : RoomDetailsEvent
data class CopyToClipboard(val text: String) : RoomDetailsEvent
data class SetFavorite(val isFavorite: Boolean) : RoomDetailsEvent
}

View File

@@ -0,0 +1,438 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import android.os.Parcelable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.navmodel.backstack.BackStack
import com.bumble.appyx.navmodel.backstack.operation.pop
import com.bumble.appyx.navmodel.backstack.operation.push
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.annotations.ContributesNode
import io.element.android.appconfig.LearnMoreConfig
import io.element.android.features.call.api.CallType
import io.element.android.features.call.api.ElementCallEntryPoint
import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint
import io.element.android.features.messages.api.MessagesEntryPoint
import io.element.android.features.poll.api.history.PollHistoryEntryPoint
import io.element.android.features.reportroom.api.ReportRoomEntryPoint
import io.element.android.features.rolesandpermissions.api.ChangeRoomMemberRolesEntryPoint
import io.element.android.features.rolesandpermissions.api.ChangeRoomMemberRolesListType
import io.element.android.features.rolesandpermissions.api.RolesAndPermissionsEntryPoint
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
import io.element.android.features.roomdetails.impl.edit.RoomDetailsEditNode
import io.element.android.features.roomdetails.impl.invite.RoomInviteMembersNode
import io.element.android.features.roomdetails.impl.members.RoomMemberListNode
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsNode
import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsNode
import io.element.android.features.securityandprivacy.api.SecurityAndPrivacyEntryPoint
import io.element.android.features.userprofile.shared.UserProfileNodeHelper
import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint
import io.element.android.libraries.architecture.BackstackWithOverlayBox
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.callback
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.overlay.operation.hide
import io.element.android.libraries.architecture.overlay.operation.show
import io.element.android.libraries.designsystem.utils.OpenUrlInTabView
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.verification.VerificationRequest
import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint
import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
@ContributesNode(RoomScope::class)
@AssistedInject
class RoomDetailsFlowNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val pollHistoryEntryPoint: PollHistoryEntryPoint,
private val elementCallEntryPoint: ElementCallEntryPoint,
private val room: JoinedRoom,
private val analyticsService: AnalyticsService,
private val messagesEntryPoint: MessagesEntryPoint,
private val knockRequestsListEntryPoint: KnockRequestsListEntryPoint,
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
private val mediaGalleryEntryPoint: MediaGalleryEntryPoint,
private val outgoingVerificationEntryPoint: OutgoingVerificationEntryPoint,
private val reportRoomEntryPoint: ReportRoomEntryPoint,
private val changeRoomMemberRolesEntryPoint: ChangeRoomMemberRolesEntryPoint,
private val rolesAndPermissionsEntryPoint: RolesAndPermissionsEntryPoint,
private val securityAndPrivacyEntryPoint: SecurityAndPrivacyEntryPoint,
) : BaseFlowNode<RoomDetailsFlowNode.NavTarget>(
backstack = BackStack(
initialElement = plugins.filterIsInstance<RoomDetailsEntryPoint.Params>().first().initialElement.toNavTarget(),
savedStateMap = buildContext.savedStateMap,
),
buildContext = buildContext,
plugins = plugins,
) {
sealed interface NavTarget : Parcelable {
@Parcelize
data object RoomDetails : NavTarget
@Parcelize
data object RoomMemberList : NavTarget
@Parcelize
data object RoomDetailsEdit : NavTarget
@Parcelize
data object InviteMembers : NavTarget
@Parcelize
data class RoomNotificationSettings(
/**
* When presented from outside the context of the room, the rooms settings UI is different.
* Figma designs: https://www.figma.com/file/0MMNu7cTOzLOlWb7ctTkv3/Element-X?type=design&node-id=5199-198932&mode=design&t=fTTvpuxYFjewYQOe-0
*/
val showUserDefinedSettingStyle: Boolean
) : NavTarget
@Parcelize
data class RoomMemberDetails(val roomMemberId: UserId) : NavTarget
@Parcelize
data class AvatarPreview(val name: String, val avatarUrl: String) : NavTarget
@Parcelize
data object PollHistory : NavTarget
@Parcelize
data object MediaGallery : NavTarget
@Parcelize
data object AdminSettings : NavTarget
@Parcelize
data object PinnedMessagesList : NavTarget
@Parcelize
data object KnockRequestsList : NavTarget
@Parcelize
data object SecurityAndPrivacy : NavTarget
@Parcelize
data class VerifyUser(val userId: UserId) : NavTarget
@Parcelize
data object ReportRoom : NavTarget
@Parcelize
data object SelectNewOwnersWhenLeaving : NavTarget
}
private val callback: RoomDetailsEntryPoint.Callback = callback()
override fun onBuilt() {
super.onBuilt()
whenChildrenAttached {
commonLifecycle: Lifecycle,
roomDetailsNode: RoomDetailsNode,
changeRoomMemberRolesNode: ChangeRoomMemberRolesEntryPoint.NodeProxy,
->
commonLifecycle.coroutineScope.launch {
val isNewOwnerSelected = changeRoomMemberRolesNode.waitForCompletion()
withContext(NonCancellable) {
backstack.pop()
if (isNewOwnerSelected) {
roomDetailsNode.onNewOwnersSelected()
}
}
}
}
}
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) {
NavTarget.RoomDetails -> {
val roomDetailsCallback = object : RoomDetailsNode.Callback {
override fun navigateToRoomMemberList() {
backstack.push(NavTarget.RoomMemberList)
}
override fun navigateToRoomDetailsEdit() {
backstack.push(NavTarget.RoomDetailsEdit)
}
override fun navigateToInviteMembers() {
backstack.push(NavTarget.InviteMembers)
}
override fun navigateToRoomNotificationSettings() {
backstack.push(NavTarget.RoomNotificationSettings(showUserDefinedSettingStyle = false))
}
override fun navigateToAvatarPreview(name: String, url: String) {
overlay.show(NavTarget.AvatarPreview(name, url))
}
override fun navigateToPollHistory() {
backstack.push(NavTarget.PollHistory)
}
override fun navigateToMediaGallery() {
backstack.push(NavTarget.MediaGallery)
}
override fun navigateToAdminSettings() {
backstack.push(NavTarget.AdminSettings)
}
override fun navigateToPinnedMessagesList() {
backstack.push(NavTarget.PinnedMessagesList)
}
override fun navigateToKnockRequestsList() {
backstack.push(NavTarget.KnockRequestsList)
}
override fun navigateToSecurityAndPrivacy() {
backstack.push(NavTarget.SecurityAndPrivacy)
}
override fun navigateToRoomMemberDetails(userId: UserId) {
backstack.push(NavTarget.RoomMemberDetails(userId))
}
override fun navigateToRoomCall() {
val inputs = CallType.RoomCall(
sessionId = room.sessionId,
roomId = room.roomId,
)
analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton)
elementCallEntryPoint.startCall(inputs)
}
override fun navigateToReportRoom() {
backstack.push(NavTarget.ReportRoom)
}
override fun navigateToSelectNewOwnersWhenLeaving() {
backstack.push(NavTarget.SelectNewOwnersWhenLeaving)
}
}
createNode<RoomDetailsNode>(buildContext, listOf(roomDetailsCallback))
}
NavTarget.RoomMemberList -> {
val roomMemberListCallback = object : RoomMemberListNode.Callback {
override fun navigateToRoomMemberDetails(roomMemberId: UserId) {
backstack.push(NavTarget.RoomMemberDetails(roomMemberId))
}
override fun navigateToInviteMembers() {
backstack.push(NavTarget.InviteMembers)
}
}
createNode<RoomMemberListNode>(buildContext, listOf(roomMemberListCallback))
}
NavTarget.RoomDetailsEdit -> {
createNode<RoomDetailsEditNode>(buildContext)
}
NavTarget.InviteMembers -> {
createNode<RoomInviteMembersNode>(buildContext)
}
is NavTarget.RoomNotificationSettings -> {
val input = RoomNotificationSettingsNode.RoomNotificationSettingInput(navTarget.showUserDefinedSettingStyle)
val callback = object : RoomNotificationSettingsNode.Callback {
override fun navigateToGlobalNotificationSettings() {
callback.navigateToGlobalNotificationSettings()
}
}
createNode<RoomNotificationSettingsNode>(buildContext, listOf(input, callback))
}
is NavTarget.RoomMemberDetails -> {
val callback = object : UserProfileNodeHelper.Callback {
override fun navigateToAvatarPreview(username: String, avatarUrl: String) {
overlay.show(NavTarget.AvatarPreview(username, avatarUrl))
}
override fun navigateToRoom(roomId: RoomId) {
callback.navigateToRoom(roomId, emptyList())
}
override fun startCall(dmRoomId: RoomId) {
elementCallEntryPoint.startCall(CallType.RoomCall(roomId = dmRoomId, sessionId = room.sessionId))
}
override fun startVerifyUserFlow(userId: UserId) {
backstack.push(NavTarget.VerifyUser(userId))
}
}
val plugins = listOf(RoomMemberDetailsNode.RoomMemberDetailsInput(navTarget.roomMemberId), callback)
createNode<RoomMemberDetailsNode>(buildContext, plugins)
}
is NavTarget.AvatarPreview -> {
val callback = object : MediaViewerEntryPoint.Callback {
override fun onDone() {
overlay.hide()
}
override fun viewInTimeline(eventId: EventId) {
// Cannot happen
}
override fun forwardEvent(eventId: EventId, fromPinnedEvents: Boolean) {
// Cannot happen
}
}
val params = mediaViewerEntryPoint.createParamsForAvatar(
filename = navTarget.name,
avatarUrl = navTarget.avatarUrl,
)
mediaViewerEntryPoint.createNode(
parentNode = this,
buildContext = buildContext,
params = params,
callback = callback,
)
}
is NavTarget.PollHistory -> {
pollHistoryEntryPoint.createNode(this, buildContext)
}
is NavTarget.MediaGallery -> {
val callback = object : MediaGalleryEntryPoint.Callback {
override fun onBackClick() {
backstack.pop()
}
override fun viewInTimeline(eventId: EventId) {
val permalinkData = PermalinkData.RoomLink(
roomIdOrAlias = room.roomId.toRoomIdOrAlias(),
eventId = eventId,
)
callback.handlePermalinkClick(permalinkData, pushToBackstack = false)
}
override fun forward(eventId: EventId, fromPinnedEvents: Boolean) {
callback.startForwardEventFlow(eventId, fromPinnedEvents)
}
}
mediaGalleryEntryPoint.createNode(
parentNode = this,
buildContext = buildContext,
callback = callback,
)
}
is NavTarget.AdminSettings -> {
rolesAndPermissionsEntryPoint.createNode(this, buildContext)
}
NavTarget.PinnedMessagesList -> {
val params = MessagesEntryPoint.Params(
MessagesEntryPoint.InitialTarget.PinnedMessages
)
val callback = object : MessagesEntryPoint.Callback {
override fun navigateToRoomDetails() = Unit
override fun navigateToRoomMemberDetails(userId: UserId) = Unit
override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) {
callback.handlePermalinkClick(data, pushToBackstack)
}
override fun forwardEvent(eventId: EventId, fromPinnedEvents: Boolean) {
callback.startForwardEventFlow(eventId, fromPinnedEvents)
}
override fun navigateToRoom(roomId: RoomId) {
callback.navigateToRoom(roomId, emptyList())
}
}
return messagesEntryPoint.createNode(
parentNode = this,
buildContext = buildContext,
params = params,
callback = callback,
)
}
NavTarget.KnockRequestsList -> {
knockRequestsListEntryPoint.createNode(this, buildContext)
}
NavTarget.SecurityAndPrivacy -> {
securityAndPrivacyEntryPoint.createNode(this, buildContext)
}
is NavTarget.VerifyUser -> {
val params = OutgoingVerificationEntryPoint.Params(
showDeviceVerifiedScreen = true,
verificationRequest = VerificationRequest.Outgoing.User(userId = navTarget.userId)
)
outgoingVerificationEntryPoint.createNode(
parentNode = this,
buildContext = buildContext,
params = params,
callback = object : OutgoingVerificationEntryPoint.Callback {
override fun onDone() {
backstack.pop()
}
override fun onBack() {
backstack.pop()
}
override fun navigateToLearnMoreAboutEncryption() {
learnMoreUrl.value = LearnMoreConfig.ENCRYPTION_URL
}
},
)
}
is NavTarget.ReportRoom -> {
reportRoomEntryPoint.createNode(
parentNode = this,
buildContext = buildContext,
roomId = room.roomId,
)
}
is NavTarget.SelectNewOwnersWhenLeaving -> {
changeRoomMemberRolesEntryPoint.createNode(
parentNode = this,
buildContext = buildContext,
room = room,
listType = ChangeRoomMemberRolesListType.SelectNewOwnersWhenLeaving,
)
}
}
}
private val learnMoreUrl = mutableStateOf<String?>(null)
@Composable
override fun View(modifier: Modifier) {
BackstackWithOverlayBox(modifier)
OpenUrlInTabView(learnMoreUrl)
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.lifecycleScope
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.ContributesNode
import io.element.android.features.leaveroom.api.LeaveRoomRenderer
import io.element.android.libraries.androidutils.system.startSharePlainTextIntent
import io.element.android.libraries.architecture.appyx.launchMolecule
import io.element.android.libraries.architecture.callback
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
import io.element.android.libraries.androidutils.R as AndroidUtilsR
@ContributesNode(RoomScope::class)
@AssistedInject
class RoomDetailsNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val presenter: RoomDetailsPresenter,
private val room: BaseRoom,
private val analyticsService: AnalyticsService,
private val leaveRoomRenderer: LeaveRoomRenderer,
) : Node(buildContext, plugins = plugins) {
interface Callback : Plugin {
fun navigateToRoomMemberList()
fun navigateToInviteMembers()
fun navigateToRoomDetailsEdit()
fun navigateToRoomNotificationSettings()
fun navigateToAvatarPreview(name: String, url: String)
fun navigateToPollHistory()
fun navigateToMediaGallery()
fun navigateToAdminSettings()
fun navigateToPinnedMessagesList()
fun navigateToKnockRequestsList()
fun navigateToSecurityAndPrivacy()
fun navigateToRoomMemberDetails(userId: UserId)
fun navigateToRoomCall()
fun navigateToReportRoom()
fun navigateToSelectNewOwnersWhenLeaving()
}
private val callback: Callback = callback()
init {
lifecycle.subscribe(
onResume = {
analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.RoomDetails))
}
)
}
private fun CoroutineScope.onShareRoom(context: Context) = launch {
room.getPermalink()
.onSuccess { permalink ->
context.startSharePlainTextIntent(
activityResultLauncher = null,
chooserTitle = context.getString(R.string.screen_room_details_share_room_title),
text = permalink,
noActivityFoundMessage = context.getString(AndroidUtilsR.string.error_no_compatible_app_found)
)
}
.onFailure {
Timber.e(it)
}
}
private val stateFlow = launchMolecule { presenter.present() }
fun onNewOwnersSelected() {
stateFlow.value.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = false))
}
@Composable
override fun View(modifier: Modifier) {
val context = LocalContext.current
val state by stateFlow.collectAsState()
fun onShareRoom() {
lifecycleScope.onShareRoom(context)
}
fun onActionClick(action: RoomDetailsAction) {
when (action) {
RoomDetailsAction.Edit -> {
callback.navigateToRoomDetailsEdit()
}
RoomDetailsAction.AddTopic -> {
callback.navigateToRoomDetailsEdit()
}
}
}
RoomDetailsView(
state = state,
modifier = modifier,
goBack = ::navigateUp,
onActionClick = ::onActionClick,
onShareRoom = ::onShareRoom,
openRoomMemberList = callback::navigateToRoomMemberList,
openRoomNotificationSettings = callback::navigateToRoomNotificationSettings,
invitePeople = callback::navigateToInviteMembers,
openAvatarPreview = callback::navigateToAvatarPreview,
openPollHistory = callback::navigateToPollHistory,
openMediaGallery = callback::navigateToMediaGallery,
openAdminSettings = callback::navigateToAdminSettings,
onJoinCallClick = callback::navigateToRoomCall,
onPinnedMessagesClick = callback::navigateToPinnedMessagesList,
onKnockRequestsClick = callback::navigateToKnockRequestsList,
onSecurityAndPrivacyClick = callback::navigateToSecurityAndPrivacy,
onProfileClick = callback::navigateToRoomMemberDetails,
onReportRoomClick = callback::navigateToReportRoom,
leaveRoomView = {
leaveRoomRenderer.Render(
state = state.leaveRoomState,
onSelectNewOwners = { callback.navigateToSelectNewOwnersWhenLeaving() },
modifier = Modifier
)
}
)
}
}

View File

@@ -0,0 +1,257 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import dev.zacsweers.metro.Inject
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.features.securityandprivacy.api.securityAndPrivacyPermissionsAsState
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
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.RoomMembersState
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
import io.element.android.libraries.matrix.ui.room.canHandleKnockRequestsAsState
import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember
import io.element.android.libraries.matrix.ui.room.getDirectRoomMember
import io.element.android.libraries.matrix.ui.room.isDmAsState
import io.element.android.libraries.matrix.ui.room.isOwnUserAdmin
import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@Inject
class RoomDetailsPresenter(
private val client: MatrixClient,
private val room: JoinedRoom,
private val featureFlagService: FeatureFlagService,
private val notificationSettingsService: NotificationSettingsService,
private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory,
private val leaveRoomPresenter: Presenter<LeaveRoomState>,
private val roomCallStatePresenter: Presenter<RoomCallState>,
private val dispatchers: CoroutineDispatchers,
private val analyticsService: AnalyticsService,
private val clipboardHelper: ClipboardHelper,
private val appPreferencesStore: AppPreferencesStore,
) : Presenter<RoomDetailsState> {
@Composable
override fun present(): RoomDetailsState {
val scope = rememberCoroutineScope()
val leaveRoomState = leaveRoomPresenter.present()
val roomInfo by room.roomInfoFlow.collectAsState()
val isUserAdmin = room.isOwnUserAdmin()
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
val roomAvatar by remember { derivedStateOf { roomInfo.avatarUrl } }
val roomName by remember { derivedStateOf { roomInfo.name?.trim().orEmpty() } }
val roomTopic by remember { derivedStateOf { roomInfo.topic } }
val isFavorite by remember { derivedStateOf { roomInfo.isFavorite } }
val joinRule by remember { derivedStateOf { roomInfo.joinRule } }
val pinnedMessagesCount by remember { derivedStateOf { roomInfo.pinnedEventIds.size } }
LaunchedEffect(Unit) {
room.updateRoomNotificationSettings()
observeNotificationSettings()
}
val membersState by room.membersStateFlow.collectAsState()
val canInvite by getCanInvite(membersState)
val canonicalAlias by remember { derivedStateOf { roomInfo.canonicalAlias } }
val isEncrypted by remember { derivedStateOf { roomInfo.isEncrypted == true } }
val isDm by room.isDmAsState()
val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME)
val canEditAvatar by getCanSendState(membersState, StateEventType.ROOM_AVATAR)
val canEditTopic by getCanSendState(membersState, StateEventType.ROOM_TOPIC)
val dmMember by room.getDirectRoomMember(membersState)
val currentMember by room.getCurrentRoomMember(membersState)
val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember)
val roomType = getRoomType(dmMember, currentMember)
val roomCallState = roomCallStatePresenter.present()
val joinedMemberCount by remember { derivedStateOf { roomInfo.joinedMembersCount } }
val topicState = remember(canEditTopic, roomTopic, roomType) {
val topic = roomTopic
when {
!topic.isNullOrBlank() -> RoomTopicState.ExistingTopic(topic)
canEditTopic && roomType is RoomDetailsType.Room -> RoomTopicState.CanAddTopic
else -> RoomTopicState.Hidden
}
}
val canHandleKnockRequests by room.canHandleKnockRequestsAsState(syncUpdateFlow.value)
val isKnockRequestsEnabled by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock)
}.collectAsState(false)
val knockRequestsCount by produceState<Int?>(null) {
room.knockRequestsFlow.collect { value = it.size }
}
val canShowKnockRequests by remember {
derivedStateOf { isKnockRequestsEnabled && canHandleKnockRequests && joinRule == JoinRule.Knock }
}
val isDeveloperModeEnabled by remember {
appPreferencesStore.isDeveloperModeEnabledFlow()
}.collectAsState(initial = false)
val roomNotificationSettingsState by room.roomNotificationSettingsStateFlow.collectAsState()
val snackbarDispatcher = LocalSnackbarDispatcher.current
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
fun handleEvent(event: RoomDetailsEvent) {
when (event) {
is RoomDetailsEvent.LeaveRoom -> {
leaveRoomState.eventSink(LeaveRoomEvent.LeaveRoom(room.roomId, needsConfirmation = event.needsConfirmation))
}
RoomDetailsEvent.MuteNotification -> {
scope.launch(dispatchers.io) {
notificationSettingsService.muteRoom(room.roomId)
}
}
RoomDetailsEvent.UnmuteNotification -> {
scope.launch(dispatchers.io) {
notificationSettingsService.unmuteRoom(room.roomId, isEncrypted, room.isOneToOne)
}
}
is RoomDetailsEvent.SetFavorite -> scope.setFavorite(event.isFavorite)
is RoomDetailsEvent.CopyToClipboard -> {
clipboardHelper.copyPlainText(event.text)
snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_copied_to_clipboard))
}
}
}
val roomMemberDetailsState = roomMemberDetailsPresenter?.present()
val securityAndPrivacyPermissions = room.securityAndPrivacyPermissionsAsState(syncUpdateFlow.value)
val canShowSecurityAndPrivacy by remember {
derivedStateOf {
roomType is RoomDetailsType.Room && securityAndPrivacyPermissions.value.hasAny
}
}
val hasMemberVerificationViolations by produceState(false) {
room.roomMemberIdentityStateChange(waitForEncryption = true)
.onEach { identities -> value = identities.any { it.identityState == IdentityState.VerificationViolation } }
.launchIn(this)
}
val canReportRoom by produceState(false) { value = client.canReportRoom() }
return RoomDetailsState(
roomId = room.roomId,
roomName = roomName,
roomAlias = canonicalAlias,
roomAvatarUrl = roomAvatar,
roomTopic = topicState,
memberCount = joinedMemberCount,
isEncrypted = isEncrypted,
canInvite = canInvite,
canEdit = (canEditAvatar || canEditName || canEditTopic) && roomType == RoomDetailsType.Room,
roomCallState = roomCallState,
roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState,
leaveRoomState = leaveRoomState,
roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(),
isFavorite = isFavorite,
displayRolesAndPermissionsSettings = !isDm && isUserAdmin,
isPublic = joinRule == JoinRule.Public,
heroes = roomInfo.heroes.toImmutableList(),
pinnedMessagesCount = pinnedMessagesCount,
snackbarMessage = snackbarMessage,
canShowKnockRequests = canShowKnockRequests,
knockRequestsCount = knockRequestsCount,
canShowSecurityAndPrivacy = canShowSecurityAndPrivacy,
hasMemberVerificationViolations = hasMemberVerificationViolations,
canReportRoom = canReportRoom,
isTombstoned = roomInfo.successorRoom != null,
showDebugInfo = isDeveloperModeEnabled,
roomVersion = roomInfo.roomVersion,
eventSink = ::handleEvent,
)
}
@Composable
private fun roomMemberDetailsPresenter(dmMemberState: RoomMember?) = remember(dmMemberState) {
dmMemberState?.let { roomMember ->
roomMembersDetailsPresenterFactory.create(roomMember.userId)
}
}
@Composable
private fun getRoomType(
dmMember: RoomMember?,
currentMember: RoomMember?,
): RoomDetailsType = remember(dmMember, currentMember) {
if (dmMember != null && currentMember != null) {
RoomDetailsType.Dm(
me = currentMember,
otherMember = dmMember,
)
} else {
RoomDetailsType.Room
}
}
@Composable
private fun getCanInvite(membersState: RoomMembersState) = produceState(false, membersState) {
value = room.canInvite().getOrElse { false }
}
@Composable
private fun getCanSendState(membersState: RoomMembersState, type: StateEventType) = produceState(false, membersState) {
value = room.canSendState(type).getOrElse { false }
}
private fun CoroutineScope.observeNotificationSettings() {
notificationSettingsService.notificationSettingsChangeFlow.onEach {
room.updateRoomNotificationSettings()
}.launchIn(this)
}
private fun CoroutineScope.setFavorite(isFavorite: Boolean) = launch {
room.setIsFavorite(isFavorite)
.onSuccess {
analyticsService.captureInteraction(Interaction.Name.MobileRoomFavouriteToggle)
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import androidx.compose.runtime.Immutable
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.userprofile.api.UserProfileState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
data class RoomDetailsState(
val roomId: RoomId,
val roomName: String,
val roomAlias: RoomAlias?,
val roomAvatarUrl: String?,
val roomTopic: RoomTopicState,
val memberCount: Long,
val isEncrypted: Boolean,
val roomType: RoomDetailsType,
val roomMemberDetailsState: UserProfileState?,
val canEdit: Boolean,
val canInvite: Boolean,
val roomCallState: RoomCallState,
val leaveRoomState: LeaveRoomState,
val roomNotificationSettings: RoomNotificationSettings?,
val isFavorite: Boolean,
val displayRolesAndPermissionsSettings: Boolean,
val isPublic: Boolean,
val heroes: ImmutableList<MatrixUser>,
val pinnedMessagesCount: Int?,
val snackbarMessage: SnackbarMessage?,
val canShowKnockRequests: Boolean,
val knockRequestsCount: Int?,
val canShowSecurityAndPrivacy: Boolean,
val hasMemberVerificationViolations: Boolean,
val canReportRoom: Boolean,
val isTombstoned: Boolean,
val showDebugInfo: Boolean,
val roomVersion: String?,
val eventSink: (RoomDetailsEvent) -> Unit
) {
val roomBadges = buildList {
if (isEncrypted) {
add(RoomBadge.ENCRYPTED)
} else {
add(RoomBadge.NOT_ENCRYPTED)
}
if (isPublic) {
add(RoomBadge.PUBLIC)
}
}.toImmutableList()
}
@Immutable
sealed interface RoomDetailsType {
data object Room : RoomDetailsType
data class Dm(
val me: RoomMember,
val otherMember: RoomMember,
) : RoomDetailsType
}
@Immutable
sealed interface RoomTopicState {
data object Hidden : RoomTopicState
data object CanAddTopic : RoomTopicState
data class ExistingTopic(val topic: String) : RoomTopicState
}
enum class RoomBadge {
ENCRYPTED,
NOT_ENCRYPTED,
PUBLIC,
}

View File

@@ -0,0 +1,184 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.roomcall.api.aStandByCallState
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.userprofile.api.UserProfileState
import io.element.android.features.userprofile.api.UserProfileVerificationState
import io.element.android.features.userprofile.shared.aUserProfileState
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
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 io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
import kotlinx.collections.immutable.toImmutableList
open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState> {
override val values: Sequence<RoomDetailsState>
get() = sequenceOf(
aRoomDetailsState(displayAdminSettings = true),
aRoomDetailsState(roomTopic = RoomTopicState.Hidden, showDebugInfo = true),
aRoomDetailsState(roomTopic = RoomTopicState.CanAddTopic),
aRoomDetailsState(isEncrypted = false),
aRoomDetailsState(roomAlias = null),
aDmRoomDetailsState(),
aDmRoomDetailsState(isDmMemberIgnored = true, roomName = "Daniel (ignored and clear)", isEncrypted = false),
aRoomDetailsState(canInvite = true),
aRoomDetailsState(isFavorite = true),
aRoomDetailsState(
canEdit = true,
// Also test the roomNotificationSettings ALL_MESSAGES in the same screenshot. Icon 'Mute' should be displayed
roomNotificationSettings = aRoomNotificationSettings(mode = RoomNotificationMode.ALL_MESSAGES, isDefault = true)
),
aRoomDetailsState(roomCallState = aStandByCallState(false), canInvite = false),
aRoomDetailsState(isPublic = false),
aRoomDetailsState(heroes = aMatrixUserList()),
aRoomDetailsState(pinnedMessagesCount = 3),
aRoomDetailsState(knockRequestsCount = null, canShowKnockRequests = true),
aRoomDetailsState(knockRequestsCount = 4, canShowKnockRequests = true),
aRoomDetailsState(hasMemberVerificationViolations = true),
aRoomDetailsState(isTombstoned = true),
aDmRoomDetailsState(dmRoomMemberVerificationState = UserProfileVerificationState.VERIFIED),
aDmRoomDetailsState(dmRoomMemberVerificationState = UserProfileVerificationState.VERIFICATION_VIOLATION),
// Add other state here
)
}
fun aDmRoomMember(
userId: UserId = UserId("@daniel:domain.com"),
displayName: String? = "Daniel",
avatarUrl: String? = null,
membership: RoomMembershipState = RoomMembershipState.JOIN,
isNameAmbiguous: Boolean = false,
powerLevel: Long = 0,
isIgnored: Boolean = false,
role: RoomMember.Role = RoomMember.Role.User,
membershipChangeReason: String? = null,
) = RoomMember(
userId = userId,
displayName = displayName,
avatarUrl = avatarUrl,
membership = membership,
isNameAmbiguous = isNameAmbiguous,
powerLevel = powerLevel,
isIgnored = isIgnored,
role = role,
membershipChangeReason = membershipChangeReason
)
fun aRoomDetailsState(
roomId: RoomId = RoomId("!aRoomId:domain.com"),
roomName: String = "Marketing",
roomAlias: RoomAlias? = RoomAlias("#marketing:domain.com"),
roomAvatarUrl: String? = null,
roomTopic: RoomTopicState = RoomTopicState.ExistingTopic(
"Welcome to #marketing, home of the Marketing team " +
"|| WIKI PAGE: https://domain.org/wiki/Marketing " +
"|| MAIL iki/Marketing " +
"|| MAI iki/Marketing " +
"|| MAI iki/Marketing..."
),
memberCount: Long = 32,
isEncrypted: Boolean = true,
canInvite: Boolean = false,
canEdit: Boolean = false,
roomCallState: RoomCallState = aStandByCallState(),
roomType: RoomDetailsType = RoomDetailsType.Room,
roomMemberDetailsState: UserProfileState? = null,
leaveRoomState: LeaveRoomState = aLeaveRoomState(),
roomNotificationSettings: RoomNotificationSettings = aRoomNotificationSettings(),
isFavorite: Boolean = false,
displayAdminSettings: Boolean = false,
isPublic: Boolean = true,
heroes: List<MatrixUser> = emptyList(),
pinnedMessagesCount: Int? = null,
snackbarMessage: SnackbarMessage? = null,
canShowKnockRequests: Boolean = false,
knockRequestsCount: Int? = null,
canShowSecurityAndPrivacy: Boolean = true,
hasMemberVerificationViolations: Boolean = false,
canReportRoom: Boolean = true,
isTombstoned: Boolean = false,
showDebugInfo: Boolean = false,
eventSink: (RoomDetailsEvent) -> Unit = {},
) = RoomDetailsState(
roomId = roomId,
roomName = roomName,
roomAlias = roomAlias,
roomAvatarUrl = roomAvatarUrl,
roomTopic = roomTopic,
memberCount = memberCount,
isEncrypted = isEncrypted,
canInvite = canInvite,
canEdit = canEdit,
roomCallState = roomCallState,
roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState,
leaveRoomState = leaveRoomState,
roomNotificationSettings = roomNotificationSettings,
isFavorite = isFavorite,
displayRolesAndPermissionsSettings = displayAdminSettings,
isPublic = isPublic,
heroes = heroes.toImmutableList(),
pinnedMessagesCount = pinnedMessagesCount,
snackbarMessage = snackbarMessage,
canShowKnockRequests = canShowKnockRequests,
knockRequestsCount = knockRequestsCount,
canShowSecurityAndPrivacy = canShowSecurityAndPrivacy,
hasMemberVerificationViolations = hasMemberVerificationViolations,
canReportRoom = canReportRoom,
isTombstoned = isTombstoned,
showDebugInfo = showDebugInfo,
roomVersion = "12",
eventSink = eventSink,
)
internal fun aLeaveRoomState(
eventSink: (LeaveRoomEvent) -> Unit = {}
) = object : LeaveRoomState {
override val eventSink: (LeaveRoomEvent) -> Unit = eventSink
}
fun aRoomNotificationSettings(
mode: RoomNotificationMode = RoomNotificationMode.MUTE,
isDefault: Boolean = false,
) = RoomNotificationSettings(
mode = mode,
isDefault = isDefault
)
fun aDmRoomDetailsState(
isDmMemberIgnored: Boolean = false,
roomName: String = "Daniel",
isEncrypted: Boolean = true,
dmRoomMemberVerificationState: UserProfileVerificationState = UserProfileVerificationState.UNKNOWN,
) = aRoomDetailsState(
roomName = roomName,
isPublic = false,
isEncrypted = isEncrypted,
roomType = RoomDetailsType.Dm(
me = aRoomMember(),
otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored),
),
roomMemberDetailsState = aUserProfileState(
isBlocked = AsyncData.Success(isDmMemberIgnored),
verificationState = dmRoomMemberVerificationState,
)
)

View File

@@ -0,0 +1,793 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.roomcall.api.hasPermissionToJoin
import io.element.android.features.userprofile.api.UserProfileVerificationState
import io.element.android.features.userprofile.shared.blockuser.BlockUserDialogs
import io.element.android.features.userprofile.shared.blockuser.BlockUserSection
import io.element.android.libraries.androidutils.system.copyToClipboard
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
import io.element.android.libraries.designsystem.atomic.atoms.MatrixBadgeAtom
import io.element.android.libraries.designsystem.atomic.molecules.MatrixBadgeRowMolecule
import io.element.android.libraries.designsystem.components.ClickableLinkText
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.components.avatar.DmAvatars
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.button.MainActionButton
import io.element.android.libraries.designsystem.components.list.ListItemContent
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
import io.element.android.libraries.designsystem.modifiers.niceClickable
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.IconSource
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.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
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.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.getBestName
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.analytics.compose.LocalAnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Composable
fun RoomDetailsView(
state: RoomDetailsState,
goBack: () -> Unit,
onActionClick: (RoomDetailsAction) -> Unit,
onShareRoom: () -> Unit,
openRoomMemberList: () -> Unit,
openRoomNotificationSettings: () -> Unit,
invitePeople: () -> Unit,
openAvatarPreview: (name: String, url: String) -> Unit,
openPollHistory: () -> Unit,
openMediaGallery: () -> Unit,
openAdminSettings: () -> Unit,
onJoinCallClick: () -> Unit,
onPinnedMessagesClick: () -> Unit,
onKnockRequestsClick: () -> Unit,
onSecurityAndPrivacyClick: () -> Unit,
onProfileClick: (UserId) -> Unit,
onReportRoomClick: () -> Unit,
modifier: Modifier = Modifier,
leaveRoomView: @Composable () -> Unit,
) {
val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage)
Scaffold(
modifier = modifier,
topBar = {
RoomDetailsTopBar(
goBack = goBack,
showEdit = state.canEdit,
onActionClick = onActionClick
)
},
snackbarHost = { SnackbarHost(snackbarHostState) },
) { padding ->
Column(
modifier = Modifier
.padding(padding)
.verticalScroll(rememberScrollState())
.consumeWindowInsets(padding)
) {
leaveRoomView()
when (state.roomType) {
RoomDetailsType.Room -> {
RoomHeaderSection(
avatarUrl = state.roomAvatarUrl,
roomId = state.roomId,
roomName = state.roomName,
roomAlias = state.roomAlias,
heroes = state.heroes,
isTombstoned = state.isTombstoned,
openAvatarPreview = { avatarUrl ->
openAvatarPreview(state.roomName, avatarUrl)
},
onSubtitleClick = { subtitle ->
state.eventSink(RoomDetailsEvent.CopyToClipboard(subtitle))
}
)
}
is RoomDetailsType.Dm -> {
DmHeaderSection(
me = state.roomType.me,
otherMember = state.roomType.otherMember,
roomName = state.roomName,
openAvatarPreview = { name, avatarUrl ->
openAvatarPreview(name, avatarUrl)
},
onSubtitleClick = { subtitle ->
state.eventSink(RoomDetailsEvent.CopyToClipboard(subtitle))
}
)
}
}
BadgeList(
roomBadge = state.roomBadges,
modifier = Modifier.align(Alignment.CenterHorizontally),
)
Spacer(Modifier.height(32.dp))
MainActionsSection(
state = state,
onShareRoom = onShareRoom,
onInvitePeople = invitePeople,
onCall = onJoinCallClick,
)
Spacer(Modifier.height(12.dp))
if (state.roomTopic !is RoomTopicState.Hidden) {
TopicSection(
roomTopic = state.roomTopic,
onActionClick = onActionClick,
)
}
PreferenceCategory {
if (state.roomNotificationSettings != null) {
NotificationItem(
isDefaultMode = state.roomNotificationSettings.isDefault,
openRoomNotificationSettings = openRoomNotificationSettings
)
}
FavoriteItem(
isFavorite = state.isFavorite,
onFavoriteChanges = {
state.eventSink(RoomDetailsEvent.SetFavorite(it))
}
)
if (state.canShowSecurityAndPrivacy) {
SecurityAndPrivacyItem(
onClick = onSecurityAndPrivacyClick
)
}
state.roomMemberDetailsState?.let { dmMemberDetails ->
ProfileItem(
verificationState = dmMemberDetails.verificationState,
onClick = { onProfileClick(dmMemberDetails.userId) }
)
}
}
if (state.roomType is RoomDetailsType.Room) {
PreferenceCategory {
MembersItem(
memberCount = state.memberCount,
hasVerificationViolations = state.hasMemberVerificationViolations,
openRoomMemberList = openRoomMemberList,
)
if (state.canShowKnockRequests) {
KnockRequestsItem(
knockRequestsCount = state.knockRequestsCount,
onKnockRequestsClick = onKnockRequestsClick
)
}
if (state.displayRolesAndPermissionsSettings) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_roles_and_permissions)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())),
onClick = openAdminSettings,
)
}
}
}
PreferenceCategory {
PinnedMessagesItem(
pinnedMessagesCount = state.pinnedMessagesCount,
onPinnedMessagesClick = onPinnedMessagesClick
)
PollsItem(
openPollHistory = openPollHistory
)
MediaGalleryItem(
onClick = openMediaGallery
)
}
if (state.roomType is RoomDetailsType.Dm && state.roomMemberDetailsState != null) {
val roomMemberState = state.roomMemberDetailsState
BlockUserSection(roomMemberState)
BlockUserDialogs(roomMemberState)
}
OtherActionsSection(
canReportRoom = state.canReportRoom,
onReportRoomClick = onReportRoomClick,
onLeaveRoomClick = { state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true)) }
)
if (state.showDebugInfo) {
DebugInfoSection(
roomId = state.roomId,
roomVersion = state.roomVersion,
)
}
}
}
}
@Composable
private fun KnockRequestsItem(knockRequestsCount: Int?, onKnockRequestsClick: () -> Unit) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_requests_to_join_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.AskToJoin())),
trailingContent = if (knockRequestsCount == null || knockRequestsCount == 0) {
null
} else {
ListItemContent.Counter(knockRequestsCount)
},
onClick = onKnockRequestsClick,
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun RoomDetailsTopBar(
goBack: () -> Unit,
onActionClick: (RoomDetailsAction) -> Unit,
showEdit: Boolean,
) {
var showMenu by remember { mutableStateOf(false) }
TopAppBar(
title = { },
navigationIcon = { BackButton(onClick = goBack) },
actions = {
if (showEdit) {
IconButton(onClick = { showMenu = !showMenu }) {
Icon(CompoundIcons.OverflowVertical(), stringResource(id = CommonStrings.a11y_user_menu))
}
DropdownMenu(
expanded = showMenu,
onDismissRequest = { showMenu = false },
) {
DropdownMenuItem(
text = { Text(stringResource(id = CommonStrings.action_edit)) },
onClick = {
// Explicitly close the menu before handling the action, as otherwise it stays open during the
// transition and renders really badly.
showMenu = false
onActionClick(RoomDetailsAction.Edit)
},
)
}
}
},
)
}
@Composable
private fun MainActionsSection(
state: RoomDetailsState,
onShareRoom: () -> Unit,
onInvitePeople: () -> Unit,
onCall: () -> Unit,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
) {
state.roomNotificationSettings?.let { roomNotificationSettings ->
if (roomNotificationSettings.mode == RoomNotificationMode.MUTE) {
MainActionButton(
title = stringResource(CommonStrings.common_unmute),
imageVector = CompoundIcons.NotificationsOff(),
onClick = {
state.eventSink(RoomDetailsEvent.UnmuteNotification)
},
)
} else {
MainActionButton(
title = stringResource(CommonStrings.common_mute),
imageVector = CompoundIcons.Notifications(),
onClick = {
state.eventSink(RoomDetailsEvent.MuteNotification)
},
)
}
}
if (state.roomCallState.hasPermissionToJoin()) {
// TODO Improve the view depending on all the cases here?
MainActionButton(
title = stringResource(CommonStrings.action_call),
imageVector = CompoundIcons.VideoCall(),
onClick = onCall,
)
}
if (state.roomType is RoomDetailsType.Room) {
if (state.canInvite) {
MainActionButton(
title = stringResource(CommonStrings.action_invite),
imageVector = CompoundIcons.UserAdd(),
onClick = onInvitePeople,
)
}
// Share CTA should be hidden for DMs
MainActionButton(
title = stringResource(CommonStrings.action_share),
imageVector = CompoundIcons.ShareAndroid(),
onClick = onShareRoom
)
}
}
}
@Composable
private fun RoomHeaderSection(
avatarUrl: String?,
roomId: RoomId,
roomName: String,
roomAlias: RoomAlias?,
heroes: ImmutableList<MatrixUser>,
isTombstoned: Boolean,
openAvatarPreview: (url: String) -> Unit,
onSubtitleClick: (String) -> Unit,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Avatar(
avatarData = AvatarData(roomId.value, roomName, avatarUrl, AvatarSize.RoomDetailsHeader),
avatarType = AvatarType.Room(
heroes = heroes.map { user ->
user.getAvatarData(size = AvatarSize.RoomDetailsHeader)
}.toImmutableList(),
isTombstoned = isTombstoned,
),
contentDescription = avatarUrl?.let { stringResource(CommonStrings.a11y_room_avatar) },
modifier = Modifier
.clickable(
enabled = avatarUrl != null,
onClickLabel = stringResource(CommonStrings.action_view),
) {
openAvatarPreview(avatarUrl!!)
}
.testTag(TestTags.roomDetailAvatar)
)
TitleAndSubtitle(
title = roomName,
subtitle = roomAlias?.value,
onSubtitleClick = onSubtitleClick,
)
}
}
@Composable
private fun DmHeaderSection(
me: RoomMember,
otherMember: RoomMember,
roomName: String,
openAvatarPreview: (name: String, url: String) -> Unit,
onSubtitleClick: (String) -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
DmAvatars(
userAvatarData = me.getAvatarData(size = AvatarSize.DmCluster),
otherUserAvatarData = otherMember.getAvatarData(size = AvatarSize.DmCluster),
openAvatarPreview = { url -> openAvatarPreview(me.getBestName(), url) },
openOtherAvatarPreview = { url -> openAvatarPreview(roomName, url) },
)
TitleAndSubtitle(
title = roomName,
subtitle = otherMember.userId.value,
onSubtitleClick = onSubtitleClick,
)
}
}
@Composable
private fun TitleAndSubtitle(
title: String,
subtitle: String?,
onSubtitleClick: (String) -> Unit,
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Spacer(modifier = Modifier.height(24.dp))
Text(
text = title,
style = ElementTheme.typography.fontHeadingLgBold,
textAlign = TextAlign.Center,
)
if (subtitle != null) {
Spacer(modifier = Modifier.height(6.dp))
Text(
modifier = Modifier.niceClickable { onSubtitleClick(subtitle) },
text = subtitle,
style = ElementTheme.typography.fontBodyLgRegular,
color = ElementTheme.colors.textSecondary,
textAlign = TextAlign.Center,
)
}
}
}
@Composable
private fun BadgeList(
roomBadge: ImmutableList<RoomBadge>,
modifier: Modifier = Modifier,
) {
Box(modifier = modifier) {
if (roomBadge.isNotEmpty()) {
MatrixBadgeRowMolecule(
data = roomBadge.map {
it.toMatrixBadgeData()
}.toImmutableList(),
)
}
}
}
@Composable
private fun RoomBadge.toMatrixBadgeData(): MatrixBadgeAtom.MatrixBadgeData {
return when (this) {
RoomBadge.ENCRYPTED -> {
MatrixBadgeAtom.MatrixBadgeData(
text = stringResource(R.string.screen_room_details_badge_encrypted),
icon = CompoundIcons.LockSolid(),
type = MatrixBadgeAtom.Type.Positive,
)
}
RoomBadge.NOT_ENCRYPTED -> {
MatrixBadgeAtom.MatrixBadgeData(
text = stringResource(R.string.screen_room_details_badge_not_encrypted),
icon = CompoundIcons.LockOff(),
type = MatrixBadgeAtom.Type.Info,
)
}
RoomBadge.PUBLIC -> {
MatrixBadgeAtom.MatrixBadgeData(
text = stringResource(R.string.screen_room_details_badge_public),
icon = CompoundIcons.Public(),
type = MatrixBadgeAtom.Type.Info,
)
}
}
}
@Composable
private fun TopicSection(
roomTopic: RoomTopicState,
onActionClick: (RoomDetailsAction) -> Unit,
) {
PreferenceCategory(
title = stringResource(CommonStrings.common_topic),
showTopDivider = false,
) {
if (roomTopic is RoomTopicState.CanAddTopic) {
ListItem(
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Plus())),
headlineContent = {
Text(stringResource(id = R.string.screen_room_details_add_topic_title))
},
onClick = {
onActionClick(RoomDetailsAction.AddTopic)
},
)
} else if (roomTopic is RoomTopicState.ExistingTopic) {
ClickableLinkText(
text = roomTopic.topic,
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp),
interactionSource = remember { MutableInteractionSource() },
style = MaterialTheme.typography.bodyMedium.copy(
color = MaterialTheme.colorScheme.tertiary,
),
)
}
}
}
@Composable
private fun NotificationItem(
isDefaultMode: Boolean,
openRoomNotificationSettings: () -> Unit,
) {
val subtitle = if (isDefaultMode) {
stringResource(R.string.screen_room_details_notification_mode_default)
} else {
stringResource(R.string.screen_room_details_notification_mode_custom)
}
ListItem(
headlineContent = { Text(text = stringResource(R.string.screen_room_details_notification_title)) },
supportingContent = { Text(text = subtitle) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Notifications())),
onClick = openRoomNotificationSettings,
)
}
@Composable
private fun SecurityAndPrivacyItem(
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_security_and_privacy_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())),
onClick = onClick,
modifier = modifier,
)
}
@Composable
private fun FavoriteItem(
isFavorite: Boolean,
onFavoriteChanges: (Boolean) -> Unit,
) {
PreferenceSwitch(
icon = CompoundIcons.Favourite(),
title = stringResource(id = CommonStrings.common_favourite),
isChecked = isFavorite,
onCheckedChange = onFavoriteChanges
)
}
@Composable
private fun ProfileItem(
verificationState: UserProfileVerificationState,
onClick: () -> Unit,
) {
ListItem(
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())),
headlineContent = { Text(stringResource(id = R.string.screen_room_details_profile_row_title)) },
trailingContent = when (verificationState) {
UserProfileVerificationState.VERIFIED -> ListItemContent.Icon(
iconSource = IconSource.Vector(CompoundIcons.Verified()),
tintColor = ElementTheme.colors.iconSuccessPrimary,
)
UserProfileVerificationState.VERIFICATION_VIOLATION -> ListItemContent.Icon(
iconSource = IconSource.Vector(CompoundIcons.ErrorSolid()),
tintColor = ElementTheme.colors.iconCriticalPrimary,
)
else -> null
},
onClick = onClick,
)
}
@Composable
private fun MembersItem(
memberCount: Long,
hasVerificationViolations: Boolean,
openRoomMemberList: () -> Unit,
) {
ListItem(
headlineContent = { Text(stringResource(CommonStrings.common_people)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.User())),
trailingContent = if (hasVerificationViolations) {
ListItemContent.Icon(
iconSource = IconSource.Vector(CompoundIcons.ErrorSolid()),
tintColor = ElementTheme.colors.textCriticalPrimary,
)
} else {
ListItemContent.Text(memberCount.toString())
},
onClick = openRoomMemberList,
)
}
@Composable
private fun PinnedMessagesItem(
pinnedMessagesCount: Int?,
onPinnedMessagesClick: () -> Unit,
) {
val analyticsService = LocalAnalyticsService.current
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_pinned_events_row_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Pin())),
trailingContent =
if (pinnedMessagesCount == null) {
ListItemContent.Custom {
CircularProgressIndicator(strokeWidth = 2.dp, modifier = Modifier.size(24.dp))
}
} else {
ListItemContent.Text(pinnedMessagesCount.toString())
},
onClick = {
analyticsService.captureInteraction(Interaction.Name.PinnedMessageRoomInfoButton)
onPinnedMessagesClick()
}
)
}
@Composable
private fun PollsItem(
openPollHistory: () -> Unit,
) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_polls_history_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Polls())),
onClick = openPollHistory,
)
}
@Composable
private fun MediaGalleryItem(
onClick: () -> Unit,
) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_media_gallery_title)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Image())),
onClick = onClick,
)
}
@Composable
private fun OtherActionsSection(
canReportRoom: Boolean,
onReportRoomClick: () -> Unit,
onLeaveRoomClick: () -> Unit,
) {
PreferenceCategory(showTopDivider = true) {
if (canReportRoom) {
ListItem(
headlineContent = {
Text(stringResource(CommonStrings.action_report_room))
},
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChatProblem())),
style = ListItemStyle.Destructive,
onClick = onReportRoomClick,
)
}
ListItem(
headlineContent = {
Text(stringResource(CommonStrings.action_leave_room))
},
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Leave())),
style = ListItemStyle.Destructive,
onClick = onLeaveRoomClick,
)
}
}
@Composable
private fun DebugInfoSection(
roomId: RoomId,
roomVersion: String?,
) {
val context = LocalContext.current
PreferenceCategory(showTopDivider = true) {
ListItem(
headlineContent = {
Text("Internal room ID")
},
supportingContent = {
Text(
text = roomId.value,
style = ElementTheme.typography.fontBodySmRegular,
color = ElementTheme.colors.textSecondary,
)
},
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Code())),
trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Copy())),
onClick = {
context.copyToClipboard(
roomId.value,
context.getString(CommonStrings.common_copied_to_clipboard)
)
},
)
ListItem(
headlineContent = {
Text("Room version")
},
supportingContent = {
Text(
text = roomVersion ?: "Unknown",
style = ElementTheme.typography.fontBodySmRegular,
color = ElementTheme.colors.textSecondary,
)
},
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Info())),
)
}
}
@PreviewWithLargeHeight
@Composable
internal fun RoomDetailsPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
ElementPreviewLight { ContentToPreview(state) }
@PreviewWithLargeHeight
@Composable
internal fun RoomDetailsDarkPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
ElementPreviewDark { ContentToPreview(state) }
@ExcludeFromCoverage
@Composable
private fun ContentToPreview(state: RoomDetailsState) {
RoomDetailsView(
state = state,
goBack = {},
onActionClick = {},
onShareRoom = {},
openRoomMemberList = {},
openRoomNotificationSettings = {},
invitePeople = {},
openAvatarPreview = { _, _ -> },
openPollHistory = {},
openMediaGallery = {},
openAdminSettings = {},
onJoinCallClick = {},
onPinnedMessagesClick = {},
onKnockRequestsClick = {},
onSecurityAndPrivacyClick = {},
onProfileClick = {},
onReportRoomClick = {},
leaveRoomView = {},
)
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.di
import dev.zacsweers.metro.BindingContainer
import dev.zacsweers.metro.ContributesTo
import dev.zacsweers.metro.Provides
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.features.userprofile.api.UserProfilePresenterFactory
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.room.JoinedRoom
@BindingContainer
@ContributesTo(RoomScope::class)
object RoomMemberModule {
@Provides
fun provideRoomMemberDetailsPresenterFactory(
room: JoinedRoom,
userProfilePresenterFactory: UserProfilePresenterFactory,
encryptionService: EncryptionService,
clipboardHelper: ClipboardHelper,
): RoomMemberDetailsPresenter.Factory {
return object : RoomMemberDetailsPresenter.Factory {
override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter {
return RoomMemberDetailsPresenter(
roomMemberId = roomMemberId,
room = room,
userProfilePresenterFactory = userProfilePresenterFactory,
encryptionService = encryptionService,
clipboardHelper = clipboardHelper,
)
}
}
}
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.edit
import io.element.android.libraries.matrix.ui.media.AvatarAction
sealed interface RoomDetailsEditEvents {
data class HandleAvatarAction(val action: AvatarAction) : RoomDetailsEditEvents
data class UpdateRoomName(val name: String) : RoomDetailsEditEvents
data class UpdateRoomTopic(val topic: String) : RoomDetailsEditEvents
data object OnBackPress : RoomDetailsEditEvents
data object Save : RoomDetailsEditEvents
data object CloseDialog : RoomDetailsEditEvents
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.edit
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.ContributesNode
import io.element.android.libraries.di.RoomScope
import io.element.android.services.analytics.api.AnalyticsService
@ContributesNode(RoomScope::class)
@AssistedInject
class RoomDetailsEditNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val presenter: RoomDetailsEditPresenter,
private val analyticsService: AnalyticsService,
) : Node(buildContext, plugins = plugins) {
init {
lifecycle.subscribe(
onResume = {
analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.RoomSettings))
}
)
}
@Composable
override fun View(modifier: Modifier) {
val state = presenter.present()
RoomDetailsEditView(
state = state,
onDone = ::navigateUp,
modifier = modifier,
)
}
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.edit
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.core.net.toUri
import dev.zacsweers.metro.Inject
import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.matrix.ui.room.avatarUrl
import io.element.android.libraries.matrix.ui.room.rawName
import io.element.android.libraries.matrix.ui.room.topic
import io.element.android.libraries.mediapickers.api.PickerProvider
import io.element.android.libraries.mediaupload.api.MediaOptimizationConfigProvider
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
import io.element.android.libraries.permissions.api.PermissionsEvents
import io.element.android.libraries.permissions.api.PermissionsPresenter
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
@Inject
class RoomDetailsEditPresenter(
private val room: JoinedRoom,
private val mediaPickerProvider: PickerProvider,
private val mediaPreProcessor: MediaPreProcessor,
private val temporaryUriDeleter: TemporaryUriDeleter,
permissionsPresenterFactory: PermissionsPresenter.Factory,
private val mediaOptimizationConfigProvider: MediaOptimizationConfigProvider,
) : Presenter<RoomDetailsEditState> {
private val cameraPermissionPresenter = permissionsPresenterFactory.create(android.Manifest.permission.CAMERA)
private var pendingPermissionRequest = false
@Composable
override fun present(): RoomDetailsEditState {
val cameraPermissionState = cameraPermissionPresenter.present()
val roomSyncUpdateFlow = room.syncUpdateFlow.collectAsState()
val roomAvatarUri = room.avatarUrl()
var roomAvatarUriEdited by rememberSaveable { mutableStateOf<String?>(null) }
LaunchedEffect(roomAvatarUri) {
// Every time the roomAvatar change (from sync), we can set the new avatar.
temporaryUriDeleter.delete(roomAvatarUriEdited?.toUri())
roomAvatarUriEdited = roomAvatarUri
}
val roomRawNameTrimmed = room.rawName().orEmpty().trim()
var roomRawNameEdited by rememberSaveable { mutableStateOf("") }
LaunchedEffect(roomRawNameTrimmed) {
// Every time the rawName change (from sync), we can set the new name.
roomRawNameEdited = roomRawNameTrimmed
}
val roomTopicTrimmed = room.topic().orEmpty().trim()
var roomTopicEdited by rememberSaveable { mutableStateOf("") }
LaunchedEffect(roomTopicTrimmed) {
// Every time the topic change (from sync), we can set the new topic.
roomTopicEdited = roomTopicTrimmed
}
val saveButtonEnabled by remember(
roomRawNameTrimmed,
roomTopicTrimmed,
roomAvatarUri,
) {
derivedStateOf {
roomRawNameTrimmed != roomRawNameEdited.trim() ||
roomTopicTrimmed != roomTopicEdited.trim() ||
roomAvatarUri != roomAvatarUriEdited
}
}
var canChangeName by remember { mutableStateOf(false) }
var canChangeTopic by remember { mutableStateOf(false) }
var canChangeAvatar by remember { mutableStateOf(false) }
LaunchedEffect(roomSyncUpdateFlow.value) {
canChangeName = room.canSendState(StateEventType.ROOM_NAME).getOrElse { false }
canChangeTopic = room.canSendState(StateEventType.ROOM_TOPIC).getOrElse { false }
canChangeAvatar = room.canSendState(StateEventType.ROOM_AVATAR).getOrElse { false }
}
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(
onResult = { uri ->
if (uri != null) {
temporaryUriDeleter.delete(roomAvatarUriEdited?.toUri())
roomAvatarUriEdited = uri.toString()
}
}
)
val galleryImagePicker = mediaPickerProvider.registerGalleryImagePicker(
onResult = { uri ->
if (uri != null) {
temporaryUriDeleter.delete(roomAvatarUriEdited?.toUri())
roomAvatarUriEdited = uri.toString()
}
}
)
LaunchedEffect(cameraPermissionState.permissionGranted) {
if (cameraPermissionState.permissionGranted && pendingPermissionRequest) {
pendingPermissionRequest = false
cameraPhotoPicker.launch()
}
}
val avatarActions by remember(roomAvatarUriEdited) {
derivedStateOf {
listOfNotNull(
AvatarAction.TakePhoto,
AvatarAction.ChoosePhoto,
AvatarAction.Remove.takeIf { roomAvatarUriEdited != null },
).toImmutableList()
}
}
val saveAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val localCoroutineScope = rememberCoroutineScope()
fun handleEvent(event: RoomDetailsEditEvents) {
when (event) {
is RoomDetailsEditEvents.Save -> localCoroutineScope.saveChanges(
currentNameTrimmed = roomRawNameTrimmed,
newNameTrimmed = roomRawNameEdited.trim(),
currentTopicTrimmed = roomTopicTrimmed,
newTopicTrimmed = roomTopicEdited.trim(),
currentAvatar = roomAvatarUri?.toUri(),
newAvatarUri = roomAvatarUriEdited?.toUri(),
action = saveAction,
)
is RoomDetailsEditEvents.HandleAvatarAction -> {
when (event.action) {
AvatarAction.ChoosePhoto -> galleryImagePicker.launch()
AvatarAction.TakePhoto -> if (cameraPermissionState.permissionGranted) {
cameraPhotoPicker.launch()
} else {
pendingPermissionRequest = true
cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions)
}
AvatarAction.Remove -> {
temporaryUriDeleter.delete(roomAvatarUriEdited?.toUri())
roomAvatarUriEdited = null
}
}
}
is RoomDetailsEditEvents.UpdateRoomName -> roomRawNameEdited = event.name
is RoomDetailsEditEvents.UpdateRoomTopic -> roomTopicEdited = event.topic
RoomDetailsEditEvents.CloseDialog -> saveAction.value = AsyncAction.Uninitialized
RoomDetailsEditEvents.OnBackPress -> if (saveButtonEnabled.not() || saveAction.value == AsyncAction.ConfirmingCancellation) {
// No changes to save or already confirming exit without saving
saveAction.value = AsyncAction.Success(Unit)
} else {
saveAction.value = AsyncAction.ConfirmingCancellation
}
}
}
return RoomDetailsEditState(
roomId = room.roomId,
roomRawName = roomRawNameEdited,
canChangeName = canChangeName,
roomTopic = roomTopicEdited,
canChangeTopic = canChangeTopic,
roomAvatarUrl = roomAvatarUriEdited,
canChangeAvatar = canChangeAvatar,
avatarActions = avatarActions,
saveButtonEnabled = saveButtonEnabled,
saveAction = saveAction.value,
cameraPermissionState = cameraPermissionState,
eventSink = ::handleEvent,
)
}
private fun CoroutineScope.saveChanges(
currentNameTrimmed: String,
newNameTrimmed: String,
currentTopicTrimmed: String,
newTopicTrimmed: String,
currentAvatar: Uri?,
newAvatarUri: Uri?,
action: MutableState<AsyncAction<Unit>>,
) = launch {
val results = mutableListOf<Result<Unit>>()
suspend {
if (newTopicTrimmed != currentTopicTrimmed) {
results.add(room.setTopic(newTopicTrimmed).onFailure {
Timber.e(it, "Failed to set room topic")
})
}
if (newNameTrimmed.isNotEmpty() && newNameTrimmed != currentNameTrimmed) {
results.add(room.setName(newNameTrimmed).onFailure {
Timber.e(it, "Failed to set room name")
})
}
if (newAvatarUri != currentAvatar) {
results.add(updateAvatar(newAvatarUri).onFailure {
Timber.e(it, "Failed to update avatar")
})
}
if (results.all { it.isSuccess }) Unit else results.first { it.isFailure }.getOrThrow()
}.runCatchingUpdatingState(action)
}
private suspend fun updateAvatar(avatarUri: Uri?): Result<Unit> {
return runCatchingExceptions {
if (avatarUri != null) {
val preprocessed = mediaPreProcessor.process(
uri = avatarUri,
mimeType = MimeTypes.Jpeg,
deleteOriginal = false,
mediaOptimizationConfig = mediaOptimizationConfigProvider.get(),
).getOrThrow()
room.updateAvatar(MimeTypes.Jpeg, preprocessed.file.readBytes()).getOrThrow()
} else {
room.removeAvatar().getOrThrow()
}
}
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.edit
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.permissions.api.PermissionsState
import kotlinx.collections.immutable.ImmutableList
data class RoomDetailsEditState(
val roomId: RoomId,
/** The raw room name (i.e. the room name from the state event `m.room.name`), not the display name. */
val roomRawName: String,
val canChangeName: Boolean,
val roomTopic: String,
val canChangeTopic: Boolean,
val roomAvatarUrl: String?,
val canChangeAvatar: Boolean,
val avatarActions: ImmutableList<AvatarAction>,
val saveButtonEnabled: Boolean,
val saveAction: AsyncAction<Unit>,
val cameraPermissionState: PermissionsState,
val eventSink: (RoomDetailsEditEvents) -> Unit
)

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.edit
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.permissions.api.PermissionsState
import io.element.android.libraries.permissions.api.aPermissionsState
import kotlinx.collections.immutable.toImmutableList
open class RoomDetailsEditStateProvider : PreviewParameterProvider<RoomDetailsEditState> {
override val values: Sequence<RoomDetailsEditState>
get() = sequenceOf(
aRoomDetailsEditState(),
aRoomDetailsEditState(roomTopic = ""),
aRoomDetailsEditState(roomRawName = ""),
aRoomDetailsEditState(roomAvatarUrl = "example://uri"),
aRoomDetailsEditState(canChangeName = true, canChangeTopic = false, canChangeAvatar = true, saveButtonEnabled = false),
aRoomDetailsEditState(canChangeName = false, canChangeTopic = true, canChangeAvatar = false, saveButtonEnabled = false),
aRoomDetailsEditState(saveAction = AsyncAction.Loading),
aRoomDetailsEditState(saveAction = AsyncAction.Failure(RuntimeException("Whelp"))),
aRoomDetailsEditState(saveAction = AsyncAction.ConfirmingCancellation),
)
}
fun aRoomDetailsEditState(
roomId: RoomId = RoomId("!aRoomId:aDomain"),
roomRawName: String = "Marketing",
canChangeName: Boolean = true,
roomTopic: String = "a room topic that is quite long so should wrap onto multiple lines",
canChangeTopic: Boolean = true,
roomAvatarUrl: String? = null,
canChangeAvatar: Boolean = true,
avatarActions: List<AvatarAction> = emptyList(),
saveButtonEnabled: Boolean = true,
saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
cameraPermissionState: PermissionsState = aPermissionsState(showDialog = false),
eventSink: (RoomDetailsEditEvents) -> Unit = {},
) = RoomDetailsEditState(
roomId = roomId,
roomRawName = roomRawName,
canChangeName = canChangeName,
roomTopic = roomTopic,
canChangeTopic = canChangeTopic,
roomAvatarUrl = roomAvatarUrl,
canChangeAvatar = canChangeAvatar,
avatarActions = avatarActions.toImmutableList(),
saveButtonEnabled = saveButtonEnabled,
saveAction = saveAction,
cameraPermissionState = cameraPermissionState,
eventSink = eventSink,
)

View File

@@ -0,0 +1,179 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.
*/
@file:OptIn(ExperimentalMaterial3Api::class)
package io.element.android.features.roomdetails.impl.edit
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.components.async.AsyncActionView
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.SaveChangesDialog
import io.element.android.libraries.designsystem.modifiers.clearFocusOnTap
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TextField
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
import io.element.android.libraries.matrix.ui.components.EditableAvatarView
import io.element.android.libraries.permissions.api.PermissionsView
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun RoomDetailsEditView(
state: RoomDetailsEditState,
onDone: () -> Unit,
modifier: Modifier = Modifier,
) {
val focusManager = LocalFocusManager.current
val isAvatarActionsSheetVisible = remember { mutableStateOf(false) }
fun onAvatarClick() {
focusManager.clearFocus()
isAvatarActionsSheetVisible.value = true
}
BackHandler {
state.eventSink(RoomDetailsEditEvents.OnBackPress)
}
Scaffold(
modifier = modifier.clearFocusOnTap(focusManager),
topBar = {
TopAppBar(
titleStr = stringResource(id = R.string.screen_room_details_edit_room_title),
navigationIcon = {
BackButton(
onClick = {
state.eventSink(RoomDetailsEditEvents.OnBackPress)
}
)
},
actions = {
TextButton(
text = stringResource(CommonStrings.action_save),
enabled = state.saveButtonEnabled,
onClick = {
focusManager.clearFocus()
state.eventSink(RoomDetailsEditEvents.Save)
},
)
}
)
},
) { padding ->
Column(
modifier = Modifier
.padding(padding)
.padding(horizontal = 16.dp)
.navigationBarsPadding()
.imePadding()
.verticalScroll(rememberScrollState())
) {
Spacer(modifier = Modifier.height(24.dp))
EditableAvatarView(
matrixId = state.roomId.value,
// As per Element Web, we use the raw name for the avatar as well
displayName = state.roomRawName,
avatarUrl = state.roomAvatarUrl,
avatarSize = AvatarSize.EditRoomDetails,
avatarType = AvatarType.Room(),
onAvatarClick = ::onAvatarClick,
modifier = Modifier.fillMaxWidth(),
)
Spacer(modifier = Modifier.height(60.dp))
TextField(
label = stringResource(id = R.string.screen_room_details_room_name_label),
value = state.roomRawName,
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
singleLine = true,
readOnly = !state.canChangeName,
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomName(it)) },
)
Spacer(modifier = Modifier.height(28.dp))
TextField(
label = stringResource(CommonStrings.common_topic),
value = state.roomTopic,
placeholder = stringResource(CommonStrings.common_topic_placeholder),
maxLines = 10,
readOnly = !state.canChangeTopic,
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(it)) },
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Sentences,
),
)
}
}
AvatarActionBottomSheet(
actions = state.avatarActions,
isVisible = isAvatarActionsSheetVisible.value,
onDismiss = { isAvatarActionsSheetVisible.value = false },
onSelectAction = { state.eventSink(RoomDetailsEditEvents.HandleAvatarAction(it)) }
)
AsyncActionView(
async = state.saveAction,
progressDialog = {
AsyncActionViewDefaults.ProgressDialog(
progressText = stringResource(R.string.screen_room_details_updating_room),
)
},
confirmationDialog = {
if (state.saveAction == AsyncAction.ConfirmingCancellation) {
SaveChangesDialog(
onSubmitClick = { state.eventSink(RoomDetailsEditEvents.OnBackPress) },
onDismiss = { state.eventSink(RoomDetailsEditEvents.CloseDialog) }
)
}
},
onSuccess = { onDone() },
errorMessage = { stringResource(R.string.screen_room_details_edition_error) },
onErrorDismiss = { state.eventSink(RoomDetailsEditEvents.CloseDialog) }
)
PermissionsView(
state = state.cameraPermissionState,
)
}
@PreviewsDayNight
@Composable
internal fun RoomDetailsEditViewPreview(@PreviewParameter(RoomDetailsEditStateProvider::class) state: RoomDetailsEditState) = ElementPreview {
RoomDetailsEditView(
state = state,
onDone = {},
)
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.invite
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.ContributesNode
import io.element.android.features.invitepeople.api.InvitePeoplePresenter
import io.element.android.features.invitepeople.api.InvitePeopleRenderer
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.services.analytics.api.AnalyticsService
@ContributesNode(RoomScope::class)
@AssistedInject
class RoomInviteMembersNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val analyticsService: AnalyticsService,
private val invitePeopleRenderer: InvitePeopleRenderer,
room: JoinedRoom,
invitePeoplePresenterFactory: InvitePeoplePresenter.Factory,
) : Node(buildContext, plugins = plugins) {
init {
lifecycle.subscribe(
onResume = {
analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.Invites))
}
)
}
private val invitePeoplePresenter = invitePeoplePresenterFactory.create(
joinedRoom = room,
roomId = room.roomId,
)
@Composable
override fun View(modifier: Modifier) {
val state = invitePeoplePresenter.present()
// Once invites have been sent successfully, close the Invite view.
LaunchedEffect(state.sendInvitesAction) {
if (state.sendInvitesAction.isReady()) {
navigateUp()
}
}
RoomInviteMembersView(
state = state,
modifier = modifier,
onBackClick = { navigateUp() }
) {
invitePeopleRenderer.Render(state, Modifier)
}
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.invite
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.invitepeople.api.InvitePeopleEvents
import io.element.android.features.invitepeople.api.InvitePeopleState
import io.element.android.features.invitepeople.api.InvitePeopleStateProvider
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun RoomInviteMembersView(
state: InvitePeopleState,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
invitePeopleView: @Composable () -> Unit,
) {
Scaffold(
modifier = modifier,
topBar = {
RoomInviteMembersTopBar(
onBackClick = {
if (state.isSearchActive) {
state.eventSink(InvitePeopleEvents.CloseSearch)
} else {
onBackClick()
}
},
onSubmitClick = {
state.eventSink(InvitePeopleEvents.SendInvites)
},
canSend = state.canInvite,
)
}
) { padding ->
Box(
modifier = Modifier
.fillMaxWidth()
.padding(padding)
.consumeWindowInsets(padding),
) {
invitePeopleView()
}
}
if (state.sendInvitesAction.isLoading()) {
InviteProgressDialog()
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun RoomInviteMembersTopBar(
canSend: Boolean,
onBackClick: () -> Unit,
onSubmitClick: () -> Unit,
) {
TopAppBar(
titleStr = stringResource(R.string.screen_room_details_invite_people_title),
navigationIcon = { BackButton(onClick = onBackClick) },
actions = {
TextButton(
text = stringResource(CommonStrings.action_invite),
onClick = onSubmitClick,
enabled = canSend,
)
}
)
}
@Composable
private fun InviteProgressDialog() {
ProgressDialog {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.screen_room_details_invite_people_preparing),
color = ElementTheme.colors.textPrimary,
style = ElementTheme.typography.fontHeadingSmMedium,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(R.string.screen_room_details_invite_people_dont_close),
color = ElementTheme.colors.textSecondary,
style = MaterialTheme.typography.bodyMedium,
)
}
}
@PreviewsDayNight
@Composable
internal fun RoomInviteMembersViewPreview(@PreviewParameter(InvitePeopleStateProvider::class) state: InvitePeopleState) = ElementPreview {
RoomInviteMembersView(
state = state,
invitePeopleView = {},
onBackClick = {},
)
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members
import io.element.android.libraries.matrix.api.room.RoomMember
sealed interface RoomMemberListEvents {
data class ChangeSelectedSection(val section: SelectedSection) : RoomMemberListEvents
data class UpdateSearchQuery(val query: String) : RoomMemberListEvents
data class RoomMemberSelected(val roomMember: RoomMember) : RoomMemberListEvents
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.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.architecture.appyx.launchMolecule
import io.element.android.libraries.architecture.callback
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.services.analytics.api.AnalyticsService
@ContributesNode(RoomScope::class)
@AssistedInject
class RoomMemberListNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val presenter: RoomMemberListPresenter,
private val analyticsService: AnalyticsService,
private val roomMemberModerationRenderer: RoomMemberModerationRenderer,
) : Node(buildContext, plugins = plugins), RoomMemberListNavigator {
interface Callback : Plugin {
fun navigateToRoomMemberDetails(roomMemberId: UserId)
fun navigateToInviteMembers()
}
private val callback: Callback = callback()
private val stateFlow = launchMolecule { presenter.present() }
init {
lifecycle.subscribe(
onResume = {
analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.RoomMembers))
}
)
}
override fun openRoomMemberDetails(roomMemberId: UserId) {
callback.navigateToRoomMemberDetails(roomMemberId)
}
override fun openInviteMembers() {
callback.navigateToInviteMembers()
}
override fun exitRoomMemberList() {
navigateUp()
}
@Composable
override fun View(modifier: Modifier) {
val state by stateFlow.collectAsState()
RoomMemberListView(
state = state,
modifier = modifier,
navigator = this,
)
roomMemberModerationRenderer.Render(
state = state.moderationState,
onSelectAction = { action, target ->
when (action) {
is ModerationAction.DisplayProfile -> openRoomMemberDetails(target.userId)
else -> state.moderationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target))
}
},
modifier = Modifier,
)
}
}
interface RoomMemberListNavigator {
fun exitRoomMemberList() {}
fun openRoomMemberDetails(roomMemberId: UserId) {}
fun openInviteMembers() {}
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import dev.zacsweers.metro.Inject
import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents.ShowActionsForUser
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.architecture.map
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
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.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.api.room.toMatrixUser
import io.element.android.libraries.matrix.ui.room.PowerLevelRoomMemberComparator
import io.element.android.libraries.matrix.ui.room.canInviteAsState
import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.withContext
@Inject
class RoomMemberListPresenter(
private val room: JoinedRoom,
private val coroutineDispatchers: CoroutineDispatchers,
private val roomMembersModerationPresenter: Presenter<RoomMemberModerationState>,
private val encryptionService: EncryptionService,
) : Presenter<RoomMemberListState> {
private val powerLevelRoomMemberComparator = PowerLevelRoomMemberComparator()
@Composable
override fun present(): RoomMemberListState {
var searchQuery by rememberSaveable { mutableStateOf("") }
val membersState by room.membersStateFlow.collectAsState()
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
val canInvite by room.canInviteAsState(syncUpdateFlow.value)
val roomModerationState = roomMembersModerationPresenter.present()
val roomMemberIdentityStates by produceState(persistentMapOf()) {
room.roomMemberIdentityStateChange(waitForEncryption = true)
.onEach { identities ->
value = identities.associateBy({ it.identityRoomMember.userId }, { it.identityState }).toImmutableMap()
}
.launchIn(this)
}
var selectedSection by remember { mutableStateOf(SelectedSection.MEMBERS) }
var roomMembers: AsyncData<RoomMembers> by remember { mutableStateOf(AsyncData.Loading()) }
var filteredRoomMembers: AsyncData<RoomMembers> by remember { mutableStateOf(AsyncData.Loading()) }
// Update the room members when the screen is loaded
LaunchedEffect(Unit) {
room.updateMembers()
}
LaunchedEffect(membersState, roomMemberIdentityStates) {
if (membersState is RoomMembersState.Unknown) {
return@LaunchedEffect
}
val finalMembersState = membersState
if (finalMembersState is RoomMembersState.Error && finalMembersState.roomMembers().orEmpty().isEmpty()) {
// Cannot fetch members and no cached members, display the error
roomMembers = AsyncData.Failure(finalMembersState.failure)
return@LaunchedEffect
}
withContext(coroutineDispatchers.io) {
val members = membersState.roomMembers().orEmpty().groupBy { it.membership }
val info = room.info()
if (members.getOrDefault(RoomMembershipState.JOIN, emptyList()).size < info.joinedMembersCount / 2) {
// Don't display initial room member list if we have less than half of the joined members:
// This result will come from the timeline loading membership events and it'll be wrong.
return@withContext
}
val result = RoomMembers(
invited = members.getOrDefault(RoomMembershipState.INVITE, emptyList())
.map { it.withIdentityState(roomMemberIdentityStates) }
.toImmutableList(),
joined = members.getOrDefault(RoomMembershipState.JOIN, emptyList())
.sortedWith(powerLevelRoomMemberComparator)
.map { it.withIdentityState(roomMemberIdentityStates) }
.toImmutableList(),
banned = members.getOrDefault(RoomMembershipState.BAN, emptyList())
.sortedBy { it.userId.value }
.map { it.withIdentityState(roomMemberIdentityStates) }
.toImmutableList(),
)
roomMembers = if (membersState is RoomMembersState.Pending) {
AsyncData.Loading(result)
} else {
AsyncData.Success(result)
}
}
}
LaunchedEffect(searchQuery, roomMembers) {
filteredRoomMembers = roomMembers.map { members ->
withContext(coroutineDispatchers.io) {
members.filter(searchQuery)
}
}
}
fun handleEvent(event: RoomMemberListEvents) {
when (event) {
is RoomMemberListEvents.UpdateSearchQuery -> searchQuery = event.query
is RoomMemberListEvents.RoomMemberSelected ->
roomModerationState.eventSink(ShowActionsForUser(event.roomMember.toMatrixUser()))
is RoomMemberListEvents.ChangeSelectedSection -> selectedSection = event.section
}
}
val state = RoomMemberListState(
roomMembers = roomMembers,
filteredRoomMembers = filteredRoomMembers,
searchQuery = searchQuery,
canInvite = canInvite,
moderationState = roomModerationState,
selectedSection = selectedSection,
eventSink = ::handleEvent,
)
if (!state.showBannedSection && selectedSection == SelectedSection.BANNED) {
SideEffect {
selectedSection = SelectedSection.MEMBERS
}
}
return state
}
private suspend fun RoomMember.withIdentityState(identityStates: ImmutableMap<UserId, IdentityState>): RoomMemberWithIdentityState {
return if (room.info().isEncrypted != true) {
RoomMemberWithIdentityState(this, null)
} else {
val identityState = identityStates[userId] ?: encryptionService.getUserIdentity(userId, fallbackToServer = false).getOrNull()
RoomMemberWithIdentityState(this, identityState)
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members
import io.element.android.features.roommembermoderation.api.RoomMemberModerationState
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.room.RoomMember
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
data class RoomMemberListState(
// Only used to know if we can show the banned section
private val roomMembers: AsyncData<RoomMembers>,
val filteredRoomMembers: AsyncData<RoomMembers>,
val searchQuery: String,
val canInvite: Boolean,
val selectedSection: SelectedSection,
val moderationState: RoomMemberModerationState,
val eventSink: (RoomMemberListEvents) -> Unit,
) {
val showBannedSection: Boolean = moderationState.canBan && roomMembers.dataOrNull()?.banned?.isNotEmpty() == true
}
enum class SelectedSection {
MEMBERS,
BANNED
}
data class RoomMembers(
val invited: ImmutableList<RoomMemberWithIdentityState>,
val joined: ImmutableList<RoomMemberWithIdentityState>,
val banned: ImmutableList<RoomMemberWithIdentityState>,
) {
fun isEmpty(section: SelectedSection): Boolean {
return when (section) {
SelectedSection.MEMBERS -> invited.isEmpty() && joined.isEmpty()
SelectedSection.BANNED -> banned.isEmpty()
}
}
fun filter(query: String): RoomMembers {
if (query.isBlank()) {
return this
}
val filterPredicate = { member: RoomMemberWithIdentityState ->
member.roomMember.userId.value.contains(query, ignoreCase = true) ||
member.roomMember.displayName?.contains(query, ignoreCase = true).orFalse()
}
return RoomMembers(
invited = invited.filter(filterPredicate).toImmutableList(),
joined = joined.filter(filterPredicate).toImmutableList(),
banned = banned.filter(filterPredicate).toImmutableList(),
)
}
}
data class RoomMemberWithIdentityState(
val roomMember: RoomMember,
val identityState: IdentityState?,
)

View File

@@ -0,0 +1,159 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
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.map
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import kotlinx.collections.immutable.persistentListOf
internal class RoomMemberListStateProvider : PreviewParameterProvider<RoomMemberListState> {
override val values: Sequence<RoomMemberListState>
get() = sequenceOf(
aRoomMemberListState(
roomMembers = AsyncData.Loading(),
selectedSection = SelectedSection.MEMBERS,
),
aRoomMemberListState(
roomMembers = AsyncData.Failure(Exception("Error details")),
selectedSection = SelectedSection.MEMBERS,
),
aRoomMemberListState(
roomMembers = aLoadedRoomMembers(),
selectedSection = SelectedSection.MEMBERS,
),
aRoomMemberListState(
roomMembers = aLoadedRoomMembers(),
selectedSection = SelectedSection.BANNED,
moderationState = aRoomMemberModerationState(canBan = true),
),
aRoomMemberListState(
roomMembers = aLoadedRoomMembers(),
canInvite = true,
selectedSection = SelectedSection.MEMBERS,
),
aRoomMemberListState(
roomMembers = aLoadedRoomMembers(),
searchQuery = "alice",
selectedSection = SelectedSection.MEMBERS,
),
aRoomMemberListState(
roomMembers = aLoadedRoomMembers(),
searchQuery = "something-with-no-results",
selectedSection = SelectedSection.MEMBERS,
),
)
}
private fun aLoadedRoomMembers() = AsyncData.Success(
RoomMembers(
invited = persistentListOf(
anInvitedVictor().withIdentity(),
anInvitedWalter().withIdentity(),
),
joined = persistentListOf(
anAlice().withIdentity(identityState = IdentityState.Verified),
aBob().withIdentity(identityState = IdentityState.PinViolation),
aCarol().withIdentity(),
aDavid().withIdentity(),
anEve().withIdentity(identityState = IdentityState.VerificationViolation)
),
banned = persistentListOf(
aBannedMallory().withIdentity(),
aBannedSusie().withIdentity()
),
)
)
internal fun aRoomMemberListState(
roomMembers: AsyncData<RoomMembers> = AsyncData.Loading(),
moderationState: RoomMemberModerationState = aRoomMemberModerationState(),
selectedSection: SelectedSection = SelectedSection.MEMBERS,
searchQuery: String = "",
canInvite: Boolean = false,
eventSink: (RoomMemberListEvents) -> Unit = {},
) = RoomMemberListState(
roomMembers = roomMembers,
filteredRoomMembers = roomMembers.map { it.filter(searchQuery) },
searchQuery = searchQuery,
canInvite = canInvite,
moderationState = moderationState,
selectedSection = selectedSection,
eventSink = 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,
avatarUrl: String? = null,
membership: RoomMembershipState = RoomMembershipState.JOIN,
isNameAmbiguous: Boolean = false,
powerLevel: Long = 0L,
isIgnored: Boolean = false,
role: RoomMember.Role = RoomMember.Role.User,
membershipChangeReason: String? = null,
) = RoomMember(
userId = userId,
displayName = displayName,
avatarUrl = avatarUrl,
membership = membership,
isNameAmbiguous = isNameAmbiguous,
powerLevel = powerLevel,
isIgnored = isIgnored,
role = role,
membershipChangeReason = membershipChangeReason,
)
fun aRoomMemberList() = persistentListOf(
anAlice(),
aBob(),
aCarol(),
aDavid(),
anEve(),
anInvitedVictor(),
anInvitedWalter(),
aBannedSusie(),
aBannedMallory(),
)
fun anEve(): RoomMember = aRoomMember(UserId("@eve:server.org"), "Eve")
fun aDavid(): RoomMember = aRoomMember(UserId("@david:server.org"), "David")
fun aCarol(): RoomMember = aRoomMember(UserId("@carol:server.org"), "Carol")
fun anAlice() = aRoomMember(UserId("@alice:server.org"), "Alice", role = RoomMember.Role.Admin)
fun aBob() = aRoomMember(UserId("@bob:server.org"), "Bob", role = RoomMember.Role.Moderator)
fun anInvitedVictor() = aRoomMember(UserId("@victor:server.org"), "Victor", membership = RoomMembershipState.INVITE)
fun anInvitedWalter() = aRoomMember(UserId("@walter:server.org"), "Walter", membership = RoomMembershipState.INVITE)
fun aBannedSusie(): RoomMember = aRoomMember(UserId("@susie:server.org"), "Susie", membership = RoomMembershipState.BAN)
fun aBannedMallory(): RoomMember = aRoomMember(UserId("@mallory:server.org"), "Mallory", membership = RoomMembershipState.BAN)
private fun RoomMember.withIdentity(identityState: IdentityState? = null) = RoomMemberWithIdentityState(this, identityState)

View File

@@ -0,0 +1,368 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
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.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.components.BigIcon
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.form.textFieldState
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.SearchField
import io.element.android.libraries.designsystem.theme.components.SegmentedButton
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.getBestName
import io.element.android.libraries.matrix.api.room.toMatrixUser
import io.element.android.libraries.matrix.ui.components.MatrixUserRow
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@Composable
fun RoomMemberListView(
state: RoomMemberListState,
navigator: RoomMemberListNavigator,
modifier: Modifier = Modifier,
) {
fun onSelectUser(roomMember: RoomMember) {
state.eventSink(RoomMemberListEvents.RoomMemberSelected(roomMember))
}
Scaffold(
modifier = modifier,
topBar = {
RoomMemberListTopBar(
canInvite = state.canInvite,
onBackClick = navigator::exitRoomMemberList,
onInviteClick = navigator::openInviteMembers,
)
}
) { padding ->
Column(
modifier = Modifier
.fillMaxWidth()
.padding(padding)
.consumeWindowInsets(padding),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
var searchQuery by textFieldState(state.searchQuery)
SearchField(
value = searchQuery,
onValueChange = { newQuery ->
searchQuery = newQuery
state.eventSink(RoomMemberListEvents.UpdateSearchQuery(newQuery))
},
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
placeholder = stringResource(CommonStrings.common_search_for_someone),
)
RoomMemberList(
roomMembersData = state.filteredRoomMembers,
selectedSection = state.selectedSection,
showBannedSection = state.showBannedSection,
searchQuery = state.searchQuery,
onSelectedSectionChange = { state.eventSink(RoomMemberListEvents.ChangeSelectedSection(it)) },
onSelectUser = ::onSelectUser,
)
}
}
}
@Composable
private fun RoomMemberList(
roomMembersData: AsyncData<RoomMembers>,
selectedSection: SelectedSection,
showBannedSection: Boolean,
searchQuery: String,
onSelectedSectionChange: (SelectedSection) -> Unit,
onSelectUser: (RoomMember) -> Unit,
) {
LazyColumn(modifier = Modifier.fillMaxWidth(), state = rememberLazyListState()) {
stickyHeader {
Column {
AnimatedVisibility(visible = showBannedSection) {
val segmentedButtonTitles = persistentListOf(
stringResource(id = R.string.screen_room_member_list_mode_members),
stringResource(id = R.string.screen_room_member_list_mode_banned),
)
SingleChoiceSegmentedButtonRow(
modifier = Modifier
.background(ElementTheme.colors.bgCanvasDefault)
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
) {
for ((index, title) in segmentedButtonTitles.withIndex()) {
SegmentedButton(
index = index,
count = segmentedButtonTitles.size,
selected = selectedSection.ordinal == index,
onClick = { onSelectedSectionChange(SelectedSection.entries[index]) },
text = title,
)
}
}
}
AnimatedVisibility(visible = roomMembersData.isLoading()) {
LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
}
}
}
when (roomMembersData) {
is AsyncData.Failure -> failureItem(roomMembersData.error)
is AsyncData.Loading,
is AsyncData.Success -> {
val roomMembers = roomMembersData.dataOrNull() ?: return@LazyColumn
if (roomMembers.isEmpty(selectedSection)) {
emptySearchItem(searchQuery)
} else {
memberItems(
roomMembers = roomMembers,
selectedSection = selectedSection,
onSelectUser = onSelectUser,
)
}
}
AsyncData.Uninitialized -> Unit
}
}
}
private fun LazyListScope.memberItems(
roomMembers: RoomMembers,
selectedSection: SelectedSection,
onSelectUser: (RoomMember) -> Unit,
) {
when (selectedSection) {
SelectedSection.MEMBERS -> {
if (roomMembers.invited.isNotEmpty()) {
roomMemberListSectionHeader(
text = {
val memberCount = roomMembers.invited.count()
pluralStringResource(id = R.plurals.screen_room_member_list_pending_header_title, memberCount, memberCount)
},
)
roomMemberListSectionItems(
members = roomMembers.invited,
onMemberSelected = { onSelectUser(it) }
)
}
if (roomMembers.joined.isNotEmpty()) {
roomMemberListSectionHeader(
text = {
val memberCount = roomMembers.joined.count()
pluralStringResource(id = R.plurals.screen_room_member_list_header_title, count = memberCount, memberCount)
},
)
roomMemberListSectionItems(
members = roomMembers.joined,
onMemberSelected = { onSelectUser(it) }
)
}
}
SelectedSection.BANNED -> {
if (roomMembers.banned.isNotEmpty()) {
roomMemberListSectionHeader(
text = {
val memberCount = roomMembers.banned.count()
pluralStringResource(id = R.plurals.screen_room_member_list_banned_header_title, memberCount, memberCount)
},
isCritical = true,
)
roomMemberListSectionItems(
members = roomMembers.banned,
onMemberSelected = { onSelectUser(it) }
)
}
}
}
}
private fun LazyListScope.failureItem(failure: Throwable) {
item {
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 32.dp),
text = stringResource(id = CommonStrings.error_unknown) + "\n\n" + failure.localizedMessage,
color = ElementTheme.colors.textCriticalPrimary,
textAlign = TextAlign.Center,
)
}
}
private fun LazyListScope.roomMemberListSectionHeader(
text: @Composable (() -> String),
modifier: Modifier = Modifier,
isCritical: Boolean = false,
) {
item {
Text(
modifier = modifier.padding(horizontal = 16.dp, vertical = 12.dp),
text = text(),
style = ElementTheme.typography.fontBodyLgMedium,
color = if (isCritical) ElementTheme.colors.textCriticalPrimary else ElementTheme.colors.textPrimary,
)
}
}
private fun LazyListScope.roomMemberListSectionItems(
members: ImmutableList<RoomMemberWithIdentityState>?,
onMemberSelected: (RoomMember) -> Unit,
) {
items(members.orEmpty()) { matrixUser ->
RoomMemberListItem(
modifier = Modifier.fillMaxWidth(),
roomMemberWithIdentity = matrixUser,
onClick = { onMemberSelected(matrixUser.roomMember) }
)
}
}
private fun LazyListScope.emptySearchItem(searchQuery: String) {
item {
IconTitleSubtitleMolecule(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 32.dp),
iconStyle = BigIcon.Style.Default(
vectorIcon = CompoundIcons.Search(),
contentDescription = null,
),
title = stringResource(R.string.screen_room_member_list_empty_search_title, searchQuery),
subTitle = stringResource(R.string.screen_room_member_list_empty_search_subtitle),
)
}
}
@Composable
private fun RoomMemberListItem(
roomMemberWithIdentity: RoomMemberWithIdentityState,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val member = roomMemberWithIdentity.roomMember
val roleText = when (member.role) {
RoomMember.Role.Admin -> stringResource(R.string.screen_room_member_list_role_administrator)
RoomMember.Role.Moderator -> stringResource(R.string.screen_room_member_list_role_moderator)
is RoomMember.Role.Owner -> stringResource(R.string.screen_room_member_list_role_owner)
else -> null
}
MatrixUserRow(
modifier = modifier.clickable(onClick = onClick),
matrixUser = roomMemberWithIdentity.roomMember.toMatrixUser(),
avatarSize = AvatarSize.UserListItem,
trailingContent = {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically,
) {
when (roomMemberWithIdentity.identityState) {
IdentityState.Verified -> {
Icon(
modifier = Modifier.size(20.dp),
imageVector = CompoundIcons.Verified(),
contentDescription = stringResource(CommonStrings.common_verified),
tint = ElementTheme.colors.iconSuccessPrimary
)
}
IdentityState.VerificationViolation -> {
Icon(
modifier = Modifier.size(20.dp),
imageVector = CompoundIcons.ErrorSolid(),
contentDescription = stringResource(
CommonStrings.crypto_identity_change_profile_pin_violation,
roomMemberWithIdentity.roomMember.getBestName()
),
tint = ElementTheme.colors.iconCriticalPrimary
)
}
else -> Unit
}
roleText?.let {
Text(
text = it,
style = ElementTheme.typography.fontBodySmRegular,
color = ElementTheme.colors.textSecondary,
)
}
}
}
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun RoomMemberListTopBar(
canInvite: Boolean,
onBackClick: () -> Unit,
onInviteClick: () -> Unit,
) {
TopAppBar(
titleStr = stringResource(CommonStrings.common_people),
navigationIcon = { BackButton(onClick = onBackClick) },
actions = {
if (canInvite) {
TextButton(
text = stringResource(CommonStrings.action_invite),
onClick = onInviteClick,
)
}
}
)
}
@PreviewsDayNight
@Composable
internal fun RoomMemberListViewPreview(@PreviewParameter(RoomMemberListStateProvider::class) state: RoomMemberListState) = ElementPreview {
RoomMemberListView(
state = state,
navigator = object : RoomMemberListNavigator {},
)
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members.details
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.ContributesNode
import io.element.android.features.userprofile.shared.UserProfileNodeHelper
import io.element.android.features.userprofile.shared.UserProfileView
import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.services.analytics.api.AnalyticsService
@ContributesNode(RoomScope::class)
@AssistedInject
class RoomMemberDetailsNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val analyticsService: AnalyticsService,
private val permalinkBuilder: PermalinkBuilder,
presenterFactory: RoomMemberDetailsPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
data class RoomMemberDetailsInput(
val roomMemberId: UserId,
) : NodeInputs
private val inputs = inputs<RoomMemberDetailsInput>()
private val callback = inputs<UserProfileNodeHelper.Callback>()
private val presenter = presenterFactory.create(inputs.roomMemberId)
private val userProfileNodeHelper = UserProfileNodeHelper(inputs.roomMemberId)
init {
lifecycle.subscribe(
onResume = {
analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.User))
}
)
}
@Composable
override fun View(modifier: Modifier) {
val context = LocalContext.current
fun onShareUser() {
userProfileNodeHelper.onShareUser(context, permalinkBuilder)
}
fun navigateToRoom(roomId: RoomId) {
callback.navigateToRoom(roomId)
}
fun onStartCall(roomId: RoomId) {
callback.startCall(roomId)
}
val state = presenter.present()
UserProfileView(
state = state,
modifier = modifier,
goBack = this::navigateUp,
onShareUser = ::onShareUser,
onOpenDm = ::navigateToRoom,
onStartCall = ::onStartCall,
openAvatarPreview = callback::navigateToAvatarPreview,
onVerifyClick = callback::startVerifyUserFlow,
)
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members.details
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import io.element.android.features.userprofile.api.UserProfileEvents
import io.element.android.features.userprofile.api.UserProfilePresenterFactory
import io.element.android.features.userprofile.api.UserProfileState
import io.element.android.features.userprofile.api.UserProfileVerificationState
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.ui.room.getRoomMemberAsState
import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
/**
* Presenter for room member details screen.
* Rely on UserProfilePresenter, but override some fields with room member info when available.
*/
@AssistedInject
class RoomMemberDetailsPresenter(
@Assisted private val roomMemberId: UserId,
private val room: JoinedRoom,
private val encryptionService: EncryptionService,
private val clipboardHelper: ClipboardHelper,
userProfilePresenterFactory: UserProfilePresenterFactory,
) : Presenter<UserProfileState> {
interface Factory {
fun create(roomMemberId: UserId): RoomMemberDetailsPresenter
}
private val userProfilePresenter = userProfilePresenterFactory.create(roomMemberId)
@Composable
override fun present(): UserProfileState {
val coroutineScope = rememberCoroutineScope()
val snackbarDispatcher = LocalSnackbarDispatcher.current
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
val roomMember by room.getRoomMemberAsState(roomMemberId)
LaunchedEffect(Unit) {
// Update room member info when opening this screen
// We don't need to assign the result as it will be automatically propagated by `room.getRoomMemberAsState`
room.getUpdatedMember(roomMemberId)
}
val roomUserName: String? by produceState(
initialValue = roomMember?.displayName,
key1 = roomMember,
) {
value = room.userDisplayName(roomMemberId).getOrNull() ?: roomMember?.displayName
}
val roomUserAvatar: String? by produceState(
initialValue = roomMember?.avatarUrl,
key1 = roomMember,
) {
value = room.userAvatarUrl(roomMemberId).getOrNull() ?: roomMember?.avatarUrl
}
val userProfileState = userProfilePresenter.present()
val identityStateChanges = produceState<IdentityStateChange?>(initialValue = null) {
// Fetch the initial identity state manually
val identityState = encryptionService.getUserIdentity(roomMemberId).getOrNull()
value = identityState?.let { IdentityStateChange(roomMemberId, it) }
// Subscribe to the identity changes
room.roomMemberIdentityStateChange(waitForEncryption = false)
.map { it.find { it.identityRoomMember.userId == roomMemberId } }
.map { roomMemberIdentityStateChange ->
// If we didn't receive any info, manually fetch it
roomMemberIdentityStateChange?.identityState ?: encryptionService.getUserIdentity(roomMemberId).getOrNull()
}
.filterNotNull()
.collect { value = IdentityStateChange(roomMemberId, it) }
}
val verificationState by remember {
derivedStateOf {
when (identityStateChanges.value?.identityState) {
IdentityState.VerificationViolation -> UserProfileVerificationState.VERIFICATION_VIOLATION
IdentityState.Verified -> UserProfileVerificationState.VERIFIED
IdentityState.Pinned, IdentityState.PinViolation -> UserProfileVerificationState.UNVERIFIED
else -> UserProfileVerificationState.UNKNOWN
}
}
}
fun handleEvent(event: UserProfileEvents) {
when (event) {
UserProfileEvents.WithdrawVerification -> coroutineScope.launch {
encryptionService.withdrawVerification(roomMemberId)
}
is UserProfileEvents.CopyToClipboard -> {
clipboardHelper.copyPlainText(event.text)
snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_copied_to_clipboard))
}
else -> userProfileState.eventSink(event)
}
}
return userProfileState.copy(
userName = roomUserName ?: userProfileState.userName,
avatarUrl = roomUserAvatar ?: userProfileState.avatarUrl,
verificationState = verificationState,
snackbarMessage = snackbarMessage,
eventSink = ::handleEvent,
)
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
sealed interface RoomNotificationSettingsEvents {
data class ChangeRoomNotificationMode(val mode: RoomNotificationMode) : RoomNotificationSettingsEvents
data class SetNotificationMode(val isDefault: Boolean) : RoomNotificationSettingsEvents
data object DeleteCustomNotification : RoomNotificationSettingsEvents
data object ClearSetNotificationError : RoomNotificationSettingsEvents
data object ClearRestoreDefaultError : RoomNotificationSettingsEvents
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
data class RoomNotificationSettingsItem(
val mode: RoomNotificationMode,
val title: String,
)
@Composable
fun roomNotificationSettingsItems(): ImmutableList<RoomNotificationSettingsItem> {
return RoomNotificationMode.entries
.map {
when (it) {
RoomNotificationMode.ALL_MESSAGES -> RoomNotificationSettingsItem(
mode = it,
title = stringResource(R.string.screen_room_notification_settings_mode_all_messages),
)
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RoomNotificationSettingsItem(
mode = it,
title = stringResource(R.string.screen_room_notification_settings_mode_mentions_and_keywords),
)
RoomNotificationMode.MUTE -> RoomNotificationSettingsItem(
mode = it,
title = stringResource(CommonStrings.common_mute),
)
}
}
.toImmutableList()
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.ContributesNode
import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.callback
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.RoomScope
import io.element.android.services.analytics.api.AnalyticsService
@ContributesNode(RoomScope::class)
@AssistedInject
class RoomNotificationSettingsNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
presenterFactory: RoomNotificationSettingsPresenter.Factory,
private val analyticsService: AnalyticsService,
) : Node(buildContext, plugins = plugins) {
data class RoomNotificationSettingInput(
val showUserDefinedSettingStyle: Boolean
) : NodeInputs
interface Callback : Plugin {
fun navigateToGlobalNotificationSettings()
}
private val callback: Callback = callback()
private val inputs = inputs<RoomNotificationSettingInput>()
private val presenter = presenterFactory.create(inputs.showUserDefinedSettingStyle)
init {
lifecycle.subscribe(
onResume = {
analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.RoomNotifications))
}
)
}
@Composable
override fun View(modifier: Modifier) {
val state = presenter.present()
RoomNotificationSettingsView(
state = state,
modifier = modifier,
onShowGlobalNotifications = callback::navigateToGlobalNotificationSettings,
onBackClick = ::navigateUp,
)
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.designsystem.components.list.ListItemContent
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.ListItem
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
@Composable
fun RoomNotificationSettingsOption(
roomNotificationSettingsItem: RoomNotificationSettingsItem,
onSelectOption: (RoomNotificationSettingsItem) -> Unit,
displayMentionsOnlyDisclaimer: Boolean,
modifier: Modifier = Modifier,
enabled: Boolean = true,
isSelected: Boolean = false,
) {
val mode = roomNotificationSettingsItem.mode
val title = roomNotificationSettingsItem.title
val subtitle = when {
mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY && displayMentionsOnlyDisclaimer -> {
stringResource(id = R.string.screen_notification_settings_mentions_only_disclaimer)
}
else -> null
}
ListItem(
modifier = modifier,
enabled = enabled,
headlineContent = { Text(title) },
supportingContent = subtitle?.let { { Text(it) } },
trailingContent = ListItemContent.RadioButton(selected = isSelected),
onClick = { onSelectOption(roomNotificationSettingsItem) },
)
}
@PreviewsDayNight
@Composable
internal fun RoomNotificationSettingsOptionPreview() = ElementPreview {
Column {
for ((index, item) in roomNotificationSettingsItems().withIndex()) {
RoomNotificationSettingsOption(
roomNotificationSettingsItem = item,
onSelectOption = {},
isSelected = index == 0,
enabled = index != 2,
displayMentionsOnlyDisclaimer = index == 1,
)
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
@Composable
fun RoomNotificationSettingsOptions(
selected: RoomNotificationMode?,
enabled: Boolean,
onSelectOption: (RoomNotificationSettingsItem) -> Unit,
displayMentionsOnlyDisclaimer: Boolean,
modifier: Modifier = Modifier,
) {
val items = roomNotificationSettingsItems()
Column(modifier = modifier.selectableGroup()) {
items.forEach { item ->
RoomNotificationSettingsOption(
roomNotificationSettingsItem = item,
isSelected = selected == item.mode,
onSelectOption = onSelectOption,
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
enabled = enabled
)
}
}
}

View File

@@ -0,0 +1,208 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedFactory
import dev.zacsweers.metro.AssistedInject
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.runCatchingUpdatingState
import io.element.android.libraries.core.coroutine.suspendWithMinimumDuration
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.seconds
@AssistedInject
class RoomNotificationSettingsPresenter(
private val room: JoinedRoom,
private val notificationSettingsService: NotificationSettingsService,
@Assisted private val showUserDefinedSettingStyle: Boolean,
) : Presenter<RoomNotificationSettingsState> {
@AssistedFactory
interface Factory {
fun create(showUserDefinedSettingStyle: Boolean): RoomNotificationSettingsPresenter
}
@Composable
override fun present(): RoomNotificationSettingsState {
var shouldDisplayMentionsOnlyDisclaimer by remember { mutableStateOf(false) }
val defaultRoomNotificationMode: MutableState<RoomNotificationMode?> = rememberSaveable {
mutableStateOf(null)
}
val localCoroutineScope = rememberCoroutineScope()
val setNotificationSettingAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val restoreDefaultAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val roomNotificationSettings: MutableState<AsyncData<RoomNotificationSettings>> = remember {
mutableStateOf(AsyncData.Uninitialized)
}
// We store state of which mode the user has set via the notification service before the new push settings have been updated.
// We show this state immediately to the user and debounce updates to notification settings to hide some invalid states returned
// by the rust sdk during these two events that cause the radio buttons ot toggle quickly back and forth.
// This is a client side work-around until bulk push rule updates are supported.
// ref: https://github.com/matrix-org/matrix-spec-proposals/pull/3934
val pendingRoomNotificationMode: MutableState<RoomNotificationMode?> = remember {
mutableStateOf(null)
}
// We store state of whether the user has set the notifications settings to default or custom via the notification service.
// We show this state immediately to the user and debounce updates to notification settings to hide some invalid states returned
// by the rust sdk during these two events that cause the switch ot toggle quickly back and forth.
// This is a client side work-around until bulk push rule updates are supported.
// ref: https://github.com/matrix-org/matrix-spec-proposals/pull/3934
val pendingSetDefault: MutableState<Boolean?> = remember {
mutableStateOf(null)
}
val displayName by produceState(room.info().name) {
room.roomInfoFlow.collect { value = it.name }
}
val isRoomEncrypted by produceState(room.info().isEncrypted) {
room.roomInfoFlow.collect { value = it.isEncrypted }
}
LaunchedEffect(Unit) {
getDefaultRoomNotificationMode(defaultRoomNotificationMode)
fetchNotificationSettings(pendingRoomNotificationMode, roomNotificationSettings)
observeNotificationSettings(pendingRoomNotificationMode, roomNotificationSettings)
}
LaunchedEffect(isRoomEncrypted) {
shouldDisplayMentionsOnlyDisclaimer = isRoomEncrypted == true &&
!notificationSettingsService.canHomeServerPushEncryptedEventsToDevice().getOrDefault(true)
}
fun handleEvent(event: RoomNotificationSettingsEvents) {
when (event) {
is RoomNotificationSettingsEvents.ChangeRoomNotificationMode -> {
localCoroutineScope.setRoomNotificationMode(event.mode, pendingRoomNotificationMode, pendingSetDefault, setNotificationSettingAction)
}
is RoomNotificationSettingsEvents.SetNotificationMode -> {
if (event.isDefault) {
localCoroutineScope.restoreDefaultRoomNotificationMode(restoreDefaultAction, pendingSetDefault)
} else {
defaultRoomNotificationMode.value?.let {
localCoroutineScope.setRoomNotificationMode(it, pendingRoomNotificationMode, pendingSetDefault, setNotificationSettingAction)
}
}
}
is RoomNotificationSettingsEvents.DeleteCustomNotification -> {
localCoroutineScope.restoreDefaultRoomNotificationMode(restoreDefaultAction, pendingSetDefault)
}
RoomNotificationSettingsEvents.ClearSetNotificationError -> {
setNotificationSettingAction.value = AsyncAction.Uninitialized
}
RoomNotificationSettingsEvents.ClearRestoreDefaultError -> {
restoreDefaultAction.value = AsyncAction.Uninitialized
}
}
}
return RoomNotificationSettingsState(
showUserDefinedSettingStyle = showUserDefinedSettingStyle,
roomName = displayName.orEmpty(),
roomNotificationSettings = roomNotificationSettings.value,
pendingRoomNotificationMode = pendingRoomNotificationMode.value,
pendingSetDefault = pendingSetDefault.value,
defaultRoomNotificationMode = defaultRoomNotificationMode.value,
setNotificationSettingAction = setNotificationSettingAction.value,
restoreDefaultAction = restoreDefaultAction.value,
displayMentionsOnlyDisclaimer = shouldDisplayMentionsOnlyDisclaimer,
eventSink = ::handleEvent,
)
}
@OptIn(FlowPreview::class)
private fun CoroutineScope.observeNotificationSettings(
pendingModeState: MutableState<RoomNotificationMode?>,
roomNotificationSettings: MutableState<AsyncData<RoomNotificationSettings>>
) {
notificationSettingsService.notificationSettingsChangeFlow
.debounce(0.5.seconds)
.onEach {
fetchNotificationSettings(pendingModeState, roomNotificationSettings)
}
.launchIn(this)
}
private fun CoroutineScope.fetchNotificationSettings(
pendingModeState: MutableState<RoomNotificationMode?>,
roomNotificationSettings: MutableState<AsyncData<RoomNotificationSettings>>
) = launch {
suspend {
val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow()
pendingModeState.value = null
notificationSettingsService.getRoomNotificationSettings(room.roomId, isEncrypted, room.isOneToOne).getOrThrow()
}.runCatchingUpdatingState(roomNotificationSettings)
}
private fun CoroutineScope.getDefaultRoomNotificationMode(
defaultRoomNotificationMode: MutableState<RoomNotificationMode?>
) = launch {
val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow()
defaultRoomNotificationMode.value = notificationSettingsService.getDefaultRoomNotificationMode(
isEncrypted,
room.isOneToOne
).getOrThrow()
}
private fun CoroutineScope.setRoomNotificationMode(
mode: RoomNotificationMode,
pendingModeState: MutableState<RoomNotificationMode?>,
pendingDefaultState: MutableState<Boolean?>,
action: MutableState<AsyncAction<Unit>>
) = launch {
suspendWithMinimumDuration {
pendingModeState.value = mode
pendingDefaultState.value = false
val result = notificationSettingsService.setRoomNotificationMode(room.roomId, mode)
if (result.isFailure) {
pendingModeState.value = null
pendingDefaultState.value = null
}
result.getOrThrow()
}.runCatchingUpdatingState(action)
}
private fun CoroutineScope.restoreDefaultRoomNotificationMode(
action: MutableState<AsyncAction<Unit>>,
pendingDefaultState: MutableState<Boolean?>
) = launch {
suspendWithMinimumDuration {
pendingDefaultState.value = true
val result = notificationSettingsService.restoreDefaultRoomNotificationMode(room.roomId)
if (result.isFailure) {
pendingDefaultState.value = null
}
result.getOrThrow()
}.runCatchingUpdatingState(action)
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
data class RoomNotificationSettingsState(
val showUserDefinedSettingStyle: Boolean,
val roomName: String,
val roomNotificationSettings: AsyncData<RoomNotificationSettings>,
val pendingRoomNotificationMode: RoomNotificationMode?,
val pendingSetDefault: Boolean?,
val defaultRoomNotificationMode: RoomNotificationMode?,
val setNotificationSettingAction: AsyncAction<Unit>,
val restoreDefaultAction: AsyncAction<Unit>,
val displayMentionsOnlyDisclaimer: Boolean,
val eventSink: (RoomNotificationSettingsEvents) -> Unit
)
val RoomNotificationSettingsState.displayNotificationMode: RoomNotificationMode? get() {
return pendingRoomNotificationMode ?: roomNotificationSettings.dataOrNull()?.mode
}
val RoomNotificationSettingsState.displayIsDefault: Boolean? get() {
return pendingSetDefault ?: roomNotificationSettings.dataOrNull()?.isDefault
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.roomdetails.impl.aRoomNotificationSettings
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
internal class RoomNotificationSettingsStateProvider : PreviewParameterProvider<RoomNotificationSettingsState> {
override val values: Sequence<RoomNotificationSettingsState>
get() = sequenceOf(
aRoomNotificationSettingsState(),
aRoomNotificationSettingsState(isDefault = false),
aRoomNotificationSettingsState(setNotificationSettingAction = AsyncAction.Loading),
aRoomNotificationSettingsState(setNotificationSettingAction = AsyncAction.Failure(RuntimeException("error"))),
aRoomNotificationSettingsState(restoreDefaultAction = AsyncAction.Loading),
aRoomNotificationSettingsState(restoreDefaultAction = AsyncAction.Failure(RuntimeException("error"))),
aRoomNotificationSettingsState(displayMentionsOnlyDisclaimer = true)
)
private fun aRoomNotificationSettingsState(
isDefault: Boolean = true,
setNotificationSettingAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
restoreDefaultAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
displayMentionsOnlyDisclaimer: Boolean = false,
): RoomNotificationSettingsState {
return RoomNotificationSettingsState(
showUserDefinedSettingStyle = false,
roomName = "Room 1",
AsyncData.Success(aRoomNotificationSettings(
mode = RoomNotificationMode.MUTE,
isDefault = isDefault
)),
pendingRoomNotificationMode = null,
pendingSetDefault = null,
defaultRoomNotificationMode = RoomNotificationMode.ALL_MESSAGES,
setNotificationSettingAction = setNotificationSettingAction,
restoreDefaultAction = restoreDefaultAction,
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
eventSink = { },
)
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.core.bool.orTrue
import io.element.android.libraries.designsystem.components.ClickableLinkText
import io.element.android.libraries.designsystem.components.async.AsyncActionView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun RoomNotificationSettingsView(
state: RoomNotificationSettingsState,
onShowGlobalNotifications: () -> Unit,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
if (state.showUserDefinedSettingStyle) {
UserDefinedRoomNotificationSettingsView(
state = state,
modifier = modifier,
onBackClick = onBackClick,
)
} else {
RoomSpecificNotificationSettingsView(
state = state,
modifier = modifier,
onShowGlobalNotifications = onShowGlobalNotifications,
onBackClick = onBackClick,
)
}
}
@Composable
private fun RoomSpecificNotificationSettingsView(
state: RoomNotificationSettingsState,
onShowGlobalNotifications: () -> Unit,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Scaffold(
modifier = modifier,
topBar = {
RoomNotificationSettingsTopBar(
onBackClick = { onBackClick() }
)
}
) { padding ->
Column(
modifier = Modifier
.fillMaxWidth()
.padding(padding)
.consumeWindowInsets(padding),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
val roomNotificationSettings = state.roomNotificationSettings.dataOrNull()
PreferenceSwitch(
isChecked = !state.displayIsDefault.orTrue(),
onCheckedChange = {
state.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(!it))
},
title = stringResource(id = R.string.screen_room_notification_settings_allow_custom),
subtitle = stringResource(id = R.string.screen_room_notification_settings_allow_custom_footnote),
enabled = roomNotificationSettings != null
)
if (state.displayIsDefault.orTrue()) {
PreferenceCategory(title = stringResource(id = R.string.screen_room_notification_settings_default_setting_title)) {
val text = buildAnnotatedStringWithStyledPart(
R.string.screen_room_notification_settings_default_setting_footnote,
R.string.screen_room_notification_settings_default_setting_footnote_content_link,
color = Color.Unspecified,
underline = false,
bold = true,
)
ClickableLinkText(
annotatedString = text,
onClick = {
onShowGlobalNotifications()
},
modifier = Modifier
.padding(start = 16.dp, bottom = 16.dp, end = 16.dp),
style = ElementTheme.typography.fontBodyMdRegular
.copy(
color = ElementTheme.colors.textSecondary,
)
)
if (state.defaultRoomNotificationMode != null) {
val defaultModeTitle = when (state.defaultRoomNotificationMode) {
RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_room_notification_settings_mode_all_messages)
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> {
stringResource(id = R.string.screen_room_notification_settings_mode_mentions_and_keywords)
}
RoomNotificationMode.MUTE -> stringResource(id = CommonStrings.common_mute)
}
val displayMentionsOnlyDisclaimer = state.displayMentionsOnlyDisclaimer &&
state.defaultRoomNotificationMode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
RoomNotificationSettingsOption(
roomNotificationSettingsItem = RoomNotificationSettingsItem(state.defaultRoomNotificationMode, defaultModeTitle),
isSelected = true,
onSelectOption = { },
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
enabled = true
)
}
}
} else {
PreferenceCategory(title = stringResource(id = R.string.screen_room_notification_settings_custom_settings_title)) {
RoomNotificationSettingsOptions(
selected = state.displayNotificationMode,
enabled = !state.displayIsDefault.orTrue(),
displayMentionsOnlyDisclaimer = state.displayMentionsOnlyDisclaimer,
onSelectOption = {
state.eventSink(RoomNotificationSettingsEvents.ChangeRoomNotificationMode(it.mode))
},
)
}
}
AsyncActionView(
async = state.setNotificationSettingAction,
onSuccess = {},
errorMessage = { stringResource(R.string.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearSetNotificationError) },
)
AsyncActionView(
async = state.restoreDefaultAction,
onSuccess = {},
errorMessage = { stringResource(R.string.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearRestoreDefaultError) },
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun RoomNotificationSettingsTopBar(
onBackClick: () -> Unit,
) {
TopAppBar(
titleStr = stringResource(R.string.screen_room_details_notification_title),
navigationIcon = { BackButton(onClick = onBackClick) },
)
}
@PreviewsDayNight
@Composable
internal fun RoomNotificationSettingsViewPreview(
@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState
) = ElementPreview {
RoomNotificationSettingsView(
state = state,
onShowGlobalNotifications = {},
onBackClick = {},
)
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.roomdetails.impl.aRoomNotificationSettings
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
internal class UserDefinedRoomNotificationSettingsStateProvider : PreviewParameterProvider<RoomNotificationSettingsState> {
override val values: Sequence<RoomNotificationSettingsState>
get() = sequenceOf(
RoomNotificationSettingsState(
showUserDefinedSettingStyle = false,
roomName = "Room 1",
AsyncData.Success(
aRoomNotificationSettings(
mode = RoomNotificationMode.MUTE,
isDefault = false
)
),
pendingRoomNotificationMode = null,
pendingSetDefault = null,
defaultRoomNotificationMode = RoomNotificationMode.ALL_MESSAGES,
setNotificationSettingAction = AsyncAction.Uninitialized,
restoreDefaultAction = AsyncAction.Uninitialized,
displayMentionsOnlyDisclaimer = false,
eventSink = { },
),
)
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.core.bool.orTrue
import io.element.android.libraries.designsystem.components.async.AsyncActionView
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
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.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
@Composable
fun UserDefinedRoomNotificationSettingsView(
state: RoomNotificationSettingsState,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Scaffold(
modifier = modifier,
topBar = {
UserDefinedRoomNotificationSettingsTopBar(
roomName = state.roomName,
onBackClick = { onBackClick() }
)
}
) { padding ->
Column(
modifier = Modifier
.fillMaxWidth()
.padding(padding)
.consumeWindowInsets(padding),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
val roomNotificationSettings = state.roomNotificationSettings.dataOrNull()
if (roomNotificationSettings != null && state.displayNotificationMode != null) {
RoomNotificationSettingsOptions(
selected = state.displayNotificationMode,
enabled = !state.displayIsDefault.orTrue(),
displayMentionsOnlyDisclaimer = state.displayMentionsOnlyDisclaimer,
onSelectOption = {
state.eventSink(RoomNotificationSettingsEvents.ChangeRoomNotificationMode(it.mode))
},
)
}
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_notification_settings_edit_remove_setting)) },
style = ListItemStyle.Destructive,
onClick = {
state.eventSink(RoomNotificationSettingsEvents.DeleteCustomNotification)
}
)
AsyncActionView(
async = state.setNotificationSettingAction,
onSuccess = {},
errorMessage = { stringResource(R.string.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearSetNotificationError) },
)
AsyncActionView(
async = state.restoreDefaultAction,
onSuccess = { onBackClick() },
errorMessage = { stringResource(R.string.screen_notification_settings_edit_failed_updating_default_mode) },
onErrorDismiss = { state.eventSink(RoomNotificationSettingsEvents.ClearRestoreDefaultError) },
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun UserDefinedRoomNotificationSettingsTopBar(
roomName: String,
onBackClick: () -> Unit,
) {
TopAppBar(
titleStr = roomName,
navigationIcon = { BackButton(onClick = onBackClick) },
)
}
@PreviewsDayNight
@Composable
internal fun UserDefinedRoomNotificationSettingsViewPreview(
@PreviewParameter(UserDefinedRoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState
) = ElementPreview {
UserDefinedRoomNotificationSettingsView(
state = state,
onBackClick = {},
)
}

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Пры абнаўленні налад апавяшчэнняў адбылася памылка."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш хатні сервер не падтрымлівае гэтую опцыю ў зашыфраваных пакоях, вы можаце не атрымаць апавяшчэнне ў некаторых пакоях."</string>
<string name="screen_polls_history_title">"Апытанні"</string>
<string name="screen_room_change_permissions_administrators">"Толькі адміністратары"</string>
<string name="screen_room_change_permissions_ban_people">"Заблакіраваць людзей"</string>
<string name="screen_room_change_permissions_delete_messages">"Выдаліць паведамленні"</string>
<string name="screen_room_change_permissions_invite_people">"Запрашайце людзей і прымайце запыты на далучэнне"</string>
<string name="screen_room_change_permissions_messages_and_content">"Паведамленні і змест"</string>
<string name="screen_room_change_permissions_moderators">"Адміністратары і мадэратары"</string>
<string name="screen_room_change_permissions_remove_people">"Выдаляйце людзей і адхіляйце запыты на далучэнне"</string>
<string name="screen_room_change_permissions_room_avatar">"Змяніць аватар пакоя"</string>
<string name="screen_room_change_permissions_room_details">"Рэдагаваць пакой"</string>
<string name="screen_room_change_permissions_room_name">"Змяніць назву пакоя"</string>
<string name="screen_room_change_permissions_room_topic">"Змяніць тэму пакоя"</string>
<string name="screen_room_change_permissions_send_messages">"Адправіць паведамленні"</string>
<string name="screen_room_change_role_administrators_title">"Рэдагаваць адміністратараў"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Вы не зможаце адмяніць гэта дзеянне. Вы прасоўваеце карыстальніка да таго ж узроўню магутнасці, што і вы."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Дадаць адміністратара?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Паніжэнне ўзроўню"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Вы не зможаце адмяніць гэтае змяненне, бо паніжаеце сябе. Калі вы апошні адміністратар у пакоі, вярнуць права будзе немагчыма."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Панізіць сябе?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (У чаканні)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(У чаканні)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Адміністратары аўтаматычна маюць права мадэратара"</string>
<string name="screen_room_change_role_moderators_title">"Рэдагаваць мадэратараў"</string>
<string name="screen_room_change_role_section_administrators">"Адміністратары"</string>
<string name="screen_room_change_role_section_moderators">"Мадэратары"</string>
<string name="screen_room_change_role_section_users">"Удзельнікі"</string>
<string name="screen_room_change_role_unsaved_changes_description">"У вас ёсць незахаваныя змены."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Захаваць змены?"</string>
<string name="screen_room_details_add_topic_title">"Дадаць тэму"</string>
<string name="screen_room_details_badge_encrypted">"Зашыфраваны"</string>
<string name="screen_room_details_badge_not_encrypted">"Не зашыфраваны"</string>
<string name="screen_room_details_badge_public">"Публічны пакой"</string>
<string name="screen_room_details_edit_room_title">"Рэдагаваць пакой"</string>
<string name="screen_room_details_edition_error">"Адбылася невядомая памылка, і інфармацыю нельга было змяніць."</string>
<string name="screen_room_details_edition_error_title">"Немагчыма абнавіць пакой"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Паведамленні зашыфраваны. Толькі ў вас і ў атрымальнікаў ёсць унікальныя ключы для іх разблакіроўкі."</string>
<string name="screen_room_details_encryption_enabled_title">"Шыфраванне паведамленняў уключана"</string>
<string name="screen_room_details_error_loading_notification_settings">"Пры загрузцы налад апавяшчэнняў адбылася памылка."</string>
<string name="screen_room_details_error_muting">"Не атрымалася адключыць гук у гэтым пакоі, паўтарыце спробу."</string>
<string name="screen_room_details_error_unmuting">"Не ўдалося ўключыць гук у гэтым пакоі. Паўтарыце спробу."</string>
<string name="screen_room_details_invite_people_title">"Запрасіць карыстальнікаў"</string>
<string name="screen_room_details_leave_conversation_title">"Пакінуць размову"</string>
<string name="screen_room_details_leave_room_title">"Пакінуць пакой"</string>
<string name="screen_room_details_notification_mode_custom">"Уласныя"</string>
<string name="screen_room_details_notification_mode_default">"Стандартныя"</string>
<string name="screen_room_details_notification_title">"Апавяшчэнні"</string>
<string name="screen_room_details_pinned_events_row_title">"Замацаваныя паведамленні"</string>
<string name="screen_room_details_profile_row_title">"Профіль"</string>
<string name="screen_room_details_roles_and_permissions">"Ролі і дазволы"</string>
<string name="screen_room_details_room_name_label">"Назва пакоя"</string>
<string name="screen_room_details_security_title">"Бяспека"</string>
<string name="screen_room_details_share_room_title">"Падзяліцца пакоем"</string>
<string name="screen_room_details_title">"Інфармацыя аб пакоі"</string>
<string name="screen_room_details_topic_title">"Тэма"</string>
<string name="screen_room_details_updating_room">"Ідзе абнаўленне пакоя…"</string>
<string name="screen_room_member_list_banned_empty">"У гэтым пакоі няма заблакіраваных удзельнікаў."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d удзельнік"</item>
<item quantity="few">"%1$d удзельнікі"</item>
<item quantity="many">"%1$d удзельнікаў"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Выдаліць і заблакіраваць удзельніка"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Толькі выдаліць удзельніка"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Разблакіраваць"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Яны змогуць зноў далучыцца да гэтага пакоя, калі іх запросяць."</string>
<string name="screen_room_member_list_mode_banned">"Заблакіраваныя"</string>
<string name="screen_room_member_list_mode_members">"Удзельнікі"</string>
<string name="screen_room_member_list_role_administrator">"Толькі адміністратары"</string>
<string name="screen_room_member_list_role_moderator">"Адміністратары і мадэратары"</string>
<string name="screen_room_member_list_room_members_header_title">"Удзельнікі пакоя"</string>
<string name="screen_room_member_list_unbanning_user">"Разблакіроўка %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Дазволіць уласную наладу"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Калі гэта ўключыць, ваша налада прадвызначана будзе адменена"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Апавяшчаць мяне ў гэтым чаце для"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Вы можаце змяніць гэта ў %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"асноўных наладах"</string>
<string name="screen_room_notification_settings_default_setting_title">"Стандартная налада"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Выдаліць карыстальніцкую наладу"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Падчас загрузкі налад апавяшчэнняў адбылася памылка."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Не атрымалася аднавіць прадвызначаны рэжым, паспрабуйце яшчэ раз."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Не ўдалося наладзіць рэжым, паспрабуйце яшчэ раз."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Ваш хатні сервер не падтрымлівае гэту опцыю ў зашыфраваных пакоях, вы не атрымаеце апавяшчэнне ў гэтым пакоі."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Усе паведамленні"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Толькі згадванні і ключавыя словы"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"У гэтым пакоі паведаміце мяне пра"</string>
<string name="screen_room_roles_and_permissions_admins">"Адміністратары"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Змяніць маю роль"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Панізіць да ўдзельніка"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Панізіць да мадэратара"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Мадэрацыя ўдзельнікаў"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Паведамленні і змест"</string>
<string name="screen_room_roles_and_permissions_moderators">"Мадэратары"</string>
<string name="screen_room_roles_and_permissions_reset">"Скінуць дазволы"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Пасля скіду дазволаў вы страціце бягучыя налады."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Скінуць дазволы?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Ролі"</string>
<string name="screen_room_roles_and_permissions_room_details">"Дэталі пакоя"</string>
<string name="screen_room_roles_and_permissions_title">"Ролі і дазволы"</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Папрасіце далучыцца"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Хто заўгодна"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Хто заўгодна"</string>
</resources>

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Възникна грешка при обновяването на настройките за известия."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Вашият сървър не поддържа тази опция в шифровани стаи, може да не получавате известия в някои стаи."</string>
<string name="screen_polls_history_title">"Анкети"</string>
<string name="screen_room_change_permissions_administrators">"Само администратори"</string>
<string name="screen_room_change_permissions_delete_messages">"Премахване на съобщения"</string>
<string name="screen_room_change_permissions_invite_people">"Поканване на хора и приемане на заявки за присъединяване"</string>
<string name="screen_room_change_permissions_messages_and_content">"Съобщения и съдържание"</string>
<string name="screen_room_change_permissions_moderators">"Администратори и модератори"</string>
<string name="screen_room_change_permissions_remove_people">"Премахване на хора и отхвърляне на заявки за присъединяване"</string>
<string name="screen_room_change_permissions_room_details">"Редактиране на стаята"</string>
<string name="screen_room_change_permissions_room_name">"Промяна на името на стаята"</string>
<string name="screen_room_change_permissions_room_topic">"Промяна на темата на стаята"</string>
<string name="screen_room_change_permissions_send_messages">"Изпращане на съобщения"</string>
<string name="screen_room_change_role_administrators_title">"Редактиране на администраторите"</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Добавяне на администратор?"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Администраторите автоматично имат модераторски права"</string>
<string name="screen_room_change_role_moderators_title">"Редактиране на модераторите"</string>
<string name="screen_room_change_role_section_administrators">"Администратори"</string>
<string name="screen_room_change_role_section_moderators">"Модератори"</string>
<string name="screen_room_change_role_section_users">"Членове"</string>
<string name="screen_room_details_add_topic_title">"Добавяне на тема"</string>
<string name="screen_room_details_badge_encrypted">"С шифроване"</string>
<string name="screen_room_details_badge_not_encrypted">"Без шифроване"</string>
<string name="screen_room_details_badge_public">"Общодостъпна стая"</string>
<string name="screen_room_details_edit_room_title">"Редактиране на стаята"</string>
<string name="screen_room_details_edition_error">"Възникна неизвестна грешка и информацията не можа да бъде променена."</string>
<string name="screen_room_details_edition_error_title">"Не може да се обнови стаята"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Съобщенията са защитени с ключове. Само вие и получателите имате уникалните ключове, за да ги отключите."</string>
<string name="screen_room_details_encryption_enabled_title">"Шифроването на съобщенията е включено"</string>
<string name="screen_room_details_error_loading_notification_settings">"Възникна грешка при зареждането на настройките за известия."</string>
<string name="screen_room_details_error_muting">"Неуспешно заглушаване на тази стая, моля, опитайте отново."</string>
<string name="screen_room_details_error_unmuting">"Неуспешно раззаглушаване на тази стая, моля, опитайте отново."</string>
<string name="screen_room_details_invite_people_title">"Поканване на хора"</string>
<string name="screen_room_details_leave_conversation_title">"Напускане на разговора"</string>
<string name="screen_room_details_leave_room_title">"Напускане на стаята"</string>
<string name="screen_room_details_media_gallery_title">"Медия и файлове"</string>
<string name="screen_room_details_notification_mode_custom">"Персонализирани"</string>
<string name="screen_room_details_notification_mode_default">"По подразбиране"</string>
<string name="screen_room_details_notification_title">"Известия"</string>
<string name="screen_room_details_pinned_events_row_title">"Закачени съобщения"</string>
<string name="screen_room_details_profile_row_title">"Профил"</string>
<string name="screen_room_details_roles_and_permissions">"Роли и разрешения"</string>
<string name="screen_room_details_room_name_label">"Име на стаята"</string>
<string name="screen_room_details_security_and_privacy_title">"Защита и поверителност"</string>
<string name="screen_room_details_security_title">"Защита"</string>
<string name="screen_room_details_share_room_title">"Споделяне на стаята"</string>
<string name="screen_room_details_title">"Информация за стаята"</string>
<string name="screen_room_details_topic_title">"Тема"</string>
<string name="screen_room_details_updating_room">"Обновяване на стаята…"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d човек"</item>
<item quantity="other">"%1$d души"</item>
</plurals>
<string name="screen_room_member_list_mode_members">"Членове"</string>
<string name="screen_room_member_list_role_administrator">"Само администратори"</string>
<string name="screen_room_member_list_role_moderator">"Администратори и модератори"</string>
<string name="screen_room_member_list_room_members_header_title">"Членове на стаята"</string>
<string name="screen_room_notification_settings_allow_custom">"Разрешаване на персонализирана настройка"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Включването на това ще замени вашата настройка по подразбиране"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Да бъда известяван в този чат за"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Можете да го промените във вашите %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"глобални настройки"</string>
<string name="screen_room_notification_settings_default_setting_title">"Настройка по подразбиране"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Премахване на персонализираната настройка"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Възникна грешка при зареждането на настройките за известия."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Неуспешно възстановяване на режима по подразбиране, моля, опитайте отново."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Неуспешно задаване на режима, моля, опитайте отново."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Всички съобщения"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Само споменавания и ключови думи"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"В тази стая, да бъда известяван за"</string>
<string name="screen_room_roles_and_permissions_admins">"Администратори"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Промяна на моята роля"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Модериране на членове"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Съобщения и съдържание"</string>
<string name="screen_room_roles_and_permissions_moderators">"Модератори"</string>
<string name="screen_room_roles_and_permissions_reset">"Нулиране на разрешенията"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Роли"</string>
<string name="screen_room_roles_and_permissions_room_details">"Подробности за стаята"</string>
<string name="screen_room_roles_and_permissions_title">"Роли и разрешения"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Добавяне на адрес на стаята"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Да, включване на шифроването"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Да се включи ли шифроването?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Веднъж включено, шифроването не може да бъде изключено."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Шифроване"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Включване на шифроване от край до край"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Всеки може да намери и да се присъедини"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Всеки"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Хората могат да се присъединят само ако са поканени"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Само с покана"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Достъп до стаята"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Членове на пространството"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Пространствата в момента не се поддържат"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Видима в директорията на обществените стаи"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Всеки"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Кой може да чете историята"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Само за членове откакто са поканени"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Само за членове от избирането на тази опция"</string>
<string name="screen_security_and_privacy_title">"Защита и поверителност"</string>
</resources>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Budete potřebovat adresu místnosti, aby byla viditelná v adresáři místností."</string>
<string name="screen_edit_room_address_title">"Upravit adresu"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Při aktualizaci nastavení oznámení došlo k chybě."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Váš domovský server tuto možnost v zašifrovaných místnostech nepodporuje, v některých místnostech nemusíte být upozorněni."</string>
<string name="screen_polls_history_title">"Hlasování"</string>
<string name="screen_room_change_permissions_administrators">"Správce"</string>
<string name="screen_room_change_permissions_ban_people">"Vykázat lidi"</string>
<string name="screen_room_change_permissions_delete_messages">"Odstranit zprávy"</string>
<string name="screen_room_change_permissions_everyone">"Člen"</string>
<string name="screen_room_change_permissions_invite_people">"Pozvat přátele"</string>
<string name="screen_room_change_permissions_member_moderation">"Spravovat členy"</string>
<string name="screen_room_change_permissions_messages_and_content">"Zprávy a obsah"</string>
<string name="screen_room_change_permissions_moderators">"Moderátor"</string>
<string name="screen_room_change_permissions_remove_people">"Odebrat osoby"</string>
<string name="screen_room_change_permissions_room_avatar">"Změnit avatar místnosti"</string>
<string name="screen_room_change_permissions_room_details">"Upravit podrobnosti"</string>
<string name="screen_room_change_permissions_room_name">"Změnit název místnosti"</string>
<string name="screen_room_change_permissions_room_topic">"Změnit téma místnosti"</string>
<string name="screen_room_change_permissions_send_messages">"Odeslat zprávy"</string>
<string name="screen_room_change_role_administrators_title">"Upravit správce"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Tuto akci nebudete moci vrátit zpět. Upravujete oprávnění uživatele, tak aby měl stejnou úroveň jako vy."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Přidat správce?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Tuto akci nebudete moci vrátit zpět. Převádíte vlastnictví na vybrané uživatele. Jakmile tuto akci opustíte, bude tato změna trvalá."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Převést vlastnictví?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Degradovat"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Tuto změnu nebudete moci vrátit zpět, protože sami degradujete, pokud jste posledním privilegovaným uživatelem v místnosti, nebude možné znovu získat oprávnění."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Degradovat se?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (čekající)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Čeká na vyřízení)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Správci mají automaticky oprávnění moderátora"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Vlastníci mají automaticky administrátorská oprávnění."</string>
<string name="screen_room_change_role_moderators_title">"Upravit moderátory"</string>
<string name="screen_room_change_role_owners_title">"Vyberte vlastníky"</string>
<string name="screen_room_change_role_section_administrators">"Správci"</string>
<string name="screen_room_change_role_section_moderators">"Moderátoři"</string>
<string name="screen_room_change_role_section_users">"Členové"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Máte neuložené změny."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Uložit změny?"</string>
<string name="screen_room_details_add_topic_title">"Přidat téma"</string>
<string name="screen_room_details_badge_encrypted">"Šifrováno"</string>
<string name="screen_room_details_badge_not_encrypted">"Není šifrováno"</string>
<string name="screen_room_details_badge_public">"Veřejná místnost"</string>
<string name="screen_room_details_edit_room_title">"Upravit podrobnosti"</string>
<string name="screen_room_details_edition_error">"Došlo k neznámé chybě a informace nebylo možné změnit."</string>
<string name="screen_room_details_edition_error_title">"Nelze aktualizovat místnost"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Zprávy jsou zabezpečeny zámky. Pouze vy a příjemci máte jedinečné klíče k jejich odemčení."</string>
<string name="screen_room_details_encryption_enabled_title">"Šifrování zpráv povoleno"</string>
<string name="screen_room_details_error_loading_notification_settings">"Při načítání nastavení oznámení došlo k chybě."</string>
<string name="screen_room_details_error_muting">"Ztišení této místnosti se nezdařilo, zkuste to prosím znovu."</string>
<string name="screen_room_details_error_unmuting">"Nepodařilo se zrušit ztišení této místnosti, zkuste to prosím znovu."</string>
<string name="screen_room_details_invite_people_dont_close">"Nezavírejte aplikaci, dokud neskončíte."</string>
<string name="screen_room_details_invite_people_preparing">"Příprava pozvánek…"</string>
<string name="screen_room_details_invite_people_title">"Pozvat přátele"</string>
<string name="screen_room_details_leave_conversation_title">"Opustit konverzaci"</string>
<string name="screen_room_details_leave_room_title">"Opustit místnost"</string>
<string name="screen_room_details_media_gallery_title">"Média a soubory"</string>
<string name="screen_room_details_notification_mode_custom">"Vlastní"</string>
<string name="screen_room_details_notification_mode_default">"Výchozí"</string>
<string name="screen_room_details_notification_title">"Oznámení"</string>
<string name="screen_room_details_pinned_events_row_title">"Připnuté zprávy"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Žádosti o vstup"</string>
<string name="screen_room_details_roles_and_permissions">"Role a oprávnění"</string>
<string name="screen_room_details_room_name_label">"Název místnosti"</string>
<string name="screen_room_details_security_and_privacy_title">"Zabezpečení a soukromí"</string>
<string name="screen_room_details_security_title">"Zabezpečení"</string>
<string name="screen_room_details_share_room_title">"Sdílet místnost"</string>
<string name="screen_room_details_title">"Informace o místnosti"</string>
<string name="screen_room_details_topic_title">"Téma"</string>
<string name="screen_room_details_updating_room">"Aktualizace místnosti…"</string>
<string name="screen_room_member_list_banned_empty">"V této místnosti nejsou žádní vykázaní uživatelé."</string>
<plurals name="screen_room_member_list_banned_header_title">
<item quantity="one">"%1$d vykázán(a)"</item>
<item quantity="few">"%1$d vykázáni"</item>
<item quantity="other">"%1$d vykázáných"</item>
</plurals>
<string name="screen_room_member_list_empty_search_subtitle">"Zkontrolujte pravopis nebo zkuste nové vyhledávání"</string>
<string name="screen_room_member_list_empty_search_title">"Žádné výsledky pro “%1$s”"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d osoba"</item>
<item quantity="few">"%1$d osoby"</item>
<item quantity="other">"%1$d osob"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Odebrat a vykázat člena"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Pouze odebrat člena"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Zrušit vykázání"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Pokud budou pozváni, budou se moci do této místnosti znovu připojit."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Zrušit vykázání z místnosti"</string>
<string name="screen_room_member_list_mode_banned">"Vykázaní"</string>
<string name="screen_room_member_list_mode_members">"Členové"</string>
<plurals name="screen_room_member_list_pending_header_title">
<item quantity="one">"%1$d pozván(a)"</item>
<item quantity="few">"%1$d pozváni"</item>
<item quantity="other">"%1$d pozvaných"</item>
</plurals>
<string name="screen_room_member_list_pending_status">"Čekající"</string>
<string name="screen_room_member_list_role_administrator">"Správce"</string>
<string name="screen_room_member_list_role_moderator">"Moderátor"</string>
<string name="screen_room_member_list_role_owner">"Vlastník"</string>
<string name="screen_room_member_list_room_members_header_title">"Členové místnosti"</string>
<string name="screen_room_member_list_unbanning_user">"Rušení vykázání %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Povolit vlastní nastavení"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Zapnutím této funkce přepíšete výchozí nastavení"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Upozornit mě v tomto chatu na"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Můžete změnit ve vašem %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"globální nastavení"</string>
<string name="screen_room_notification_settings_default_setting_title">"Výchozí nastavení"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Odebrat vlastní nastavení"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Při načítání nastavení oznámení došlo k chybě."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Obnovení výchozího režimu se nezdařilo, zkuste to prosím znovu."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Nastavení režimu se nezdařilo, zkuste to prosím znovu."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Váš domovský server tuto možnost nepodporuje v šifrovaných místnostech, v této místnosti nebudete dostávat upozornění."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Všechny zprávy"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Pouze zmínky a klíčová slova"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"V této místnosti mě upozornit na"</string>
<string name="screen_room_roles_and_permissions_admins">"Správci"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Správci a vlastníci"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Změnit moji roli"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Degradovat na člena"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Degradovat na moderátora"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderování členů"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Zprávy a obsah"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderátoři"</string>
<string name="screen_room_roles_and_permissions_owners">"Vlastníci"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Oprávnění"</string>
<string name="screen_room_roles_and_permissions_reset">"Obnovit oprávnění"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Po obnovení oprávnění ztratíte aktuální nastavení."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Obnovit oprávnění?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Role"</string>
<string name="screen_room_roles_and_permissions_room_details">"Podrobnosti místnosti"</string>
<string name="screen_room_roles_and_permissions_title">"Role a oprávnění"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Přidat adresu"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Všichni musí požádat o přístup."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Požádat o připojení"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ano, povolit šifrování"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Po aktivaci nelze šifrování místnosti deaktivovat. Historie zpráv bude viditelná pouze pro členy místnosti od doby, kdy byli pozváni nebo od té doby, co do místnosti vstoupili.
Nikdo kromě členů místnosti nebude moci číst zprávy. To může bránit správnému fungování robotů a propojení.
Nedoporučujeme povolovat šifrování pro místnosti, které může kdokoli najít a vstoupit do nich."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Povolit šifrování?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Jakmile je povoleno, šifrování nelze zakázat."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Šifrování"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Povolit koncové šifrování"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Vstoupit může kdokoli."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Kdokoliv"</string>
<string name="screen_security_and_privacy_room_access_footer">"Vyberte, kteří členové prostorů se k této místnosti mohou připojit bez pozvánky. %1$s"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Vstoupit mohou pouze pozvaní lidé."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Pouze pro zvané"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Přístup"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_multiple_parents_description">"Vstoupit může kdokoli z autorizovaných prostorů."</string>
<string name="screen_security_and_privacy_room_access_space_members_option_single_parent_description">"Vstoupit může kdokoli v %1$s."</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Členové prostoru"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Prostory nejsou aktuálně podporovány"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Budete potřebovat adresu místnosti, aby byla viditelná v adresáři místností."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Adresa"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Umožněte nalezení této místnosti prohledáním adresáře veřejných místností na %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Umožnit nalezení vyhledáváním ve veřejném adresáři."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Viditelné ve veřejném adresáři"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Kdokoliv"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Kdo může číst historii"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Pouze členové od té doby, co byli pozváni"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Pouze členové od výběru této možnosti"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Adresy místností představují způsoby, jak najít místnosti a získat k nim přístup. Díky tomu můžete svoji místnost snadno sdílet s ostatními.
Můžete se rozhodnout publikovat svou místnost ve veřejném adresáři místnosti vašeho domovského serveru."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publikování místnosti"</string>
<string name="screen_security_and_privacy_room_visibility_section_footer">"Adresy slouží k vyhledávání a přístupu do místností a prostorů. Díky tomu je také můžete snadno sdílet s ostatními."</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Viditelnost"</string>
<string name="screen_security_and_privacy_title">"Zabezpečení a soukromí"</string>
</resources>

View File

@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Bydd angen cyfeiriad ystafell arnoch i\'w wneud yn weladwy yn y cyfeiriadur."</string>
<string name="screen_edit_room_address_title">"Cyfeiriad yr ystafell"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Digwyddodd gwall wrth ddiweddaru\'r gosodiad hysbysu."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Nid yw eich gweinydd cartref yn cefnogi\'r dewis hwn mewn ystafelloedd sydd wedi\'u hamgryptio, efallai fyddwch chi ddim yn cael gwybod mewn rhai ystafelloedd."</string>
<string name="screen_polls_history_title">"Pleidleisiau"</string>
<string name="screen_room_change_permissions_administrators">"Gweinyddwyr yn unig"</string>
<string name="screen_room_change_permissions_ban_people">"Gwahardd pobl"</string>
<string name="screen_room_change_permissions_delete_messages">"Tynnu negeseuon"</string>
<string name="screen_room_change_permissions_everyone">"Pawb"</string>
<string name="screen_room_change_permissions_invite_people">"Gwahodd pobl a derbyn ceisiadau i ymuno"</string>
<string name="screen_room_change_permissions_member_moderation">"Cymedroli aelodau"</string>
<string name="screen_room_change_permissions_messages_and_content">"Negeseuon a chynnwys"</string>
<string name="screen_room_change_permissions_moderators">"Gweinyddwyr a chymedrolwyr"</string>
<string name="screen_room_change_permissions_remove_people">"Dileu pobl a gwrthod ceisiadau i ymuno"</string>
<string name="screen_room_change_permissions_room_avatar">"Newid afatar ystafell"</string>
<string name="screen_room_change_permissions_room_details">"Ystafell Golygu"</string>
<string name="screen_room_change_permissions_room_name">"Newid enw\'r ystafell"</string>
<string name="screen_room_change_permissions_room_topic">"Newid pwnc yr ystafell"</string>
<string name="screen_room_change_permissions_send_messages">"Anfon negeseuon"</string>
<string name="screen_room_change_role_administrators_title">"Golygu Gweinyddwyr"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Fyddwch chi ddim yn gallu dadwneud y weithred hon. Rydych chi\'n hyrwyddo\'r defnyddiwr i gael yr un lefel pŵer â chi."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Ychwanegu Gweinyddwr?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Fyddwch chi ddim yn gallu dadwneud y weithred hon. Rydych yn trosglwyddo\'r berchnogaeth i\'r defnyddwyr a ddewiswyd. Unwaith y byddwch yn gadael bydd hyn yn barhaol."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Trosglwyddo perchnogaeth?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Gostwng"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Fyddwch chi ddim yn gallu dadwneud y newid hwn gan eich bod yn israddio eich hun, os mai chi yw\'r defnyddiwr breintiedig olaf yn yr ystafell bydd yn amhosibl adennill breintiau."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Israddio eich hun?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Yn aros)"</string>
<string name="screen_room_change_role_invited_member_name_android">"Yn aros"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Mae gan weinyddwyr freintiau cymedrolwr yn awtomatig"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Mae gan berchnogion freintiau gweinyddwr yn awtomatig."</string>
<string name="screen_room_change_role_moderators_title">"Golygu Cymedrolwyr"</string>
<string name="screen_room_change_role_owners_title">"Dewiswch Berchnogion"</string>
<string name="screen_room_change_role_section_administrators">"Gweinyddwyr"</string>
<string name="screen_room_change_role_section_moderators">"Cymedrolwyr"</string>
<string name="screen_room_change_role_section_users">"Aelodau"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Mae gennych newidiadau heb eu cadw."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Cadw\'r newidiadau?"</string>
<string name="screen_room_details_add_topic_title">"Ychwanegu pwnc"</string>
<string name="screen_room_details_badge_encrypted">"Wedi\'i amgryptio"</string>
<string name="screen_room_details_badge_not_encrypted">"Heb ei amgryptio"</string>
<string name="screen_room_details_badge_public">"Ystafell gyhoeddus"</string>
<string name="screen_room_details_edit_room_title">"Ystafell Golygu"</string>
<string name="screen_room_details_edition_error">"Roedd gwall anhysbys ac nid oedd modd newid y manylion."</string>
<string name="screen_room_details_edition_error_title">"Methu diweddaru\'r ystafell"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Negeseuon yn cael eu diogelu gyda chloeon. Dim ond chi a\'r derbynwyr sydd â\'r allweddi unigryw i\'w datgloi."</string>
<string name="screen_room_details_encryption_enabled_title">"Galluogwyd amgryptio neges"</string>
<string name="screen_room_details_error_loading_notification_settings">"Digwyddodd gwall wrth lwytho gosodiadau hysbysu."</string>
<string name="screen_room_details_error_muting">"Wedi methu tewi\'r ystafell hon, ceisiwch eto."</string>
<string name="screen_room_details_error_unmuting">"Wedi methu dad-dewi\'r ystafell hon, ceisiwch eto."</string>
<string name="screen_room_details_invite_people_dont_close">"Peidiwch â chau\'r ap nes ei fod wedi gorffen."</string>
<string name="screen_room_details_invite_people_preparing">"Wrthi\'n paratoi gwahoddiadau…"</string>
<string name="screen_room_details_invite_people_title">"Gwahodd pobl"</string>
<string name="screen_room_details_leave_conversation_title">"Gadael y sgwrs"</string>
<string name="screen_room_details_leave_room_title">"Gadael yr ystafell"</string>
<string name="screen_room_details_media_gallery_title">"Cyfryngau a ffeiliau"</string>
<string name="screen_room_details_notification_mode_custom">"Cyfaddas"</string>
<string name="screen_room_details_notification_mode_default">"Rhagosodiad"</string>
<string name="screen_room_details_notification_title">"Hysbysiadau"</string>
<string name="screen_room_details_pinned_events_row_title">"Negeseuon wedi\'u pinio"</string>
<string name="screen_room_details_profile_row_title">"Proffil"</string>
<string name="screen_room_details_requests_to_join_title">"Ceisiadau i ymuno"</string>
<string name="screen_room_details_roles_and_permissions">"Rolau a chaniatâd"</string>
<string name="screen_room_details_room_name_label">"Enw\'r ystafell"</string>
<string name="screen_room_details_security_and_privacy_title">"Diogelwch a phreifatrwydd"</string>
<string name="screen_room_details_security_title">"Diogelwch"</string>
<string name="screen_room_details_share_room_title">"Rhannu ystafell"</string>
<string name="screen_room_details_title">"Manylion ystafell"</string>
<string name="screen_room_details_topic_title">"Pwnc"</string>
<string name="screen_room_details_updating_room">"Wrthi\'n diweddaru ystafell…"</string>
<string name="screen_room_member_list_banned_empty">"Nid oes unrhyw ddefnyddwyr gwaharddedig yn yr ystafell hon."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="zero">"%1$d personau"</item>
<item quantity="one">"%1$d person"</item>
<item quantity="two">"%1$d berson"</item>
<item quantity="few">"%1$d person"</item>
<item quantity="many">"%1$d pherson"</item>
<item quantity="other">"%1$d person"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Gwahardd o ystafell"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Dileu aelod yn unig"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Adfer"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Fyddan nhw yn gallu ymuno â\'r ystafell hon eto os cân nhw wahoddiad."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Dad-wahardd o\'r ystafell"</string>
<string name="screen_room_member_list_mode_banned">"Wedi\'i wahardd"</string>
<string name="screen_room_member_list_mode_members">"Aelodau"</string>
<string name="screen_room_member_list_role_administrator">"Gweinyddwyr yn unig"</string>
<string name="screen_room_member_list_role_moderator">"Gweinyddwyr a chymedrolwyr"</string>
<string name="screen_room_member_list_role_owner">"Perchennog"</string>
<string name="screen_room_member_list_room_members_header_title">"Aelodau\'r ystafell"</string>
<string name="screen_room_member_list_unbanning_user">"Dad-wahardd %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Caniatáu gosodiad personol"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Bydd troi hwn ymlaen yn diystyru eich gosodiad rhagosodedig"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Rhowch wybod i mi yn y sgwrs hon am"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Gallwch ei newid yn eich %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"gosodiadau cyffredinol"</string>
<string name="screen_room_notification_settings_default_setting_title">"Gosodiad rhagosodedig"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Dileu gosodiad personol"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Digwyddodd gwall wrth lwytho gosodiadau hysbysu."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Wedi methu ag adfer y modd rhagosodedig, ceisiwch eto."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Wedi methu gosod y modd, ceisiwch eto."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Nid yw eich gweinydd cartref yn cefnogi\'r dewis hwn mewn ystafelloedd sydd wedi\'u hamgryptio, chewch chi ddim eich hysbysu yn yr ystafell hon."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Pob neges"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Crybwylliadau ac Allweddeiriau\'n unig"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Yn yr ystafell hon, rhowch wybod i mi am"</string>
<string name="screen_room_roles_and_permissions_admins">"Gweinyddwyr"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Gweinyddwyr a pherchnogion"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Newid fy rôl"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Israddio aelod"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Israddio cymedrolwr"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Cymedroli aelodau"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Negeseuon a chynnwys"</string>
<string name="screen_room_roles_and_permissions_moderators">"Cymedrolwyr"</string>
<string name="screen_room_roles_and_permissions_owners">"Perchnogion"</string>
<string name="screen_room_roles_and_permissions_reset">"Ailosod caniatâd"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Ar ôl i chi ailosod caniatâd, byddwch yn colli\'r gosodiadau cyfredol."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Ailosod caniatâd?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Rolau"</string>
<string name="screen_room_roles_and_permissions_room_details">"Manylion yr ystafell"</string>
<string name="screen_room_roles_and_permissions_title">"Rolau a chaniatâd"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Ychwanegu cyfeiriad ystafell"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Gall unrhyw un ofyn am gael ymuno â\'r ystafell ond bydd rhaid i weinyddwr neu gymedrolwr dderbyn y cais."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Gofyn i gael ymuno"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Iawn, galluogi amgryptio"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Unwaith y bydd wedi\'i alluogi, does dim modd analluogi amgryptio ar gyfer ystafell, dim ond ar gyfer aelodau\'r ystafell y bydd hanes neges yn weladwy ers iddyn nhw gael eu gwahodd neu ers iddyn nhw ymuno â\'r ystafell.
Fydd neb ar wahân i aelodau\'r ystafell yn gallu darllen negeseuon. Gall hyn atal botiau a phontydd i weithio\'n gywir.
Nid ydym yn argymell galluogi amgryptio ar gyfer ystafelloedd y gall unrhyw un ddod o hyd iddynt ac ymuno â nhw."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Galluogi amgryptio?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Unwaith y bydd wedi\'i alluogi, does dim modd analluogi amgryptio."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Amgryptiad"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Galluogi amgryptio o\'r dechrau i\'r diwedd"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Gall unrhyw un ddod o hyd iddo ac ymuno"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Unrhyw un"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Dim ond os cawn nhw wahoddiad gall pobl ymuno"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Gwahoddiad yn unig"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Mynediad ystafell"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Aelodau gofod"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Nid yw gofodau\'n cael eu cefnogi ar hyn o bryd"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Bydd angen cyfeiriad ystafell arnoch i\'w wneud yn weladwy yn y cyfeiriadur."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Cyfeiriad yr ystafell"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Caniatáu i\'r ystafell hon gael ei chanfod trwy chwilio cyfeiriadur ystafelloedd cyhoeddus %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Gweladwy yn y cyfeiriadur ystafelloedd cyhoeddus"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Unrhyw un"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Pwy all ddarllen hanes"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Yn aelodau ond dim ond ers cael eu gwahodd"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Yn aelodau dim ond ers dewis y dewis hwn"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Mae cyfeiriadau ystafelloedd yn ffyrdd o ddod o hyd i ystafelloedd a chael mynediad iddyn nhw. Mae hyn hefyd yn sicrhau y gallwch chi rannu\'ch ystafell yn hawdd ag eraill.
Gallwch ddewis cyhoeddi eich ystafell yng ngweinydd cartref eich cyfeiriadur ystafelloedd cyhoeddus."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Cyhoeddi ystafell"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Gwelededd yr ystafell"</string>
<string name="screen_security_and_privacy_title">"Diogelwch a phreifatrwydd"</string>
</resources>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Du skal bruge en rum-adresse for at gøre den synlig i kataloget."</string>
<string name="screen_edit_room_address_title">"Rummets adresse"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Der opstod en fejl under opdatering af notifikationsindstillingen."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Din hjemmeserver understøtter ikke denne mulighed i krypterede rum, og derfor er det muligt at du ikke får besked i alle rum."</string>
<string name="screen_polls_history_title">"Afstemninger"</string>
<string name="screen_room_change_permissions_administrators">"Kun admins"</string>
<string name="screen_room_change_permissions_ban_people">"Spær brugere"</string>
<string name="screen_room_change_permissions_delete_messages">"Fjern beskeder"</string>
<string name="screen_room_change_permissions_invite_people">"Invitér personer og acceptér anmodninger om at deltage"</string>
<string name="screen_room_change_permissions_messages_and_content">"Beskeder og indhold"</string>
<string name="screen_room_change_permissions_moderators">"Admins og moderatorer"</string>
<string name="screen_room_change_permissions_remove_people">"Fjern personer og afvis anmodninger om at deltage"</string>
<string name="screen_room_change_permissions_room_avatar">"Skift rummets avatar"</string>
<string name="screen_room_change_permissions_room_details">"Rediger rum"</string>
<string name="screen_room_change_permissions_room_name">"Skift rummets navn"</string>
<string name="screen_room_change_permissions_room_topic">"Skift emne for rummet"</string>
<string name="screen_room_change_permissions_send_messages">"Send beskeder"</string>
<string name="screen_room_change_role_administrators_title">"Redigér admins"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Du kan ikke fortryde denne handling. Du forfremmer brugeren til at have samme magtniveau som dig."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Tilføj Admin?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Du kan ikke fortryde denne handling. Du overfører ejerskabet til de valgte brugere. Når du forlader siden, vil dette være permanent."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Overdrag ejerskab?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Nedgradering"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Du vil ikke være i stand til at fortryde denne ændring, da du degraderer dig selv. Hvis du er den sidste privilegerede bruger i rummet, vil det være umuligt at genvinde privilegier."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Nedgrader dig selv?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Afventer)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Afventer)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Administratorer har automatisk moderatorrettigheder"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Ejere har automatisk administratorrettigheder."</string>
<string name="screen_room_change_role_moderators_title">"Redigér moderatorer"</string>
<string name="screen_room_change_role_owners_title">"Vælg ejere"</string>
<string name="screen_room_change_role_section_administrators">"Administratorer"</string>
<string name="screen_room_change_role_section_moderators">"Moderatorer"</string>
<string name="screen_room_change_role_section_users">"Medlemmer"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Du har ændringer, der ikke er gemt."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Gem ændringer?"</string>
<string name="screen_room_details_add_topic_title">"Tilføj emne"</string>
<string name="screen_room_details_badge_encrypted">"Krypteret"</string>
<string name="screen_room_details_badge_not_encrypted">"Ikke krypteret"</string>
<string name="screen_room_details_badge_public">"Offentligt rum"</string>
<string name="screen_room_details_edit_room_title">"Rediger rum"</string>
<string name="screen_room_details_edition_error">"Der opstod en ukendt fejl, og oplysningerne kunne ikke ændres."</string>
<string name="screen_room_details_edition_error_title">"Rummet kunne ikke opdateres"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Beskeder er sikret med låse. Kun du og modtagerne har de unikke nøgler til at låse dem op."</string>
<string name="screen_room_details_encryption_enabled_title">"Beskedkryptering aktiveret"</string>
<string name="screen_room_details_error_loading_notification_settings">"Der opstod en fejl under indlæsning af notifikationsindstillinger."</string>
<string name="screen_room_details_error_muting">"Det lykkedes ikke at slå lyden fra for dette rum. Prøv igen."</string>
<string name="screen_room_details_error_unmuting">"Det lykkedes ikke at slå lyden til igen i dette rum. Prøv igen."</string>
<string name="screen_room_details_invite_people_dont_close">"Luk ikke appen, før den er færdig."</string>
<string name="screen_room_details_invite_people_preparing">"Forbereder invitationer…"</string>
<string name="screen_room_details_invite_people_title">"Invitér andre"</string>
<string name="screen_room_details_leave_conversation_title">"Forlad samtalen"</string>
<string name="screen_room_details_leave_room_title">"Forlad rum"</string>
<string name="screen_room_details_media_gallery_title">"Medier og filer"</string>
<string name="screen_room_details_notification_mode_custom">"Brugerdefineret"</string>
<string name="screen_room_details_notification_mode_default">"Standard"</string>
<string name="screen_room_details_notification_title">"Notifikationer"</string>
<string name="screen_room_details_pinned_events_row_title">"Fastgjorte beskeder"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Anmodninger om at deltage"</string>
<string name="screen_room_details_roles_and_permissions">"Roller og tilladelser"</string>
<string name="screen_room_details_room_name_label">"Navn på rum"</string>
<string name="screen_room_details_security_and_privacy_title">"Sikkerhed og privatliv"</string>
<string name="screen_room_details_security_title">"Sikkerhed"</string>
<string name="screen_room_details_share_room_title">"Del rum"</string>
<string name="screen_room_details_title">"Informationer om rummet"</string>
<string name="screen_room_details_topic_title">"Emne"</string>
<string name="screen_room_details_updating_room">"Opdaterer rum…"</string>
<string name="screen_room_member_list_banned_empty">"Der er ingen spærrede brugere i dette rum."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d person"</item>
<item quantity="other">"%1$d personer"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Spær fra rum"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Fjern kun medlem"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Fjern spærring af"</string>
<string name="screen_room_member_list_manage_member_unban_message">"De vil være i stand til at deltage i dette rum igen, hvis de inviteres."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Fjern brugerens spærring fra rummet"</string>
<string name="screen_room_member_list_mode_banned">"Spærret"</string>
<string name="screen_room_member_list_mode_members">"Medlemmer"</string>
<string name="screen_room_member_list_role_administrator">"Kun admins"</string>
<string name="screen_room_member_list_role_moderator">"Admins og moderatorer"</string>
<string name="screen_room_member_list_role_owner">"Ejeren"</string>
<string name="screen_room_member_list_room_members_header_title">"Medlemmer af rummet"</string>
<string name="screen_room_member_list_unbanning_user">"Ophæver spærring af %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Tillad brugerdefineret indstilling"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Hvis du aktiverer dette, tilsidesættes din standardindstilling"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Giv mig besked i denne samtale for"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Du kan ændre det i din %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"globale indstillinger"</string>
<string name="screen_room_notification_settings_default_setting_title">"Standardindstilling"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Fjern brugerdefineret indstilling"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Der opstod en fejl under indlæsning af meddelelsesindstillinger."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Gendannelse af standardtilstanden mislykkedes. Prøv igen."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Kunne ikke indstille tilstanden. Prøv igen."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Din hjemmeserver understøtter ikke denne indstilling i krypterede rum, du får ikke besked i dette rum."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Alle beskeder"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Kun omtaler og nøgleord"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Giv mig besked i dette rum for"</string>
<string name="screen_room_roles_and_permissions_admins">"Administratorer"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administratorer og ejere"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Skift min rolle"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Nedgrader til medlem"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Nedgradering til moderator"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderation af medlemmer"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Beskeder og indhold"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatorer"</string>
<string name="screen_room_roles_and_permissions_owners">"Ejere"</string>
<string name="screen_room_roles_and_permissions_reset">"Nulstil tilladelser"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Når du nulstiller tilladelserne, mister du de nuværende indstillinger."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Nulstil tilladelser?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roller"</string>
<string name="screen_room_roles_and_permissions_room_details">"Detaljer om rummet"</string>
<string name="screen_room_roles_and_permissions_title">"Roller og tilladelser"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Tilføj adresse på rum"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Alle kan bede om at deltage i lokalet, men en administrator eller moderator skal acceptere anmodningen."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Spørg om at deltage"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ja, aktivér kryptering"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Når det først er aktiveret, kan kryptering for et rum ikke deaktiveres igen. Beskedhistorik vil kun være synlig for rummedlemmer, siden de blev inviteret, eller siden de blev medlem af rummet.
Ingen udover medlemmer af rummet vil være i stand til at læse beskeder. Dette kan forhindre bots og broer i at fungere korrekt.
Vi anbefaler ikke at aktivere kryptering for rum, som alle kan finde og deltage i."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Aktivér kryptering?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Når kryptering først er aktiveret, kan den ikke deaktiveres igen."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Kryptering"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Aktivér end-to-end-kryptering"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Alle kan finde og deltage"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Enhver"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Andre kan kun deltage, hvis de bliver inviteret"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Kun med invitation"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Adgang til rummet"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Medlemmer af gruppen"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Grupper understøttes ikke i øjeblikket"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Du skal bruge en rum-adresse for at gøre den synlig i kataloget."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Tillad, at dette rum kan findes ved at søge i %1$s fortegnelse over offentlige rum"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Synlig i det offentlige register over rum"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Enhver"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Hvem kan læse historikken?"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Kun medlemmer, efter de blev inviteret"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Kun medlemmer siden valg af denne mulighed"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Rum-adresser er en måde at finde og få adgang til værelser på. Dette sikrer også, at du nemt kan dele dit rum med andre.
Du kan vælge at offentliggøre dit rum i din hjemmeservers offentlige katalog over rum."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Udgivelse af rum"</string>
<string name="screen_security_and_privacy_title">"Sikkerhed og privatliv"</string>
</resources>

View File

@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Du benötigst eine Chat-Adresse, um den Chat im Verzeichnis sichtbar zu machen."</string>
<string name="screen_edit_room_address_title">"Chat-Adresse"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Beim Aktualisieren der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Dein Homeserver unterstützt diese Option in verschlüsselten Chats nicht. In einigen Chats erhältst du möglicherweise keine Benachrichtigungen."</string>
<string name="screen_polls_history_title">"Umfragen"</string>
<string name="screen_room_change_permissions_administrators">"Nur Admins"</string>
<string name="screen_room_change_permissions_ban_people">"Mitglieder sperren"</string>
<string name="screen_room_change_permissions_delete_messages">"Nachrichten entfernen"</string>
<string name="screen_room_change_permissions_invite_people">"Personen einladen und Beitrittsanfragen annehmen"</string>
<string name="screen_room_change_permissions_messages_and_content">"Nachrichten senden &amp; löschen"</string>
<string name="screen_room_change_permissions_moderators">"Admins und Moderatoren"</string>
<string name="screen_room_change_permissions_remove_people">"Personen entfernen und Beitrittsanfragen ablehnen"</string>
<string name="screen_room_change_permissions_room_avatar">"Avatar ändern"</string>
<string name="screen_room_change_permissions_room_details">"Chat bearbeiten"</string>
<string name="screen_room_change_permissions_room_name">"Chat-Namen ändern"</string>
<string name="screen_room_change_permissions_room_topic">"Chat Thema ändern"</string>
<string name="screen_room_change_permissions_send_messages">"Nachrichten senden"</string>
<string name="screen_room_change_role_administrators_title">"Admins bearbeiten"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Du kannst diese Aktion nicht mehr rückgängig machen. Du vergibst dieselbe Rolle, die du auch hast."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Als Admin hinzufügen?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Du kannst diese Aktion nicht rückgängig machen. Du überträgst die Eigentumsrechte an die ausgewählten Nutzer. Sobald du diesen Vorgang abschließt, ist er endgültig."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Eigentumsrechte übertragen?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Zurückstufen"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Du stufst dich selbst herab. Diese Änderung kann nicht rückgängig gemacht werden. Wenn du der letzte Nutzer mit dieser Rolle bist, ist es nicht möglich, diese Rolle wiederzuerlangen."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Möchtest du dich selbst herabstufen?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Ausstehend)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Ausstehend)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Admins haben automatisch Moderatorenrechte"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Eigentümer haben automatisch Adminrechte."</string>
<string name="screen_room_change_role_moderators_title">"Moderatoren bearbeiten"</string>
<string name="screen_room_change_role_owners_title">"Wähle Eigentümer"</string>
<string name="screen_room_change_role_section_administrators">"Admins"</string>
<string name="screen_room_change_role_section_moderators">"Moderatoren"</string>
<string name="screen_room_change_role_section_users">"Mitglieder"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Du hast nicht gespeicherte Änderungen."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Änderungen speichern?"</string>
<string name="screen_room_details_add_topic_title">"Thema hinzufügen"</string>
<string name="screen_room_details_badge_encrypted">"Verschlüsselt"</string>
<string name="screen_room_details_badge_not_encrypted">"Nicht verschlüsselt"</string>
<string name="screen_room_details_badge_public">"Öffentlicher Chat"</string>
<string name="screen_room_details_edit_room_title">"Chat bearbeiten"</string>
<string name="screen_room_details_edition_error">"Es ist ein unbekannter Fehler aufgetreten und die Informationen konnten nicht geändert werden."</string>
<string name="screen_room_details_edition_error_title">"Chat kann nicht aktualisiert werden"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Nachrichten und Anrufe sind Ende-zu-Ende verschlüsselt. Nur du und die Empfänger haben die eindeutigen Schlüssel, um sie zu entsperren."</string>
<string name="screen_room_details_encryption_enabled_title">"Nachrichtenverschlüsselung aktiviert"</string>
<string name="screen_room_details_error_loading_notification_settings">"Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."</string>
<string name="screen_room_details_error_muting">"Die Stummschaltung ist fehlgeschlagen, bitte versuche es erneut."</string>
<string name="screen_room_details_error_unmuting">"Die Deaktivierung der Stummschaltung ist fehlgeschlagen, bitte versuche es erneut."</string>
<string name="screen_room_details_invite_people_dont_close">"Schließ die App erst, wenn du fertig bist."</string>
<string name="screen_room_details_invite_people_preparing">"Einladungen werden vorbereitet…"</string>
<string name="screen_room_details_invite_people_title">"Nutzer einladen"</string>
<string name="screen_room_details_leave_conversation_title">"Unterhaltung verlassen"</string>
<string name="screen_room_details_leave_room_title">"Verlassen"</string>
<string name="screen_room_details_media_gallery_title">"Medien und Dateien"</string>
<string name="screen_room_details_notification_mode_custom">"Benutzerdefiniert"</string>
<string name="screen_room_details_notification_mode_default">"Standard"</string>
<string name="screen_room_details_notification_title">"Benachrichtigungen"</string>
<string name="screen_room_details_pinned_events_row_title">"Fixierte Nachrichten"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Beitrittsanfragen"</string>
<string name="screen_room_details_roles_and_permissions">"Rollen und Berechtigungen"</string>
<string name="screen_room_details_room_name_label">"Chat-Name"</string>
<string name="screen_room_details_security_and_privacy_title">"Sicherheit &amp; Datenschutz"</string>
<string name="screen_room_details_security_title">"Sicherheit"</string>
<string name="screen_room_details_share_room_title">"Teilen"</string>
<string name="screen_room_details_title">"Informationen"</string>
<string name="screen_room_details_topic_title">"Thema"</string>
<string name="screen_room_details_updating_room">"Chat wird aktualisiert…"</string>
<string name="screen_room_member_list_banned_empty">"Es gibt keine gesperrten Nutzer."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d Person"</item>
<item quantity="other">"%1$d Personen"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Mitglied entfernen und sperren"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Mitglied nur entfernen"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Sperre aufheben"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Die Nutzer können dem Chat wieder beitreten, wenn sie eingeladen werden."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Sperre für diesen Chat aufheben"</string>
<string name="screen_room_member_list_mode_banned">"Gesperrt"</string>
<string name="screen_room_member_list_mode_members">"Mitglieder"</string>
<string name="screen_room_member_list_role_administrator">"Nur Admins"</string>
<string name="screen_room_member_list_role_moderator">"Admins und Moderatoren"</string>
<string name="screen_room_member_list_role_owner">"Eigentümer"</string>
<string name="screen_room_member_list_room_members_header_title">"Mitglieder"</string>
<string name="screen_room_member_list_unbanning_user">"%1$s wird entsperrt."</string>
<string name="screen_room_notification_settings_allow_custom">"Benutzerdefinierte Einstellungen verwenden"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Wenn du dies einschaltest, werden deine Standardeinstellungen außer Kraft setzen."</string>
<string name="screen_room_notification_settings_custom_settings_title">"Benachrichtige mich in diesem Chat bei"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Zum Anpassen der Standardeinstellungen gehe zu: %1$s"</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"Globale Einstellungen"</string>
<string name="screen_room_notification_settings_default_setting_title">"Standardeinstellung"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Benutzerdefinierte Einstellung entfernen"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Fehler beim Wiederherstellen des Standardmodus. Bitte erneut versuchen."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Fehler beim Einstellen des Modus. Bitte erneut versuchen."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Dein Homeserver unterstützt diese Option in verschlüsselten Chats nicht. Du erhältst in diesem Chat keine Benachrichtigungen."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Alle Nachrichten"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Nur Erwähnungen und Schlüsselwörter"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Benachrichtige mich bei"</string>
<string name="screen_room_roles_and_permissions_admins">"Admins"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Admins und Eigentümer"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Ändere meine Rolle"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Zum Mitglied herabstufen"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Zum Moderator herabstufen"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderation der Mitglieder"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Nachrichten senden &amp; löschen"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatoren"</string>
<string name="screen_room_roles_and_permissions_owners">"Eigentümer"</string>
<string name="screen_room_roles_and_permissions_reset">"Rollen und Berechtigungen zurücksetzen"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Sobald du die Berechtigungen zurücksetzt, verlierst du die aktuellen Einstellungen."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Berechtigungen zurücksetzen?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Rollen"</string>
<string name="screen_room_roles_and_permissions_room_details">"Chat-Details anpassen"</string>
<string name="screen_room_roles_and_permissions_title">"Rollen und Berechtigungen"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Chat-Adresse hinzufügen"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Jeder kann den Beitritt zum Chat anfragen, aber ein Admin oder Moderator müssen die Anfrage akzeptieren."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Beitritt beantragen"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ja, Verschlüsselung aktivieren"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Einmal angeschaltet kann die Verschlüsselung für einen Chat nicht mehr deaktiviert werden. Der Nachrichtenverlauf ist für Mitglieder nur sichtbar, seit sie eingeladen wurden oder dem Chat beigetreten sind.
Niemand außer den Chat Mitgliedern kann Nachrichten lesen. Dies kann verhindern, dass Bots und Bridges richtig funktionieren.
Wir empfehlen keine Verschlüsselung für Chats zu aktivieren, die jeder finden und denen jeder beitreten darf."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Verschlüsselung aktivieren?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Einmal angeschaltet kann die Verschlüsselung nicht mehr deaktiviert werden."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Verschlüsselung"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Ende-zu-Ende-Verschlüsselung aktivieren"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Jeder kann diesen Chat finden und ihm beitreten"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Jeder"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Personen können nur beitreten, wenn sie eingeladen werden."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Nur auf Einladung"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Chat Zugang"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Spacemitglieder"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Spaces werden zur Zeit nicht unterstützt."</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Du benötigst eine Chat-Adresse, um den Chat im Verzeichnis sichtbar zu machen."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Chatroomadresse"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Erlaube das Auffinden dieses Chats durch Suche im öffentlichen Verzeichnis von %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Sichtbar im öffentlichen Verzeichnis"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Jeder"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Wer hat Zugriff auf den Nachrichtenverlauf"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Nur Mitglieder, aber erst seit deren Einladung"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Nur Mitglieder seit Auswahl dieser Option"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Chat-Adressen machen es möglich, Chats zu finden und ihnen beizutreten. Dies erleichtert es, Chats mit anderen zu teilen.
Auf Wunsch kannst du deinen Chat im öffentlichen Verzeichnis deines Homeservers veröffentlichen."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Veröffentlichung von Chats"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Chatroomsichtbarkeit."</string>
<string name="screen_security_and_privacy_title">"Sicherheit &amp; Datenschutz"</string>
</resources>

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Θα χρειαστείτε μια διεύθυνση αίθουσας για να την κάνετε ορατή στον κατάλογο."</string>
<string name="screen_edit_room_address_title">"Διεύθυνση αίθουσας"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Παρουσιάστηκε σφάλμα κατά την ενημέρωση της ρύθμισης ειδοποίησης."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Ο αρχικός διακομιστής σας δεν υποστηρίζει αυτή την επιλογή σε κρυπτογραφημένες αίθουσες, ενδέχεται να μην λαμβάνετε ειδοποιήσεις σε ορισμένες αίθουσες."</string>
<string name="screen_polls_history_title">"Δημοσκοπήσεις"</string>
<string name="screen_room_change_permissions_administrators">"Μόνο διαχειριστές"</string>
<string name="screen_room_change_permissions_ban_people">"Αποκλεισμός ατόμων"</string>
<string name="screen_room_change_permissions_delete_messages">"Αφαίρεση μηνυμάτων"</string>
<string name="screen_room_change_permissions_invite_people">"Προσκάλεσε άτομα και αποδέξου αιτήματα συμμετοχής"</string>
<string name="screen_room_change_permissions_messages_and_content">"Μηνύματα και περιεχόμενο"</string>
<string name="screen_room_change_permissions_moderators">"Διαχειριστές και συντονιστές"</string>
<string name="screen_room_change_permissions_remove_people">"Αφαίρεση ατόμων και απόρριψη αιτημάτων συμμετοχής"</string>
<string name="screen_room_change_permissions_room_avatar">"Αλλαγή εικόνας προφίλ αίθουσας"</string>
<string name="screen_room_change_permissions_room_details">"Επεξεργασία Αίθουσας"</string>
<string name="screen_room_change_permissions_room_name">"Αλλαγή ονόματος αίθουσας"</string>
<string name="screen_room_change_permissions_room_topic">"Αλλαγή θέματος αίθουσας"</string>
<string name="screen_room_change_permissions_send_messages">"Αποστολή μηνυμάτων"</string>
<string name="screen_room_change_role_administrators_title">"Επεξεργασία Διαχειριστών"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Δεν θα μπορείς να αναιρέσεις αυτήν την ενέργεια. Προβιβάζεις τον χρήστη να έχει το ίδιο επίπεδο ισχύος με σένα."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Προσθήκη Διαχειριστή;"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Υποβιβασμός"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Δεν θα μπορέσετε να αναιρέσετε αυτή την αλλαγή καθώς υποβιβάζετε τον εαυτό σας, αν είστε ο τελευταίος χρήστης με δικαιώματα στην αίθουσα θα είναι αδύνατο να ανακτήσετε δικαιώματα."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Υποβιβασμός του εαυτού σου;"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Σε αναμονή)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Σε αναμονή)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Οι διαχειριστές έχουν αυτόματα δικαιώματα συντονιστή"</string>
<string name="screen_room_change_role_moderators_title">"Επεξεργασία Συντονιστών"</string>
<string name="screen_room_change_role_section_administrators">"Διαχειριστές"</string>
<string name="screen_room_change_role_section_moderators">"Συντονιστές"</string>
<string name="screen_room_change_role_section_users">"Μέλη"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Έχεις μη αποθηκευμένες αλλαγές."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Αποθήκευση αλλαγών;"</string>
<string name="screen_room_details_add_topic_title">"Προσθήκη θέματος"</string>
<string name="screen_room_details_badge_encrypted">"Κρυπτογραφημένο"</string>
<string name="screen_room_details_badge_not_encrypted">"Μη κρυπτογραφημένο"</string>
<string name="screen_room_details_badge_public">"Δημόσια αίθουσα"</string>
<string name="screen_room_details_edit_room_title">"Επεξεργασία Αίθουσας"</string>
<string name="screen_room_details_edition_error">"Υπήρξε ένα άγνωστο σφάλμα και οι πληροφορίες δεν μπορούσαν να αλλάξουν."</string>
<string name="screen_room_details_edition_error_title">"Αδυναμία ενημέρωσης αίθουσας"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Τα μηνύματα ασφαλίζονται με κλειδαριές. Μόνο εσύ και οι παραλήπτες έχετε τα μοναδικά κλειδιά για να τα ξεκλειδώσετε."</string>
<string name="screen_room_details_encryption_enabled_title">"Ενεργοποιημένη κρυπτογράφηση μηνυμάτων"</string>
<string name="screen_room_details_error_loading_notification_settings">"Παρουσιάστηκε σφάλμα κατά τη φόρτωση των ρυθμίσεων ειδοποίησης."</string>
<string name="screen_room_details_error_muting">"Η σίγαση αυτής της αίθουσας απέτυχε, δοκιμάστε ξανά."</string>
<string name="screen_room_details_error_unmuting">"Η κατάργηση σίγασης αυτής της αίθουσας απέτυχε, δοκιμάστε ξανά."</string>
<string name="screen_room_details_invite_people_title">"Πρόσκληση ατόμων"</string>
<string name="screen_room_details_leave_conversation_title">"Αποχώρηση από τη συζήτηση"</string>
<string name="screen_room_details_leave_room_title">"Αποχώρηση από την αίθουσα"</string>
<string name="screen_room_details_media_gallery_title">"Πολυμέσα και αρχεία"</string>
<string name="screen_room_details_notification_mode_custom">"Προσαρμοσμένο"</string>
<string name="screen_room_details_notification_mode_default">"Προεπιλογή"</string>
<string name="screen_room_details_notification_title">"Ειδοποιήσεις"</string>
<string name="screen_room_details_pinned_events_row_title">"Καρφιτσωμένα μηνύματα"</string>
<string name="screen_room_details_profile_row_title">"Προφίλ"</string>
<string name="screen_room_details_requests_to_join_title">"Αιτήματα συμμετοχής"</string>
<string name="screen_room_details_roles_and_permissions">"Ρόλοι και δικαιώματα"</string>
<string name="screen_room_details_room_name_label">"Όνομα αίθουσας"</string>
<string name="screen_room_details_security_and_privacy_title">"Ασφάλεια &amp; απόρρητο"</string>
<string name="screen_room_details_security_title">"Ασφάλεια"</string>
<string name="screen_room_details_share_room_title">"Κοινή χρήση αίθουσας"</string>
<string name="screen_room_details_title">"Πληροφορίες αίθουσας"</string>
<string name="screen_room_details_topic_title">"Θέμα"</string>
<string name="screen_room_details_updating_room">"Ενημέρωση αίθουσας…"</string>
<string name="screen_room_member_list_banned_empty">"Δεν υπάρχουν αποκλεισμένοι χρήστες σε αυτή την αίθουσα."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d άτομο"</item>
<item quantity="other">"%1$d άτομα"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Αφαίρεση και αποκλεισμός μέλους"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Μόνο αφαίρεση μέλους"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Αναίρεση αποκλεισμού"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Θα μπορούν να συμμετάσχουν ξανά σε αυτή την αίθουσα, εάν προσκληθούν."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Άρση αποκλεισμού από την αίθουσα"</string>
<string name="screen_room_member_list_mode_banned">"Αποκλεισμένοι"</string>
<string name="screen_room_member_list_mode_members">"Μέλη"</string>
<string name="screen_room_member_list_role_administrator">"Μόνο διαχειριστές"</string>
<string name="screen_room_member_list_role_moderator">"Διαχειριστές και συντονιστές"</string>
<string name="screen_room_member_list_room_members_header_title">"Μέλη της αίθουσας"</string>
<string name="screen_room_member_list_unbanning_user">"Άρση αποκλεισμού %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Να επιτρέπεται η προσαρμοσμένη ρύθμιση"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Η ενεργοποίηση αυτής της ρύθμισης θα παρακάμψει την προεπιλεγμένη ρύθμιση"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Ειδοποιήσε με σε αυτήν τη συνομιλία για"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Μπορείς να το αλλάξεις στο δικό σου %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"καθολικές ρυθμίσεις"</string>
<string name="screen_room_notification_settings_default_setting_title">"Προεπιλεγμένη ρύθμιση"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Κατάργηση προσαρμοσμένης ρύθμισης"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Παρουσιάστηκε σφάλμα κατά τη φόρτωση των ρυθμίσεων ειδοποίησης."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Αποτυχία επαναφοράς της προεπιλεγμένης λειτουργίας, δοκίμασε ξανά."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Αποτυχία ρύθμισης της λειτουργίας, δοκίμασε ξανά."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Ο αρχικός διακομιστής σας δεν υποστηρίζει αυτή την επιλογή σε κρυπτογραφημένες αίθουσες, δεν θα λάβετε ειδοποιήσεις σε αυτή την αίθουσα."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Όλα τα μηνύματα"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Μόνο αναφορές και λέξεις-κλειδιά"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Σε αυτήν την αίθουσα, ειδοποιήστε με για"</string>
<string name="screen_room_roles_and_permissions_admins">"Διαχειριστές"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Άλλαξε τον ρόλο μου"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Υποβιβασμός σε μέλος"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Υποβιβασμός σε συντονιστή"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Συντονισμός μελών"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Μηνύματα και περιεχόμενο"</string>
<string name="screen_room_roles_and_permissions_moderators">"Συντονιστές"</string>
<string name="screen_room_roles_and_permissions_reset">"Επαναφορά δικαιωμάτων"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Μόλις επαναφέρεις τα δικαιώματα, θα χάσεις τις τρέχουσες ρυθμίσεις."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Επαναφορά δικαιωμάτων;"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Ρόλοι"</string>
<string name="screen_room_roles_and_permissions_room_details">"Λεπτομέρειες αίθουσας"</string>
<string name="screen_room_roles_and_permissions_title">"Ρόλοι και δικαιώματα"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Προσθήκη διεύθυνσης αίθουσας"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στην αίθουσα, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχτεί το αίτημα."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Αίτημα συμμετοχής"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ναι, ενεργοποιήστε την κρυπτογράφηση"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Μόλις ενεργοποιηθεί, η κρυπτογράφηση για μια αίθουσα δεν μπορεί να απενεργοποιηθεί, το ιστορικό μηνυμάτων θα είναι ορατό μόνο για τα μέλη της αίθουσας από τότε που προσκλήθηκαν ή από τότε που συμμετείχαν στην αίθουσα.
Κανείς άλλος εκτός από τα μέλη της αίθουσας δεν θα μπορεί να διαβάσει τα μηνύματα. Αυτό μπορεί να εμποδίσει τη σωστή λειτουργία των bots και των γεφυρών.
Δεν συνιστούμε την ενεργοποίηση της κρυπτογράφησης για αίθουσες που μπορεί να βρει και να συμμετάσχει ο καθένας."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Ενεργοποίηση κρυπτογράφησης;"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Μόλις ενεργοποιηθεί, η κρυπτογράφηση δεν μπορεί να απενεργοποιηθεί."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Κρυπτογράφηση"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Ενεργοποίηση κρυπτογράφησης από άκρο σε άκρο"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Οποιοσδήποτε μπορεί να βρει και να συμμετάσχει"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Οποιοσδήποτε"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Τα άτομα μπορούν να συμμετάσχουν μόνο εάν έχουν προσκληθεί"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Μόνο πρόσκληση"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Πρόσβαση στην αίθουσα"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Μέλη χώρου"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Οι χώροι δεν υποστηρίζονται προς το παρόν"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Θα χρειαστείτε μια διεύθυνση αίθουσας για να την κάνετε ορατή στον κατάλογο."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Επιστρέψτε την εύρεση αυτής της αίθουσας με αναζήτηση στον κατάλογο %1$s δημοσίων αιθουσών"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Ορατή στον κατάλογο δημόσιων αιθουσών"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Οποιοσδήποτε"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Ποιος μπορεί να διαβάσει το ιστορικό"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Μόνο μέλη από τη στιγμή που προσκλήθηκαν"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Μόνο για μέλη μετά από αυτήν την επιλογή"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Οι διευθύνσεις αιθουσών είναι τρόποι εύρεσης και πρόσβασης σε αίθουσες. Αυτό διασφαλίζει επίσης ότι μπορείτε εύκολα να μοιραστείτε την αίθουσα με άλλους.
Μπορείτε να επιλέξετε να δημοσιεύσετε την αίθουσά σας στον δημόσιο κατάλογο αιθουσών του αρχικού διακομιστή σας."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Δημοσίευση αίθουσας"</string>
<string name="screen_security_and_privacy_title">"Ασφάλεια &amp; απόρρητο"</string>
</resources>

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Necesitarás una dirección de sala para que sea visible en el directorio."</string>
<string name="screen_edit_room_address_title">"Dirección de la sala"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Se ha producido un error al actualizar la configuración de notificaciones."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Tu servidor base no admite esta opción en salas cifradas, puede que no recibas notificaciones de algunas salas."</string>
<string name="screen_polls_history_title">"Encuestas"</string>
<string name="screen_room_change_permissions_administrators">"Solo administradores"</string>
<string name="screen_room_change_permissions_ban_people">"Vetar personas"</string>
<string name="screen_room_change_permissions_delete_messages">"Eliminar mensajes"</string>
<string name="screen_room_change_permissions_invite_people">"Invitar personas y aceptar solicitudes de unión"</string>
<string name="screen_room_change_permissions_messages_and_content">"Mensajes y contenido"</string>
<string name="screen_room_change_permissions_moderators">"Administradores y moderadores"</string>
<string name="screen_room_change_permissions_remove_people">"Eliminar personas y rechazar solicitudes de unión"</string>
<string name="screen_room_change_permissions_room_avatar">"Cambiar el avatar de la sala"</string>
<string name="screen_room_change_permissions_room_details">"Editar sala"</string>
<string name="screen_room_change_permissions_room_name">"Cambiar el nombre de la sala"</string>
<string name="screen_room_change_permissions_room_topic">"Cambiar el tema de la sala"</string>
<string name="screen_room_change_permissions_send_messages">"Enviar mensajes"</string>
<string name="screen_room_change_role_administrators_title">"Editar administradores"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"No podrás deshacer esta acción. Estás promocionando al usuario para que tenga el mismo nivel de poder que tú."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"¿Agregar Admin?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Degradar"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"No podrás deshacer este cambio ya que te estás degradando. Si eres el último usuario privilegiado en la sala será imposible recuperar los privilegios."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"¿Degradarte?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Pendiente)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Pendiente)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Los administradores tienen privilegios de moderador de forma automática"</string>
<string name="screen_room_change_role_moderators_title">"Editar moderadores"</string>
<string name="screen_room_change_role_section_administrators">"Administradores"</string>
<string name="screen_room_change_role_section_moderators">"Moderadores"</string>
<string name="screen_room_change_role_section_users">"Miembros"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Tienes cambios sin guardar."</string>
<string name="screen_room_change_role_unsaved_changes_title">"¿Guardar cambios?"</string>
<string name="screen_room_details_add_topic_title">"Añadir tema"</string>
<string name="screen_room_details_badge_encrypted">"Cifrada"</string>
<string name="screen_room_details_badge_not_encrypted">"No cifrada"</string>
<string name="screen_room_details_badge_public">"Sala pública"</string>
<string name="screen_room_details_edit_room_title">"Editar sala"</string>
<string name="screen_room_details_edition_error">"Se ha producido un error desconocido y no se ha podido cambiar la información."</string>
<string name="screen_room_details_edition_error_title">"No se puede actualizar la sala"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Los mensajes están protegidos con \"candados\". Sólo tú y los destinatarios tenéis las llaves únicas para abrirlos."</string>
<string name="screen_room_details_encryption_enabled_title">"Cifrado de mensajes activado"</string>
<string name="screen_room_details_error_loading_notification_settings">"Se ha producido un error al cargar la configuración de las notificaciones."</string>
<string name="screen_room_details_error_muting">"No se ha podido silenciar esta sala, inténtalo de nuevo."</string>
<string name="screen_room_details_error_unmuting">"Error al dejar de silenciar esta sala, por favor inténtalo de nuevo."</string>
<string name="screen_room_details_invite_people_title">"Invitar personas"</string>
<string name="screen_room_details_leave_conversation_title">"Salir de la conversación"</string>
<string name="screen_room_details_leave_room_title">"Salir de la sala"</string>
<string name="screen_room_details_media_gallery_title">"Medios y archivos"</string>
<string name="screen_room_details_notification_mode_custom">"Personalizado"</string>
<string name="screen_room_details_notification_mode_default">"Por defecto"</string>
<string name="screen_room_details_notification_title">"Notificaciones"</string>
<string name="screen_room_details_pinned_events_row_title">"Mensajes fijados"</string>
<string name="screen_room_details_profile_row_title">"Perfil"</string>
<string name="screen_room_details_requests_to_join_title">"Solicitudes de unión"</string>
<string name="screen_room_details_roles_and_permissions">"Roles y permisos"</string>
<string name="screen_room_details_room_name_label">"Nombre de la sala"</string>
<string name="screen_room_details_security_and_privacy_title">"Seguridad y privacidad"</string>
<string name="screen_room_details_security_title">"Seguridad"</string>
<string name="screen_room_details_share_room_title">"Compartir sala"</string>
<string name="screen_room_details_title">"Información de la sala"</string>
<string name="screen_room_details_topic_title">"Tema"</string>
<string name="screen_room_details_updating_room">"Actualizando la sala…"</string>
<string name="screen_room_member_list_banned_empty">"No hay usuarios vetados en esta sala."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"Una persona"</item>
<item quantity="other">"%1$d personas"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Sacar y vetar a un miembro"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Solo eliminar miembro"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Quitar veto"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Podrá volver a unirse a esta sala si se le invita."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Eliminar veto en la sala"</string>
<string name="screen_room_member_list_mode_banned">"Vetados"</string>
<string name="screen_room_member_list_mode_members">"Miembros"</string>
<string name="screen_room_member_list_role_administrator">"Solo administradores"</string>
<string name="screen_room_member_list_role_moderator">"Administradores y moderadores"</string>
<string name="screen_room_member_list_room_members_header_title">"Miembros de la sala"</string>
<string name="screen_room_member_list_unbanning_user">"Levantando veto a %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Permitir configuración personalizada"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Si activas esta opción, anularás tu configuración por defecto"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Notificarme en este chat para"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Puedes cambiarlo en tus %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"ajustes globales"</string>
<string name="screen_room_notification_settings_default_setting_title">"Ajustes predeterminados"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Eliminar configuración personalizada"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Se ha producido un error al cargar la configuración de las notificaciones."</string>
<string name="screen_room_notification_settings_error_restoring_default">"No se pudo restaurar el modo predeterminado, por favor vuelve a intentarlo de nuevo."</string>
<string name="screen_room_notification_settings_error_setting_mode">"No se pudo cambiar el modo, por favor inténtalo de nuevo."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Tu servidor base no admite esta opción en salas cifradas, no recibirás notificaciones de esta sala."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Todos los mensajes"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Únicamente Menciones y Palabras clave"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"En esta sala, notificarme por"</string>
<string name="screen_room_roles_and_permissions_admins">"Administradores"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Cambiar mi rol"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Degradar a miembro"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Degradar a moderador"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderación de miembros"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Mensajes y contenido"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderadores"</string>
<string name="screen_room_roles_and_permissions_reset">"Restablecer permisos"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Una vez que restablezca los permisos, perderá la configuración actual."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"¿Restablecer los permisos?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roles"</string>
<string name="screen_room_roles_and_permissions_room_details">"Detalles de la sala"</string>
<string name="screen_room_roles_and_permissions_title">"Roles y permisos"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Agregar dirección de sala"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Cualquiera puede solicitar unirse a la sala, pero un administrador o moderador tendrá que aceptar la solicitud."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Solicitud para unirse"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Sí, activar cifrado"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Una vez activado, el cifrado de una sala no se puede desactivar. El historial de mensajes solo será visible para los miembros de la sala desde que fueron invitados o desde que se unieron a la sala.
Nadie más que los miembros de la sala podrán leer los mensajes. Esto puede impedir que los bots y los puentes funcionen correctamente.
No recomendamos habilitar el cifrado para las salas que cualquiera pueda encontrar y unirse."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"¿Activar cifrado?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Una vez activado, el cifrado no se puede desactivar."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Cifrado"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Activar el cifrado de extremo a extremo"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Cualquiera puede encontrarla y unirse"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Cualquiera"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Las personas solo pueden unirse si están invitadas"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Solo por invitación"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Acceso a la sala"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Miembros del espacio"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"No se admiten los espacios por el momento."</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Necesitarás una dirección de sala para que sea visible en el directorio."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Permite encontrar esta sala buscando en el directorio de salas públicas de %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Visible en el directorio de salas públicas"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Cualquiera"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Quién puede leer el historial"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Solo participantes desde que fueron invitados"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Solo participantes desde que se selecciona esta opción"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Las direcciones de sala son formas de buscar salas y acceder a ellas. Esto también garantiza que puedas compartir fácilmente tu sala con otras personas.
Puedes optar por publicar tu sala en el directorio de salas públicas de tu servidor base."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publicación de la sala"</string>
<string name="screen_security_and_privacy_title">"Seguridad y privacidad"</string>
</resources>

View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Selleks, et jututuba oleks nähtav jututubade avalikus kataloogis, vajab ta aadressi."</string>
<string name="screen_edit_room_address_title">"Muuda aadressi"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Teavituste seadistamisel tekkis viga"</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Sinu koduserver ei toeta seda funktsionaalsust krüptitud jututubades ja seega ei pruugi kõik teavitused sinuni jõuda."</string>
<string name="screen_polls_history_title">"Küsitlused"</string>
<string name="screen_room_change_permissions_administrators">"Peakasutajad"</string>
<string name="screen_room_change_permissions_ban_people">"Suhtluskeelu seadmine"</string>
<string name="screen_room_change_permissions_delete_messages">"Eemalda sõnumid"</string>
<string name="screen_room_change_permissions_everyone">"Liikmed"</string>
<string name="screen_room_change_permissions_invite_people">"Osalejate kutsumine"</string>
<string name="screen_room_change_permissions_member_moderation">"Liikmete haldus"</string>
<string name="screen_room_change_permissions_messages_and_content">"Sõnumid ja sisu"</string>
<string name="screen_room_change_permissions_moderators">"Moderaatorid"</string>
<string name="screen_room_change_permissions_remove_people">"Osalejate eemaldamine"</string>
<string name="screen_room_change_permissions_room_avatar">"Jututoa tunnuspildi muutmine"</string>
<string name="screen_room_change_permissions_room_details">"Muuda üksikasju"</string>
<string name="screen_room_change_permissions_room_name">"Jututoa nime muutmine"</string>
<string name="screen_room_change_permissions_room_topic">"Jututoa teema muutmine"</string>
<string name="screen_room_change_permissions_send_messages">"Sõnumite saatmine"</string>
<string name="screen_room_change_role_administrators_title">"Muuda peakasutajaid"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Kuna sa annad teisele kasutajale sinu õigustega võrreldes samad õigused, siis sa ei saa seda muudatust hiljem tagasi pöörata."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Lisame peakasutaja?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Seda tegevust ei saa tagasi pöörata. Järgnevaga annad jututoa omandi üle valitud kasutajatele. Kui lahkus, siis muutub see muudatus püsivaks."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Kas soovid omandi üle anda?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Vähenda õigusi"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Kui sa võtad endalt kõik õigused ära ja oled viimane peakasutaja selles jututoas, siis sa ei saa seda muudatust hiljem tagasi pöörata."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Kas vähendad enda õigusi?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (ootel)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(ootel)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Peakasutajatel on automaatselt ka moderaatori õigused"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Omanikel on automaatselt ka peakasutaja õigused."</string>
<string name="screen_room_change_role_moderators_title">"Muuda moderaatoreid"</string>
<string name="screen_room_change_role_owners_title">"Vali omanikud"</string>
<string name="screen_room_change_role_section_administrators">"Peakasutajad"</string>
<string name="screen_room_change_role_section_moderators">"Moderaatorid"</string>
<string name="screen_room_change_role_section_users">"Liikmed"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Sul on salvestamata muudatusi"</string>
<string name="screen_room_change_role_unsaved_changes_title">"Kas salvestame muudatused?"</string>
<string name="screen_room_details_add_topic_title">"Lisa teema"</string>
<string name="screen_room_details_badge_encrypted">"Krüptitud jututuba"</string>
<string name="screen_room_details_badge_not_encrypted">"Krüptimata jututuba"</string>
<string name="screen_room_details_badge_public">"Avalik jututuba"</string>
<string name="screen_room_details_edit_room_title">"Muuda üksikasju"</string>
<string name="screen_room_details_edition_error">"Tekkis tundmatu viga ja andmed jäid muutmata."</string>
<string name="screen_room_details_edition_error_title">"Jututoa andmete muutmine ei õnnestu"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Sõnumid on turvatud krüptimise abil. Ainult sinul ja sõnumite saajatel on vajalikud võtmed nende lugemiseks."</string>
<string name="screen_room_details_encryption_enabled_title">"Sõnumite krüptimine on kasutusel"</string>
<string name="screen_room_details_error_loading_notification_settings">"Teavituste seadistuste laadimisel tekkis viga."</string>
<string name="screen_room_details_error_muting">"Selle jututoa summutamine ei õnnestunud. Palun proovi uuesti."</string>
<string name="screen_room_details_error_unmuting">"Selle jututoa summutamise eemaldamine ei õnnestunud. Palun proovi uuesti."</string>
<string name="screen_room_details_invite_people_dont_close">"Ära sulge rakendust enne, kui tegevus on lõppenud."</string>
<string name="screen_room_details_invite_people_preparing">"Valmistan kutseid ette…"</string>
<string name="screen_room_details_invite_people_title">"Kutsu osalejaid"</string>
<string name="screen_room_details_leave_conversation_title">"Lahku vestlusest"</string>
<string name="screen_room_details_leave_room_title">"Lahku jututoast"</string>
<string name="screen_room_details_media_gallery_title">"Meedia ja failid"</string>
<string name="screen_room_details_notification_mode_custom">"Kohandatud"</string>
<string name="screen_room_details_notification_mode_default">"Vaikimisi"</string>
<string name="screen_room_details_notification_title">"Teavitused"</string>
<string name="screen_room_details_pinned_events_row_title">"Esiletõstetud sõnumid"</string>
<string name="screen_room_details_profile_row_title">"Profiil"</string>
<string name="screen_room_details_requests_to_join_title">"Liitumispalved"</string>
<string name="screen_room_details_roles_and_permissions">"Rollid ja õigused"</string>
<string name="screen_room_details_room_name_label">"Jututoa nimi"</string>
<string name="screen_room_details_security_and_privacy_title">"Turvalisus ja privaatsus"</string>
<string name="screen_room_details_security_title">"Turvalisus"</string>
<string name="screen_room_details_share_room_title">"Jaga jututuba"</string>
<string name="screen_room_details_title">"Jututoa teave"</string>
<string name="screen_room_details_topic_title">"Teema"</string>
<string name="screen_room_details_updating_room">"Uuendame jututuba…"</string>
<string name="screen_room_member_list_banned_empty">"Suhtluskeeluga kasutajaid pole"</string>
<string name="screen_room_member_list_empty_search_subtitle">"Palun kontrolli otsingusõna korrektsust ja proovi siis uuesti"</string>
<string name="screen_room_member_list_empty_search_title">"Otsingul „%1$s“ pole tulemusi"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d osaleja"</item>
<item quantity="other">"%1$d osalejat"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Eemalda ja sea suhtluskeeld"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Ainult eemalda kasutaja"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Eemalda suhtluskeeld"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Kutse olemasolul saab ta nüüd jututoaga uuesti liituda"</string>
<string name="screen_room_member_list_manage_member_unban_title">"Eemalda suhtluskeeld jututoas"</string>
<string name="screen_room_member_list_mode_banned">"Suhtluskeeluga kasutajad"</string>
<string name="screen_room_member_list_mode_members">"Liikmed"</string>
<string name="screen_room_member_list_pending_status">"Ootel"</string>
<string name="screen_room_member_list_role_administrator">"Peakasutajad"</string>
<string name="screen_room_member_list_role_moderator">"Moderaatorid"</string>
<string name="screen_room_member_list_role_owner">"Omanik"</string>
<string name="screen_room_member_list_room_members_header_title">"Jututoas osalejad"</string>
<string name="screen_room_member_list_unbanning_user">"Eemaldame suhtluskeelu kasutajalt %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Kasuta kohandatud seadistusi"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Selle eelistuse valimine asendab vaikimisi seadistused"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Selles vestluses teavita mind"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Sa saad seda muuta siin: %1$s"</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"üldised teavitused"</string>
<string name="screen_room_notification_settings_default_setting_title">"Vaikimisi teavitused"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Eemalda kohandatud seadistused"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Teavituste seadistuste laadimisel tekkis viga."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Vaikimisi seadistuste taastamine ei õnnestunud. Palun proovi uuesti."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Seadistuste muutmine ei õnnestunud. Palun proovi uuesti."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Sinu koduserver ei toeta seda võimalust krüptitud jututubades, seega sa ei saa selle jututoa kohta teavitusi."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Kõikide sõnumite korral"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Mainimiste ja võtmesõnade alusel"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Selles jututoas teavita mind"</string>
<string name="screen_room_roles_and_permissions_admins">"Peakasutajad"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Peakasutajad ja omanikud"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Muuda minu rolli"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Muuda tavaliikmeks"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Muuda moderaatoriks"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Jututoas osalejate modereerimine"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Sõnumid ja sisu"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderaatorid"</string>
<string name="screen_room_roles_and_permissions_owners">"Omanikud"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Õigused"</string>
<string name="screen_room_roles_and_permissions_reset">"Lähtesta õigused"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Kui lähtestad õigused, siis praegune õiguste kombinatsioon läheb kaotsi."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Kas lähtestame õigused?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Rollid"</string>
<string name="screen_room_roles_and_permissions_room_details">"Jututoa üksikasjad"</string>
<string name="screen_room_roles_and_permissions_title">"Rollid ja õigused"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Lisa aadress"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Kõik võivad paluda jututoaga liitumist."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Küsi võimalust liitumiseks"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Jah, lülita krüptimine sisse"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Kui jututoa krüptimine on kord sisse lülitatud, siis seda välja lülitada ei saa. Sõnumite ajalugu on nähtav vaid jututoa liikmetele alates kutse saamise või liitumise hetkest.
Keegi teine peale jututoa liikmete ei saa sõnumeid lugeda. See võib takistada suhtlusrobotite ja/või võrgusildade toimimist.
Me ei soovita krüptimise kasutamist selliste avalike jututubade puhul, millega kõik võivad liituda."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Kas võtame krüptimise kasutusele?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Kui krüptimine on kasutusel, siis seda enam väljalülitada ei saa."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Krüptimine"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Võta läbiv krüptimine kasutusele"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Kõik võivad jututoaga liituda"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Kõik"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Liituda saab vaid kutse olemasolul"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Vaid kutsega"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Ligipääs"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Kogukonna liikmed"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Kogukondade tugi veel puudub"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Selleks, et jututuba oleks nähtav jututubade avalikus kataloogis, vajab ta aadressi."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Aadress"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Võimalda leida seda jututuba avalikust kataloogist otsides „%1$s“"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Luba leitavus avaliku kataloogi otsingust."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Nähtav avalikus kataloogis"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Kõik"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Kes võivad lugeda jututoa ajalugu"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Liikmed peale kutse saamist"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Liikmed peale selle valiku sisselülitamist"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Jututoa aadressid annavad võimaluse neid leida ning saada neile ligi. Samuti võimaldab see jututuba teistele huvilistele jagada.
Lisaks võid sa jututoa avaldada oma koduserveri avalikus jututubade kataloogis."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Jututoa avaldamine"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Nähtavus"</string>
<string name="screen_security_and_privacy_title">"Turvalisus ja privaatsus"</string>
</resources>

View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_title">"Gelaren helbidea"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Errorea gertatu da jakinarazpen-ezarpena eguneratzean."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Zure zerbitzaria ez da bateragarria enkriptatutako gelen aukerarekin; litekeena da gela batzuetako jakinarazpenak ez jasotzea."</string>
<string name="screen_polls_history_title">"Inkestak"</string>
<string name="screen_room_change_permissions_administrators">"Administratzaileak soilik"</string>
<string name="screen_room_change_permissions_ban_people">"Jarri debekua jendeari"</string>
<string name="screen_room_change_permissions_delete_messages">"Kendu mezuak"</string>
<string name="screen_room_change_permissions_invite_people">"Gonbidatu jendea"</string>
<string name="screen_room_change_permissions_messages_and_content">"Mezuak eta edukiak"</string>
<string name="screen_room_change_permissions_moderators">"Administratzaileak eta moderatzaileak"</string>
<string name="screen_room_change_permissions_remove_people">"Kendu jendea"</string>
<string name="screen_room_change_permissions_room_avatar">"Aldatu gelaren abatarra"</string>
<string name="screen_room_change_permissions_room_details">"Editatu gela"</string>
<string name="screen_room_change_permissions_room_name">"Aldatu gelaren izena"</string>
<string name="screen_room_change_permissions_room_topic">"Aldatu gelako mintzagaia"</string>
<string name="screen_room_change_permissions_send_messages">"Bidali mezuak"</string>
<string name="screen_room_change_role_administrators_title">"Editatu administratzaileak"</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Administratzailea gehitu?"</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Jabetza eskualdatu?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Jaitsi mailaz"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Ezin izango duzu hau aldatu zure burua mailaz jaisten ari zarelako, zu bazara gelan baimenak dituen azken erabiltzailea ezin izango dira baimenak berreskuratu."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Zure burua mailaz jaitsi?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (zain)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Egiteke)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Administratzaileek automatikoki dute moderatzaile-pribilegioak"</string>
<string name="screen_room_change_role_moderators_title">"Editatu moderatzaileak"</string>
<string name="screen_room_change_role_owners_title">"Aukeratu jabeak"</string>
<string name="screen_room_change_role_section_administrators">"Administratzaileak"</string>
<string name="screen_room_change_role_section_moderators">"Moderatzaileak"</string>
<string name="screen_room_change_role_section_users">"Kideak"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Gorde gabeko aldaketak dituzu."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Aldaketak gorde?"</string>
<string name="screen_room_details_add_topic_title">"Gehitu hizketagaia"</string>
<string name="screen_room_details_badge_encrypted">"Zifratuta"</string>
<string name="screen_room_details_badge_not_encrypted">"Zifratu gabe"</string>
<string name="screen_room_details_badge_public">"Gela publikoa"</string>
<string name="screen_room_details_edit_room_title">"Editatu gela"</string>
<string name="screen_room_details_edition_error">"Errore ezezaguna gertatu da eta ezin izan da informazioa aldatu."</string>
<string name="screen_room_details_edition_error_title">"Ezin da gela eguneratu"</string>
<string name="screen_room_details_encryption_enabled_title">"Mezuen enkriptazioa gaituta dago"</string>
<string name="screen_room_details_error_loading_notification_settings">"Errorea gertatu da jakinarazpen-ezarpenak kargatzean."</string>
<string name="screen_room_details_error_muting">"Ezin izan da gela mututu; saiatu berriro."</string>
<string name="screen_room_details_error_unmuting">"Ezin izan da gela mututzeari utzi; saiatu berriro."</string>
<string name="screen_room_details_invite_people_title">"Gonbidatu jendea"</string>
<string name="screen_room_details_leave_conversation_title">"Utzi elkarrizketa"</string>
<string name="screen_room_details_leave_room_title">"Atera gelatik"</string>
<string name="screen_room_details_media_gallery_title">"Multimedia eta fitxategiak"</string>
<string name="screen_room_details_notification_mode_default">"Lehenetsia"</string>
<string name="screen_room_details_notification_title">"Jakinarazpenak"</string>
<string name="screen_room_details_pinned_events_row_title">"Finkatutako mezuak"</string>
<string name="screen_room_details_profile_row_title">"Profila"</string>
<string name="screen_room_details_requests_to_join_title">"Sartzeko eskaerak"</string>
<string name="screen_room_details_roles_and_permissions">"Rolak eta baimenak"</string>
<string name="screen_room_details_room_name_label">"Gelaren izena"</string>
<string name="screen_room_details_security_and_privacy_title">"Segurtasuna eta pribatutasuna"</string>
<string name="screen_room_details_security_title">"Segurtasuna"</string>
<string name="screen_room_details_share_room_title">"Partekatu gela"</string>
<string name="screen_room_details_title">"Gelaren informazioa"</string>
<string name="screen_room_details_topic_title">"Gaia"</string>
<string name="screen_room_details_updating_room">"Gela eguneratzen…"</string>
<string name="screen_room_member_list_banned_empty">"Gela honetan ez dago debekua ezarri zaion erabiltzailerik."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"Pertsona %1$d"</item>
<item quantity="other">"%1$d pertsona"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Kendu kidea eta ezarri debekua"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Kendu kidea soilik"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Kendu debekua"</string>
<string name="screen_room_member_list_mode_banned">"Debekatuta"</string>
<string name="screen_room_member_list_mode_members">"Kideak"</string>
<string name="screen_room_member_list_role_administrator">"Administratzaileak soilik"</string>
<string name="screen_room_member_list_role_moderator">"Administratzaileak eta moderatzaileak"</string>
<string name="screen_room_member_list_role_owner">"Jabea"</string>
<string name="screen_room_member_list_room_members_header_title">"Gelako kideak"</string>
<string name="screen_room_member_list_unbanning_user">"%1$s(r)i debekua kentzen"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Aktibatuz gero, defektuzko ezarpena gainidatziko du"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Jakinarazi txat honetan"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"%1$s alda dezakezu."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"Ezarpen orokorretan"</string>
<string name="screen_room_notification_settings_default_setting_title">"Defektuzko ezarpena"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Errorea gertatu da jakinarazpen-ezarpenak kargatzean."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Zure zerbitzaria ez da bateragarria enkriptatutako gelen aukerarekin; litekeena da gela batzuetako jakinarazpenak ez jasotzea."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Mezu guztiak"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Aipamenak eta hitz gakoak soilik"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Gela honetan, jakinarazi"</string>
<string name="screen_room_roles_and_permissions_admins">"Administratzaileak"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administratzaileak eta jabeak"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Aldatu nire rola"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Jaitsi maila, kidera"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Jaitsi maila, moderatzailera"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Kideen moderazioa"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Mezuak eta edukiak"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatzaileak"</string>
<string name="screen_room_roles_and_permissions_owners">"Jabeak"</string>
<string name="screen_room_roles_and_permissions_reset">"Berrezarri baimenak"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Baimenak berrezarritakoan, uneko ezarpenak galduko dituzu."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Baimenak berrezarri?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Rolak"</string>
<string name="screen_room_roles_and_permissions_room_details">"Gelaren xehetasunak"</string>
<string name="screen_room_roles_and_permissions_title">"Rolak eta baimenak"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Gehitu gelaren helbidea"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Bai, gaitu zifratzea"</string>
<string name="screen_security_and_privacy_encryption_section_header">"Zifratzea"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Edonork aurkitu eta bat egin dezake"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Edonork"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Gonbidatutako pertsonak bakarrik sartu ahal izango dira"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Gonbidapen bidez"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Gelarako sarbidea"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Guneko kideak"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Gaur-gaurkoz ez da guneekin bateragarria"</string>
<string name="screen_security_and_privacy_room_address_section_header">"Gelaren helbidea"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Gela publikoen direktorioan ikusgai"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Edonork"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Nork irakur dezake historia"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Kideek bakarrik, gonbidatu zituztenetik"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Kideek bakarrik, aukera hau hautatu zenetik"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Gelaren ikusgarritasuna"</string>
<string name="screen_security_and_privacy_title">"Segurtasuna eta pribatutasuna"</string>
</resources>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_title">"نشانی اتاق"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"هنگام به‌روز کردن تنظیمات آگاهی خطایی رخ داد."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"کارساز خانگیتان از این گزینه در اتاق‌های رمز شده پشتیبانی نمی‌کند. ممکن است در برخی اتاق‌ها آگاه نشوید."</string>
<string name="screen_polls_history_title">"نظرسنجی‌ها"</string>
<string name="screen_room_change_permissions_administrators">"فقط مدیران"</string>
<string name="screen_room_change_permissions_ban_people">"تحریم افراد"</string>
<string name="screen_room_change_permissions_delete_messages">"برداشتن پیام‌ها"</string>
<string name="screen_room_change_permissions_everyone">"هرکسی"</string>
<string name="screen_room_change_permissions_invite_people">"دعوت افراد و پذیرش درخواست‌های پیوستن"</string>
<string name="screen_room_change_permissions_member_moderation">"نظارت اعضا"</string>
<string name="screen_room_change_permissions_messages_and_content">"پیام‌ها و محتوا"</string>
<string name="screen_room_change_permissions_moderators">"مدیرن و ناظران"</string>
<string name="screen_room_change_permissions_remove_people">"برداشتن افراد و رد درخواست‌های پیوستن"</string>
<string name="screen_room_change_permissions_room_avatar">"تغییر چهرک اتاق"</string>
<string name="screen_room_change_permissions_room_details">"ویرایش اتاق"</string>
<string name="screen_room_change_permissions_room_name">"تغییر نام اتاق"</string>
<string name="screen_room_change_permissions_room_topic">"دگرگونی موضوع اتاق"</string>
<string name="screen_room_change_permissions_send_messages">"فرستادن پیام‌ها"</string>
<string name="screen_room_change_role_administrators_title">"ویرایش مدیران"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"قادر نخواهید بود این کنش را بازکردانید. داردید کاربر را به سطح قدرت خودتان ارتقا می‌دهید."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"افزودن مدیر؟"</string>
<string name="screen_room_change_role_confirm_change_owners_title">"انتقال مالکیت؟"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"تنزل بده"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"شما نمی‌توانید این تغییر را بازگردانید زیرا در حال تنزل نقش خود در اتاق هستید، اگر آخرین کاربر ممتاز در اتاق باشید، امکان دستیابی مجدد به دسترسی‌های سطح بالای اتاق غیرممکن است."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"تنزل نقش شما در اتاق؟"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (منتظر)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(منتظر)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"مدیران به صورت خودکار اجازه‌های نظارتی را دارند"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"ماکان به صورت خودکار اجازه‌های مدیریتی را دارند."</string>
<string name="screen_room_change_role_moderators_title">"ویرایش ناظران"</string>
<string name="screen_room_change_role_owners_title">"گزینش مالکان"</string>
<string name="screen_room_change_role_section_administrators">"مدیران"</string>
<string name="screen_room_change_role_section_moderators">"ناظم‌ها"</string>
<string name="screen_room_change_role_section_users">"اعضا"</string>
<string name="screen_room_change_role_unsaved_changes_description">"تغییراتی ذخیره نشده دارید."</string>
<string name="screen_room_change_role_unsaved_changes_title">"ذخیرهٔ تغییرات؟"</string>
<string name="screen_room_details_add_topic_title">"افزودن موضوع"</string>
<string name="screen_room_details_badge_encrypted">"رمز شده"</string>
<string name="screen_room_details_badge_not_encrypted">"رمزنگاری نشده"</string>
<string name="screen_room_details_badge_public">"اتاق عمومی"</string>
<string name="screen_room_details_edit_room_title">"ویرایش اتاق"</string>
<string name="screen_room_details_edition_error">"خطایی ناشناخته رخ داد و اطّلاعات قابل تغییر نبودند."</string>
<string name="screen_room_details_edition_error_title">"ناتوان در به‌روز رسانی اتاق"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"پیام‌ها با قفل محافظت می‌شوند. فقط شما و گیرندگان، کلیدهای منحصر به فرد برای باز کردن قفل آنها را دارید."</string>
<string name="screen_room_details_encryption_enabled_title">"رمزنگاری پیام به کار افتاد"</string>
<string name="screen_room_details_error_loading_notification_settings">"هنگام بارگیری تنظیمات اعلان خطایی رخ داد."</string>
<string name="screen_room_details_error_muting">"بی صدا کردن این اتاق ناموفق بود، لطفا دوباره امتحان کنید."</string>
<string name="screen_room_details_error_unmuting">"بی صدا کردن این اتاق ناموفق بود، لطفا دوباره امتحان کنید."</string>
<string name="screen_room_details_invite_people_dont_close">"کاره را تا زمان پایانش نبندید."</string>
<string name="screen_room_details_invite_people_preparing">"آماده سازی دعوت‌ها…"</string>
<string name="screen_room_details_invite_people_title">"دعوت افراد"</string>
<string name="screen_room_details_leave_conversation_title">"ترک گفت‌وگو"</string>
<string name="screen_room_details_leave_room_title">"ترک اتاق"</string>
<string name="screen_room_details_media_gallery_title">"رسانه‌ها و پرونده‌ها"</string>
<string name="screen_room_details_notification_mode_custom">"سفارشی"</string>
<string name="screen_room_details_notification_mode_default">"پیش‌گزیده"</string>
<string name="screen_room_details_notification_title">"آگاهی‌ها"</string>
<string name="screen_room_details_pinned_events_row_title">"پیام‌های سنجاق شده"</string>
<string name="screen_room_details_profile_row_title">"نمایه"</string>
<string name="screen_room_details_requests_to_join_title">"درخواست‌های پیوستن"</string>
<string name="screen_room_details_roles_and_permissions">"نقش‌ها و اجازه‌ها"</string>
<string name="screen_room_details_room_name_label">"نام اتاق"</string>
<string name="screen_room_details_security_and_privacy_title">"امنیت و محرمانگی"</string>
<string name="screen_room_details_security_title">"امنیت"</string>
<string name="screen_room_details_share_room_title">"هم‌رسانی اتاق"</string>
<string name="screen_room_details_title">"اطّلاعات اتاق"</string>
<string name="screen_room_details_topic_title">"موضوع"</string>
<string name="screen_room_details_updating_room">"به‌روز کردن اتاق…"</string>
<string name="screen_room_member_list_banned_empty">"هیچ کاربر محرومی در این اتاق نیست."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d نفر"</item>
<item quantity="other">"%1$d نفر"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"برداشت و تحریم عضو"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"تنها برداشتن عضو"</string>
<string name="screen_room_member_list_manage_member_unban_action">"رفع انسداد"</string>
<string name="screen_room_member_list_manage_member_unban_message">"در صورت دعوت می‌تواند دوباره به اتاق بپیوندد."</string>
<string name="screen_room_member_list_manage_member_unban_title">"تحریم نکردن از اتاق"</string>
<string name="screen_room_member_list_mode_banned">"محروم"</string>
<string name="screen_room_member_list_mode_members">"اعضا"</string>
<string name="screen_room_member_list_role_administrator">"فقط مدیران"</string>
<string name="screen_room_member_list_role_moderator">"مدیرن و ناظران"</string>
<string name="screen_room_member_list_role_owner">"مالک"</string>
<string name="screen_room_member_list_room_members_header_title">"اعضای اتاق"</string>
<string name="screen_room_member_list_unbanning_user">"رفع تحریم %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"اجازه به تنظیمت شخصی"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"روشن کردنش تنظیمات پیش‌گزیده‌تان را پایمال می‌کند"</string>
<string name="screen_room_notification_settings_custom_settings_title">"آگاهی من در این گپ برای"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"می‌توانید در %1$sتان تغییرش دهید."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"تنظیمات جهانی"</string>
<string name="screen_room_notification_settings_default_setting_title">"تنظیمات پیش‌گزیده"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"برداشتن تنظیمات سفارشی"</string>
<string name="screen_room_notification_settings_error_loading_settings">"هنگام بارگیری تنظیمات اعلان خطایی رخ داد."</string>
<string name="screen_room_notification_settings_error_restoring_default">"بازیابی حالت پیش فرض ناموفق بود، لطفا دوباره امتحان کنید."</string>
<string name="screen_room_notification_settings_error_setting_mode">"تنظیم حالت ناموفق است، لطفا دوباره امتحان کنید."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"کارساز خانگیتان از این گزینه در اتاق‌های رمز شده پشتیبانی نمی‌کند. ممکن است در این اتاق آگاه نشوید."</string>
<string name="screen_room_notification_settings_mode_all_messages">"همهٔ پیام‌ها"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"فقط اشاره‌ها و کلیدواژگان"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"آگاهی من در این اتاق برای"</string>
<string name="screen_room_roles_and_permissions_admins">"مدیران"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"مدیران و مالکان"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"تغییر نقشم"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"تنزّل به عضو"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"تنزّل به ناظم"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"نظارت اعضا"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"پیام‌ها و محتوا"</string>
<string name="screen_room_roles_and_permissions_moderators">"ناظم‌ها"</string>
<string name="screen_room_roles_and_permissions_owners">"مالکان"</string>
<string name="screen_room_roles_and_permissions_reset">"بازنشانی اجازه‌ها"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"بازنشانی اجازه‌ها؟"</string>
<string name="screen_room_roles_and_permissions_roles_header">"نقش‌ها"</string>
<string name="screen_room_roles_and_permissions_room_details">"جزییات اتاق"</string>
<string name="screen_room_roles_and_permissions_title">"نقش‌ها و اجازه‌ها"</string>
<string name="screen_security_and_privacy_add_room_address_action">"افزودن نشانی اتاق"</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"درخواست دعوت"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"بله. به کار انداختن رمزنگاری"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"رمزگذاری فعال شود؟"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"پس از به کار افتادن، رمزنگاری قابل از کار انداختن نیست."</string>
<string name="screen_security_and_privacy_encryption_section_header">"رمزنگاری"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"هرکسی می‌تواند یافته و بپیوندد"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"هرکسی"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"افراد فقط در صورت دعوت می‌توانند بپیوندند"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"فقط دعوتی"</string>
<string name="screen_security_and_privacy_room_access_section_header">"دسترسی اتاق"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"اعضای فضا"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"در حال حاضر فضاها پشتیبانی نمی‌شوند"</string>
<string name="screen_security_and_privacy_room_address_section_header">"نشانی اتاق"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"هرکسی"</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"انتشار اتاق"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"نمایانی اتاق"</string>
<string name="screen_security_and_privacy_title">"امنیت و محرمانگی"</string>
</resources>

View File

@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Tarvitset osoitteen, jotta se näkyy julkisessa hakemistossa."</string>
<string name="screen_edit_room_address_title">"Muokkaa osoitetta"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Ilmoitusasetusten muokkaamisessa tapahtui virhe."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Kotipalvelimesi ei tue tätä vaihtoehtoa salatuissa huoneissa, joten et ehkä saa ilmoitusta joissakin huoneissa."</string>
<string name="screen_polls_history_title">"Kyselyt"</string>
<string name="screen_room_change_permissions_administrators">"Ylläpitäjä"</string>
<string name="screen_room_change_permissions_ban_people">"Porttikieltojen antaminen"</string>
<string name="screen_room_change_permissions_delete_messages">"Viestien poistaminen"</string>
<string name="screen_room_change_permissions_everyone">"Jäsen"</string>
<string name="screen_room_change_permissions_invite_people">"Ihmisten kutsuminen ja liittymispyyntöjen hyväksyminen"</string>
<string name="screen_room_change_permissions_member_moderation">"Jäsenien hallinta"</string>
<string name="screen_room_change_permissions_messages_and_content">"Viestit ja sisältö"</string>
<string name="screen_room_change_permissions_moderators">"Valvoja"</string>
<string name="screen_room_change_permissions_remove_people">"Henkilöiden poistaminen ja liittymispyyntöjen hylkääminen"</string>
<string name="screen_room_change_permissions_room_avatar">"Huoneen avatarin vaihtaminen"</string>
<string name="screen_room_change_permissions_room_details">"Muokkaa tietoja"</string>
<string name="screen_room_change_permissions_room_name">"Huoneen nimen vaihtaminen"</string>
<string name="screen_room_change_permissions_room_topic">"Huoneen aiheen vaihtaminen"</string>
<string name="screen_room_change_permissions_send_messages">"Viestien lähettäminen"</string>
<string name="screen_room_change_role_administrators_title">"Muokkaa ylläpitäjiä"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Et voi peruuttaa tätä toimenpidettä. Ylennät käyttäjän samalle oikeustasolle kuin sinä."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Lisätäänkö ylläpitäjä?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Et voi kumota tätä toimintoa. Olet siirtämässä omistajuuden valituille käyttäjille. Kun poistut, muutos on pysyvä."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Siirretäänkö omistajuus?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Alenna"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Et voi perua tätä muutosta, koska olet alentamassa itseäsi. Jos olet viimeinen oikeutettu henkilö tässä huoneessa, oikeuksia ei voi enää saada takaisin."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Haluatko alentaa itsesi?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Kutsuttu)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Kutsuttu)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Ylläpitäjillä on automaattisesti valvojan oikeudet"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Omistajilla on automaattisesti ylläpitäjän oikeudet."</string>
<string name="screen_room_change_role_moderators_title">"Muokkaa valvojia"</string>
<string name="screen_room_change_role_owners_title">"Valitse Omistajat"</string>
<string name="screen_room_change_role_section_administrators">"Ylläpitäjät"</string>
<string name="screen_room_change_role_section_moderators">"Valvojat"</string>
<string name="screen_room_change_role_section_users">"Jäsenet"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Sinulla on tallentamattomia muutoksia"</string>
<string name="screen_room_change_role_unsaved_changes_title">"Tallennetaanko muutokset?"</string>
<string name="screen_room_details_add_topic_title">"Lisää aihe"</string>
<string name="screen_room_details_badge_encrypted">"Salattu"</string>
<string name="screen_room_details_badge_not_encrypted">"Ei salattu"</string>
<string name="screen_room_details_badge_public">"Julkinen huone"</string>
<string name="screen_room_details_edit_room_title">"Muokkaa tietoja"</string>
<string name="screen_room_details_edition_error">"Tuntematon virhe tapahtui, eikä tietoja voitu muuttaa."</string>
<string name="screen_room_details_edition_error_title">"Huoneen muokkaaminen ei onnistunut"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Viestisi suojataan lukoilla. Vain sinulla ja viesiten vastaanottajilla on uniikit avaimet niiden avaamiseen."</string>
<string name="screen_room_details_encryption_enabled_title">"Viestien salaus käytössä"</string>
<string name="screen_room_details_error_loading_notification_settings">"Ilmoitusasetuksia ladattaessa tapahtui virhe."</string>
<string name="screen_room_details_error_muting">"Tämän huoneen mykistäminen epäonnistui, yritä uudelleen."</string>
<string name="screen_room_details_error_unmuting">"Tämän huoneen mykistyksen poistaminen epäonnistui, yritä uudelleen."</string>
<string name="screen_room_details_invite_people_dont_close">"Älä sulje sovellusta ennen kuin se on valmis."</string>
<string name="screen_room_details_invite_people_preparing">"Valmistellaan kutsuja…"</string>
<string name="screen_room_details_invite_people_title">"Kutsu henkilöitä"</string>
<string name="screen_room_details_leave_conversation_title">"Poistu keskustelusta"</string>
<string name="screen_room_details_leave_room_title">"Poistu huoneesta"</string>
<string name="screen_room_details_media_gallery_title">"Media ja tiedostot"</string>
<string name="screen_room_details_notification_mode_custom">"Mukautettu"</string>
<string name="screen_room_details_notification_mode_default">"Oletus"</string>
<string name="screen_room_details_notification_title">"Ilmoitukset"</string>
<string name="screen_room_details_pinned_events_row_title">"Kiinnitetyt viestit"</string>
<string name="screen_room_details_profile_row_title">"Profiili"</string>
<string name="screen_room_details_requests_to_join_title">"Liittymispyynnöt"</string>
<string name="screen_room_details_roles_and_permissions">"Roolit ja oikeudet"</string>
<string name="screen_room_details_room_name_label">"Huoneen nimi"</string>
<string name="screen_room_details_security_and_privacy_title">"Turvallisuus ja yksityisyys"</string>
<string name="screen_room_details_security_title">"Turvallisuus"</string>
<string name="screen_room_details_share_room_title">"Jaa huone"</string>
<string name="screen_room_details_title">"Huoneen tiedot"</string>
<string name="screen_room_details_topic_title">"Aihe"</string>
<string name="screen_room_details_updating_room">"Muokataan huonetta…"</string>
<string name="screen_room_member_list_banned_empty">"Porttikiellettyjä käyttäjiä ei ole."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d henkilö"</item>
<item quantity="other">"%1$d henkilöä"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Poista jäsen huoneesta ja anna porttikielto"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Poista vain jäsen huoneesta"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Poista porttikielto"</string>
<string name="screen_room_member_list_manage_member_unban_message">"He voivat liittyä tähän huoneeseen uudelleen, jos heidät kutsutaan."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Poista porttikielto huoneesta"</string>
<string name="screen_room_member_list_mode_banned">"Porttikiellot"</string>
<string name="screen_room_member_list_mode_members">"Jäsenet"</string>
<string name="screen_room_member_list_role_administrator">"Ylläpitäjä"</string>
<string name="screen_room_member_list_role_moderator">"Valvoja"</string>
<string name="screen_room_member_list_role_owner">"Omistaja"</string>
<string name="screen_room_member_list_room_members_header_title">"Huoneen jäsenet"</string>
<string name="screen_room_member_list_unbanning_user">"Poistetaan käyttäjän %1$s porttikieltoa"</string>
<string name="screen_room_notification_settings_allow_custom">"Salli mukautettu asetus"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Tämän ottaminen käyttöön ohittaa oletusasetuksesi"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Ilmoita minulle tässä keskustelussa"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Voit muuttaa sen %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"yleisissä asetuksissa"</string>
<string name="screen_room_notification_settings_default_setting_title">"Oletusasetus"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Poista mukautettu asetus"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Ilmoitusasetusten lataamisessa tapahtui virhe."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Oletustilan palauttaminen epäonnistui, yritä uudelleen."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Tilan asettaminen epäonnistui, yritä uudelleen."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Kotipalvelimesi ei tue tätä vaihtoehtoa salatuissa huoneissa, joten et saa ilmoituksia tästä huoneesta."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Kaikista viesteistä"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Vain maininnoista ja avainsanoista"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Ilmoita minulle tässä huoneessa"</string>
<string name="screen_room_roles_and_permissions_admins">"Ylläpitäjät"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Ylläpitäjät ja omistajat"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Vaihda rooliani"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Alenna jäseneksi"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Alenna valvojaksi"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Jäsenten valvonta"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Viestit ja sisältö"</string>
<string name="screen_room_roles_and_permissions_moderators">"Valvojat"</string>
<string name="screen_room_roles_and_permissions_owners">"Omistajat"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Oikeudet"</string>
<string name="screen_room_roles_and_permissions_reset">"Nollaa oikeudet"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Kun nollaat käyttöoikeudet, menetät nykyiset asetukset."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Nollataanko oikeudet?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roolit"</string>
<string name="screen_room_roles_and_permissions_room_details">"Huoneen tiedot"</string>
<string name="screen_room_roles_and_permissions_title">"Roolit ja oikeudet"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Lisää osoite"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Kaikkien on pyydettävä pääsyä."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Pyydä liittymistä"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Kyllä, ota salaus käyttöön"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Kun salaus on kerran otettu käyttöön, sitä ei voi poistaa käytöstä. Viestihistoria näkyy vain huoneen jäsenille kutsusta tai liittymisestä lähtien.
Kukaan muu kuin huoneen jäsenet eivät pysty lukemaan viestejä. Tämä voi estää botteja tai siltoja toimimasta oikein.
Emme suosittele salauksen ottamista käyttöön huoneissa, jotka kuka tahansa voi löytää ja joihin kuka tahansa voi liittyä."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Otetaanko salaus käyttöön?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Kun salaus on kerran otettu käyttöön, sitä ei voi poistaa käytöstä."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Salaus"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Ota päästä päähän -salaus käyttöön"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Kuka tahansa voi liittyä."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Kuka tahansa"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Vain kutsutut henkilöt voivat liittyä."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Vain kutsutut"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Pääsy"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Tilan jäsenet"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Tiloja ei tällä hetkellä tueta"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Tarvitset osoitteen, jotta se näkyy julkisessa hakemistossa."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Osoite"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Salli tämän huoneen löytäminen hakemalla %1$s -palvelimen julkisesta huonehakemistosta."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Anna muiden löytää tämä julkisen hakemiston kautta."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Näkyy julkisessa hakemistossa"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Kuka tahansa"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Kuka voi lukea viestihistoriaa"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Jäsenet vasta kutsusta lähtien"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Jäsenet tämän vaihtoehdon valinnan jälkeen"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Huoneosoitteet ovat tapoja löytää ja käyttää huoneita. Näin voit myös helposti jakaa huoneesi muiden kanssa.
Voit halutessasi julkaista huoneesi kotipalvelimesi julkisessa huonehakemistossa."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Huoneen julkaiseminen"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Näkyvyys"</string>
<string name="screen_security_and_privacy_title">"Turvallisuus ja yksityisyys"</string>
</resources>

View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Vous aurez besoin dune adresse pour le rendre visible dans lannuaire public."</string>
<string name="screen_edit_room_address_title">"Modifier ladresse"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Une erreur sest produite lors de la mise à jour du paramètre de notification."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Votre serveur daccueil ne supporte pas cette option pour les salons chiffrés, vous pourriez ne pas être notifié(e) dans certains salons."</string>
<string name="screen_polls_history_title">"Sondages"</string>
<string name="screen_room_change_permissions_administrators">"Administrateurs"</string>
<string name="screen_room_change_permissions_ban_people">"Bannir des participants"</string>
<string name="screen_room_change_permissions_delete_messages">"Supprimer des messages"</string>
<string name="screen_room_change_permissions_everyone">"Membre"</string>
<string name="screen_room_change_permissions_invite_people">"Inviter des personnes"</string>
<string name="screen_room_change_permissions_member_moderation">"Gérer les membres"</string>
<string name="screen_room_change_permissions_messages_and_content">"Messages et contenus"</string>
<string name="screen_room_change_permissions_moderators">"Modérateurs"</string>
<string name="screen_room_change_permissions_remove_people">"Retirer des personnes"</string>
<string name="screen_room_change_permissions_room_avatar">"Changer lavatar du salon"</string>
<string name="screen_room_change_permissions_room_details">"Modifier les détails"</string>
<string name="screen_room_change_permissions_room_name">"Changer le nom du salon"</string>
<string name="screen_room_change_permissions_room_topic">"Changer le sujet du salon"</string>
<string name="screen_room_change_permissions_send_messages">"Envoyer des messages"</string>
<string name="screen_room_change_role_administrators_title">"Modifier les administrateurs"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Vous ne pourrez pas annuler cette action. Vous êtes en train de promouvoir lutilisateur pour quil ait le même niveau que vous."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Ajouter un administrateur ?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Vous ne pourrez pas annuler cette action. Vous transférez la propriété aux utilisateurs sélectionnés. Une fois que vous serez parti, laction sera définitive."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Transférer la propriété?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Rétrograder"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Vous ne pourrez pas annuler ce changement car vous vous rétrogradez, si vous êtes le dernier utilisateur privilégié du salon il sera impossible de retrouver les privilèges."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Vous rétrograder ?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (En attente)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(En attente)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Les administrateurs ont automatiquement les privilèges des modérateurs"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Les propriétaires disposent automatiquement des privilèges des administrateurs."</string>
<string name="screen_room_change_role_moderators_title">"Modifier les modérateurs"</string>
<string name="screen_room_change_role_owners_title">"Choisissez les propriétaires"</string>
<string name="screen_room_change_role_section_administrators">"Administrateurs"</string>
<string name="screen_room_change_role_section_moderators">"Modérateurs"</string>
<string name="screen_room_change_role_section_users">"Membres"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Vous avez des modifications non-enregistrées."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Enregistrer les changements ?"</string>
<string name="screen_room_details_add_topic_title">"Ajouter un sujet"</string>
<string name="screen_room_details_badge_encrypted">"Chiffré"</string>
<string name="screen_room_details_badge_not_encrypted">"Non chiffré"</string>
<string name="screen_room_details_badge_public">"Salon public"</string>
<string name="screen_room_details_edit_room_title">"Modifier les détails"</string>
<string name="screen_room_details_edition_error">"Une erreur inconnue sest produite et les informations nont pas pu être modifiées."</string>
<string name="screen_room_details_edition_error_title">"Impossible de mettre à jour le salon"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Les messages sont sécurisés par des clés de chiffrement. Seuls vous et les destinataires possédez les clés uniques pour les déverrouiller."</string>
<string name="screen_room_details_encryption_enabled_title">"Chiffrement des messages activé"</string>
<string name="screen_room_details_error_loading_notification_settings">"Une erreur sest produite lors du chargement des paramètres de notification."</string>
<string name="screen_room_details_error_muting">"Échec de la mise en sourdine de ce salon, veuillez réessayer."</string>
<string name="screen_room_details_error_unmuting">"Échec de la désactivation de la mise en sourdine de ce salon, veuillez réessayer."</string>
<string name="screen_room_details_invite_people_dont_close">"Ne fermez pas lapplication avant que lopération soit terminée."</string>
<string name="screen_room_details_invite_people_preparing">"Préparation des invitations…"</string>
<string name="screen_room_details_invite_people_title">"Inviter des amis"</string>
<string name="screen_room_details_leave_conversation_title">"Quitter la discussion"</string>
<string name="screen_room_details_leave_room_title">"Quitter le salon"</string>
<string name="screen_room_details_media_gallery_title">"Médias et fichiers"</string>
<string name="screen_room_details_notification_mode_custom">"Personnalisé"</string>
<string name="screen_room_details_notification_mode_default">"Défaut"</string>
<string name="screen_room_details_notification_title">"Notifications"</string>
<string name="screen_room_details_pinned_events_row_title">"Messages épinglés"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Demandes en attente"</string>
<string name="screen_room_details_roles_and_permissions">"Rôles &amp; autorisations"</string>
<string name="screen_room_details_room_name_label">"Nom du salon"</string>
<string name="screen_room_details_security_and_privacy_title">"Sécurité &amp; confidentialité"</string>
<string name="screen_room_details_security_title">"Sécurité"</string>
<string name="screen_room_details_share_room_title">"Partager le salon"</string>
<string name="screen_room_details_title">"Informations du salon"</string>
<string name="screen_room_details_topic_title">"Sujet"</string>
<string name="screen_room_details_updating_room">"Mise à jour du salon…"</string>
<string name="screen_room_member_list_banned_empty">"Il ny a pas dutilisateur banni."</string>
<plurals name="screen_room_member_list_banned_header_title">
<item quantity="one">"%1$d Banni(e)"</item>
<item quantity="other">"%1$d Banni(e)s"</item>
</plurals>
<string name="screen_room_member_list_empty_search_subtitle">"Vérifiez la saisie ou effectuez une nouvelle recherche"</string>
<string name="screen_room_member_list_empty_search_title">"Aucun résultat pour «%1$s»"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d Personne"</item>
<item quantity="other">"%1$d Personnes"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Bannir du salon"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Retirer le membre uniquement"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Débannir"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Il pourra rejoindre le salon à nouveau si il est invité."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Débannir du salon"</string>
<string name="screen_room_member_list_mode_banned">"Bannis"</string>
<string name="screen_room_member_list_mode_members">"Membres"</string>
<plurals name="screen_room_member_list_pending_header_title">
<item quantity="one">"%1$d Invité(e)"</item>
<item quantity="other">"%1$d Invité(e)s"</item>
</plurals>
<string name="screen_room_member_list_pending_status">"En attente"</string>
<string name="screen_room_member_list_role_administrator">"Administrateurs"</string>
<string name="screen_room_member_list_role_moderator">"Modérateurs"</string>
<string name="screen_room_member_list_role_owner">"Propriétaire"</string>
<string name="screen_room_member_list_room_members_header_title">"Membres du salon"</string>
<string name="screen_room_member_list_unbanning_user">"Débannissement de %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Autoriser les paramètres personnalisés"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Lactivation de cette option annulera votre paramètre par défaut"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Prévenez-moi dans ce salon pour"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Vous pouvez le modifier dans vos %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"paramètres globaux"</string>
<string name="screen_room_notification_settings_default_setting_title">"Paramètre par défaut"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Supprimer le paramètre personnalisé"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Une erreur sest produite lors du chargement des paramètres de notification."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Échec de la restauration du mode par défaut, veuillez réessayer."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Échec de la configuration du mode, veuillez réessayer."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Votre serveur daccueil ne supporte pas cette option pour les salons chiffrés, vous ne serez pas notifié(e) dans ce salon."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Tous les messages"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Mentions et mots clés uniquement"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Dans ce salon, prévenez-moi pour"</string>
<string name="screen_room_roles_and_permissions_admins">"Administrateurs"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administrateurs et propriétaires"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Changer mon rôle"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Devenir simple membre"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Devenir simple modérateur"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Administration des membres"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Messages et contenus"</string>
<string name="screen_room_roles_and_permissions_moderators">"Modérateurs"</string>
<string name="screen_room_roles_and_permissions_owners">"Propriétaires"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Autorisations"</string>
<string name="screen_room_roles_and_permissions_reset">"Réinitialisation des autorisations"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"La réinitialisation des autorisations entraîne la perte des réglages actuels."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Réinitialisation des autorisations ?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Rôles"</string>
<string name="screen_room_roles_and_permissions_room_details">"Détails du salon"</string>
<string name="screen_room_roles_and_permissions_title">"Rôles &amp; autorisations"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Ajouter une adresse"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Tout le monde doit demander un accès."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Demander à rejoindre"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Oui, activer le chiffrement"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Une fois activé, le chiffrement dun salon ne peut pas être désactivé. Lhistorique des messages ne sera visible que pour les membres depuis quils ont été invités ou depuis quils ont rejoint le salon.
Personne dautre que les membres du salon ne pourra lire les messages. Cela peut empêcher les bots et les bridges de fonctionner correctement.
Nous ne recommandons pas dactiver le chiffrement pour les salons que tout le monde peut trouver et rejoindre."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Activer le chiffrement ?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Une fois activé, le chiffrement ne peut pas être désactivé."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Chiffrement"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Activer le chiffrement de bout en bout"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Tout le monde peut rejoindre."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Tout le monde"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Seules les personnes invitées peuvent rejoindre."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Sur invitation uniquement"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Accès"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Membres de lespace"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Les Espaces ne sont pas encore supportés"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Vous aurez besoin dune adresse pour le rendre visible dans lannuaire public."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Adresse"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Autoriser le salon à apparaître dans les résultats de recherche dans le répertoire %1$s des salons publics"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Permet dêtre trouvé en recherchant dans lannuaire public."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Visible dans lannuaire public"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Tout le monde"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Qui peux lire lhistorique"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Les membres uniquement depuis quils ont été invités"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Les membres uniquement depuis la sélection de cette option"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Les adresses de salon sont un moyen de trouver et daccéder aux salons. Cela vous permet également de partager facilement votre salon avec dautres personnes.
Vous pouvez choisir de publier votre salon dans lannuaire des salons publics de votre serveur daccueil."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publication du salon"</string>
<string name="screen_security_and_privacy_room_visibility_section_footer">"Les adresses permettent de trouver et daccéder aux salons et aux espaces. Elles facilitent également leur partage avec dautres personnes."</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Visibilité"</string>
<string name="screen_security_and_privacy_title">"Sécurité &amp; confidentialité"</string>
</resources>

View File

@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Szüksége lesz egy szobacímre, hogy láthatóvá tegye a szobakatalógusban."</string>
<string name="screen_edit_room_address_title">"Cím szerkesztése"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Hiba történt az értesítési beállítás frissítésekor."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"A Matrix-kiszolgálója nem támogatja ezt a beállítást a titkosított szobákban, előfordulhat, hogy egyes szobákban nem kap értesítést."</string>
<string name="screen_polls_history_title">"Szavazások"</string>
<string name="screen_room_change_permissions_administrators">"Adminisztrátor"</string>
<string name="screen_room_change_permissions_ban_people">"Emberek kitiltása"</string>
<string name="screen_room_change_permissions_delete_messages">"Üzenetek eltávolítása"</string>
<string name="screen_room_change_permissions_everyone">"Tag"</string>
<string name="screen_room_change_permissions_invite_people">"Emberek meghívása"</string>
<string name="screen_room_change_permissions_member_moderation">"Tagok kezelése"</string>
<string name="screen_room_change_permissions_messages_and_content">"Üzenetek és tartalom"</string>
<string name="screen_room_change_permissions_moderators">"Moderátor"</string>
<string name="screen_room_change_permissions_remove_people">"Emberek eltávolítása"</string>
<string name="screen_room_change_permissions_room_avatar">"Szoba profilképének módosítása"</string>
<string name="screen_room_change_permissions_room_details">"Részletek szerkesztése"</string>
<string name="screen_room_change_permissions_room_name">"Szoba nevének módosítása"</string>
<string name="screen_room_change_permissions_room_topic">"Szoba témájának módosítása"</string>
<string name="screen_room_change_permissions_send_messages">"Üzenetek küldése"</string>
<string name="screen_room_change_role_administrators_title">"Adminisztrátorok szerkesztése"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Ezt a műveletet nem fogja tudja visszavonni. Ugyanarra a szintre lépteti elő a felhasználót, mint amellyel Ön is rendelkezik."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Adminisztrátor hozzáadása?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Ezt a műveletet nem lehet visszavonni. A tulajdonjogot a kiválasztott felhasználókra ruházza át. Távozás után a művelet véglegessé válik."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Átruházza a tulajdonjogot?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Lefokozás"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Ezt a változtatást nem fogja tudni visszavonni, mivel lefokozza magát, ha Ön az utolsó jogosultságokkal rendelkező felhasználó a szobában, akkor lehetetlen lesz visszaszerezni a jogosultságokat."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Lefokozza magát?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (függőben)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Függőben)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Az adminisztrátorok automatikusan moderátori jogosultságokkal rendelkeznek"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"A tulajdonosok automatikusan adminisztrátori jogosultsággal rendelkeznek."</string>
<string name="screen_room_change_role_moderators_title">"Moderátorok szerkesztése"</string>
<string name="screen_room_change_role_owners_title">"Tulajdonosok kiválasztása"</string>
<string name="screen_room_change_role_section_administrators">"Adminisztrátorok"</string>
<string name="screen_room_change_role_section_moderators">"Moderátorok"</string>
<string name="screen_room_change_role_section_users">"Tagok"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Mentetlen módosításai vannak."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Menti a módosításokat?"</string>
<string name="screen_room_details_add_topic_title">"Téma hozzáadása"</string>
<string name="screen_room_details_badge_encrypted">"Titkosított"</string>
<string name="screen_room_details_badge_not_encrypted">"Nem titkosított"</string>
<string name="screen_room_details_badge_public">"Nyilvános szoba"</string>
<string name="screen_room_details_edit_room_title">"Részletek szerkesztése"</string>
<string name="screen_room_details_edition_error">"Ismeretlen hiba történt, és az információkat nem lehetett megváltoztatni."</string>
<string name="screen_room_details_edition_error_title">"Nem sikerült frissíteni a szobát"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Az üzeneteket kulcsok védik. Csak Ön és a címzett rendelkezik a feloldásukhoz szükséges egyedi kulcsokkal."</string>
<string name="screen_room_details_encryption_enabled_title">"Az üzenettitkosítás engedélyezve"</string>
<string name="screen_room_details_error_loading_notification_settings">"Hiba történt az értesítési beállítások betöltésekor."</string>
<string name="screen_room_details_error_muting">"Nem sikerült elnémítani ezt a szobát, próbálja újra."</string>
<string name="screen_room_details_error_unmuting">"Nem sikerült feloldani a szoba némítását, próbálja újra."</string>
<string name="screen_room_details_invite_people_dont_close">"Ne zárja be az alkalmazást, amíg nem végzett."</string>
<string name="screen_room_details_invite_people_preparing">"Meghívók előkészítése…"</string>
<string name="screen_room_details_invite_people_title">"Ismerősök meghívása"</string>
<string name="screen_room_details_leave_conversation_title">"Beszélgetés elhagyása"</string>
<string name="screen_room_details_leave_room_title">"Szoba elhagyása"</string>
<string name="screen_room_details_media_gallery_title">"Média és fájlok"</string>
<string name="screen_room_details_notification_mode_custom">"Egyéni"</string>
<string name="screen_room_details_notification_mode_default">"Alapértelmezett"</string>
<string name="screen_room_details_notification_title">"Értesítések"</string>
<string name="screen_room_details_pinned_events_row_title">"Kitűzött üzenetek"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Csatlakozási kérelem"</string>
<string name="screen_room_details_roles_and_permissions">"Szerepkörök és jogosultságok"</string>
<string name="screen_room_details_room_name_label">"Szoba neve"</string>
<string name="screen_room_details_security_and_privacy_title">"Biztonság és adatvédelem"</string>
<string name="screen_room_details_security_title">"Biztonság"</string>
<string name="screen_room_details_share_room_title">"Szoba megosztása"</string>
<string name="screen_room_details_title">"Szobainformációk"</string>
<string name="screen_room_details_topic_title">"Téma"</string>
<string name="screen_room_details_updating_room">"Szoba frissítése…"</string>
<string name="screen_room_member_list_banned_empty">"Ebben a szobában nincsenek kitiltott felhasználók."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d személy"</item>
<item quantity="other">"%1$d személy"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Eltávolítás és a tag kitiltása"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Csak a tag eltávolítása"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Tiltás feloldása"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Ehhez a szobához is csatlakozhat, ha meghívják."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Visszaengedés a szobába"</string>
<string name="screen_room_member_list_mode_banned">"Kitiltva"</string>
<string name="screen_room_member_list_mode_members">"Tagok"</string>
<string name="screen_room_member_list_pending_status">"Függőben"</string>
<string name="screen_room_member_list_role_administrator">"Adminisztrátor"</string>
<string name="screen_room_member_list_role_moderator">"Moderátor"</string>
<string name="screen_room_member_list_role_owner">"Tulajdonos"</string>
<string name="screen_room_member_list_room_members_header_title">"Szoba tagjai"</string>
<string name="screen_room_member_list_unbanning_user">"%1$s tiltásának feloldása"</string>
<string name="screen_room_notification_settings_allow_custom">"Egyéni beállítás engedélyezése"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Ennek bekapcsolása felülírja az alapértelmezett beállítást"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Értesítések kérése ebben a csevegésben ezekről:"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Megváltoztathatja a %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"globális beállításokban"</string>
<string name="screen_room_notification_settings_default_setting_title">"Alapértelmezett beállítás"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Egyéni beállítás eltávolítása"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Hiba történt az értesítési beállítások betöltésekor."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Nem sikerült visszaállítani az alapértelmezett módot, próbálja újra."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Nem sikerült a mód beállítása, próbálja újra."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"A Matrix-kiszolgálója nem támogatja ezt a beállítást a titkosított szobákban, egyes szobákban nem fog értesítéseket kapni."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Összes üzenet"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Csak említések és kulcsszavak"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Ebben a szobában, értesítés ezekről:"</string>
<string name="screen_room_roles_and_permissions_admins">"Adminisztrátorok"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Adminisztrátorok és tulajdonosok"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Saját szerepkör módosítása"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Lefokozás taggá"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Lefokozás moderátorrá"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Tagok moderálása"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Üzenetek és tartalom"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderátorok"</string>
<string name="screen_room_roles_and_permissions_owners">"Tulajdonosok"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Jogosultságok"</string>
<string name="screen_room_roles_and_permissions_reset">"Jogosultságok visszaállítása"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"A jogosultságok visszaállítása után a jelenlegi beállítások elvesznek."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Jogosultságok visszaállítása?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Szerepkörök"</string>
<string name="screen_room_roles_and_permissions_room_details">"Szoba részletei"</string>
<string name="screen_room_roles_and_permissions_title">"Szerepkörök és jogosultságok"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Cím hozzáadása"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Mindenkinek hozzáférést kell kérnie."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Csatlakozás kérése"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Igen, engedélyezze a titkosítást"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Az engedélyezés után a szoba titkosítása nem tiltható le. Az üzenetek előzményei csak a szobatagok számára láthatók, amikor meghívást kaptak, vagy mióta csatlakoztak a szobához.
A szobatagokon kívül senki sem tudja olvasni az üzeneteket. Ez megakadályozhatja a botok és a hidak megfelelő működését.
Nem javasoljuk a titkosítás engedélyezését az olyan szobákban, amelyeket bárki megtalálhat és csatlakozhat."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Engedélyezi a titkosítást?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Engedélyezés után a titkosítás nem tiltható le."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Titkosítás"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Végpontok közötti titkosítás engedélyezése"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Bárki csatlakozhat."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Bárki"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Csak a meghívott emberek léphetnek be."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Csak meghívásos"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Hozzáférés"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"A tér tagjai"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"A terek jelenleg nem támogatottak"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Szüksége lesz egy szobacímre, hogy láthatóvá tegye a szobakatalógusban."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Cím"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"A szoba megtalálhatóvá tétele a(z) %1$s nyilvános szobakatalógusában való kereséssel."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Lehetővé teszi, hogy a nyilvános szobakatalógusban megtalálható legyen."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Látható a nyilvános szobakatalógusban"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Bárki"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Ki olvashatja az előzményeket"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Csak a tagok, a meghívásuktól kezdődően"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Csak a tagok, a beállítás választásától kezdődően"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"A szobacímek a szobák megtalálásának és elérésnek módjai. Ez azt is biztosítja, hogy könnyen megoszthatja a szobáját másokkal.
Kiválaszthatja, hogy szobáját közzéteszi-e a Matrix-kiszolgáló nyilvános szobakatalógusában."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Szoba közzététele"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Láthatóság"</string>
<string name="screen_security_and_privacy_title">"Biztonság és adatvédelem"</string>
</resources>

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Anda akan memerlukan alamat ruangan untuk membuatnya terlihat dalam direktori."</string>
<string name="screen_edit_room_address_title">"Alamat ruangan"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Terjadi kesalahan saat memperbarui pengaturan pemberitahuan."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Homeserver Anda tidak mendukung opsi ini dalam ruangan terenkripsi, Anda mungkin tidak diberi tahu dalam beberapa ruangan."</string>
<string name="screen_polls_history_title">"Pemungutan suara"</string>
<string name="screen_room_change_permissions_administrators">"Hanya admin"</string>
<string name="screen_room_change_permissions_ban_people">"Cekal orang-orang"</string>
<string name="screen_room_change_permissions_delete_messages">"Hilangkan pesan"</string>
<string name="screen_room_change_permissions_invite_people">"Undang orang-orang dan terima permintaan untuk bergabung"</string>
<string name="screen_room_change_permissions_messages_and_content">"Pesan dan konten"</string>
<string name="screen_room_change_permissions_moderators">"Admin dan moderator"</string>
<string name="screen_room_change_permissions_remove_people">"Keluarkan orang-orang dan tolak permintaan untuk bergabung"</string>
<string name="screen_room_change_permissions_room_avatar">"Ubah avatar ruangan"</string>
<string name="screen_room_change_permissions_room_details">"Sunting Ruangan"</string>
<string name="screen_room_change_permissions_room_name">"Ubah nama ruangan"</string>
<string name="screen_room_change_permissions_room_topic">"Ubah topik ruangan"</string>
<string name="screen_room_change_permissions_send_messages">"Kirim pesan"</string>
<string name="screen_room_change_role_administrators_title">"Sunting Admin"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Anda tidak akan dapat mengurungkan tindakan ini. Anda mempromosikan pengguna untuk memiliki tingkat daya yang sama seperti Anda."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Tambahkan Admin?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Turunkan"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Anda tidak akan dapat mengurungkan perubahan ini karena Anda sedang menurunkan Anda sendiri, jika Anda merupakan pengguna dengan hak khusus dalam ruangan maka tidak akan memungkinkan untuk mendapatkan hak tersebut lagi."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Turunkan Anda sendiri?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Tertunda)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Tertunda)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Admin secara otomatis memiliki hak moderator"</string>
<string name="screen_room_change_role_moderators_title">"Sunting Moderator"</string>
<string name="screen_room_change_role_section_administrators">"Admin"</string>
<string name="screen_room_change_role_section_moderators">"Moderator"</string>
<string name="screen_room_change_role_section_users">"Anggota"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Anda memiliki perubahan yang belum disimpan."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Simpan perubahan?"</string>
<string name="screen_room_details_add_topic_title">"Tambahkan topik"</string>
<string name="screen_room_details_badge_encrypted">"Terenkripsi"</string>
<string name="screen_room_details_badge_not_encrypted">"Tidak terenkripsi"</string>
<string name="screen_room_details_badge_public">"Ruangan publik"</string>
<string name="screen_room_details_edit_room_title">"Sunting Ruangan"</string>
<string name="screen_room_details_edition_error">"Terjadi kesalahan yang tidak diketahui dan informasinya tidak dapat diubah."</string>
<string name="screen_room_details_edition_error_title">"Tidak dapat memperbarui ruangan"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Pesan diamankan dengan kunci. Hanya Anda dan penerima yang memiliki kunci unik untuk membukanya."</string>
<string name="screen_room_details_encryption_enabled_title">"Enkripsi pesan diaktifkan"</string>
<string name="screen_room_details_error_loading_notification_settings">"Terjadi kesalahan saat memuat pengaturan notifikasi."</string>
<string name="screen_room_details_error_muting">"Gagal membisukan ruangan ini, silakan coba lagi."</string>
<string name="screen_room_details_error_unmuting">"Gagal membunyikan ruangan ini, silakan coba lagi."</string>
<string name="screen_room_details_invite_people_title">"Undang orang-orang"</string>
<string name="screen_room_details_leave_conversation_title">"Tinggalkan percakapan"</string>
<string name="screen_room_details_leave_room_title">"Tinggalkan ruangan"</string>
<string name="screen_room_details_media_gallery_title">"Media dan berkas"</string>
<string name="screen_room_details_notification_mode_custom">"Khusus"</string>
<string name="screen_room_details_notification_mode_default">"Bawaan"</string>
<string name="screen_room_details_notification_title">"Notifikasi"</string>
<string name="screen_room_details_pinned_events_row_title">"Pesan yang disematkan"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Permintaan untuk bergabung"</string>
<string name="screen_room_details_roles_and_permissions">"Peran dan perizinan"</string>
<string name="screen_room_details_room_name_label">"Nama ruangan"</string>
<string name="screen_room_details_security_and_privacy_title">"Keamanan &amp; privasi"</string>
<string name="screen_room_details_security_title">"Keamanan"</string>
<string name="screen_room_details_share_room_title">"Bagikan ruangan"</string>
<string name="screen_room_details_title">"Info ruangan"</string>
<string name="screen_room_details_topic_title">"Topik"</string>
<string name="screen_room_details_updating_room">"Memperbarui ruangan…"</string>
<string name="screen_room_member_list_banned_empty">"Tidak ada pengguna yang dicekal dalam ruangan ini."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="other">"%1$d orang"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Keluarkan dan cekal anggota"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Hanya keluarkan anggota"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Batalkan pencekalan"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Pengguna dapat bergabung ke ruangan ini lagi jika diundang."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Batalkan cekalan dari ruangan"</string>
<string name="screen_room_member_list_mode_banned">"Tercekal"</string>
<string name="screen_room_member_list_mode_members">"Anggota"</string>
<string name="screen_room_member_list_role_administrator">"Hanya admin"</string>
<string name="screen_room_member_list_role_moderator">"Admin dan moderator"</string>
<string name="screen_room_member_list_room_members_header_title">"Anggota ruangan"</string>
<string name="screen_room_member_list_unbanning_user">"Membatalkan cekalan %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Izinkan pengaturan khusus"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Mengaktifkan ini akan mengganti pengaturan bawaan Anda"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Beri tahu saya di obrolan ini tentang"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Anda dapat mengubahnya di %1$s Anda."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"pengaturan global"</string>
<string name="screen_room_notification_settings_default_setting_title">"Pengaturan bawaan"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Hapus pengaturan khusus"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Terjadi kesalahan saat memuat pengaturan pemberitahuan."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Gagal memulihkan mode bawaan, silakan coba lagi."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Gagal mengatur mode, silakan coba lagi."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Homeserver Anda tidak mendukung opsi ini dalam ruangan terenkripsi, Anda tidak akan diberi tahu dalam ruangan ini."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Semua pesan"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Sebutan dan Kata Kunci saja"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Di ruangan ini, beri tahu saya tentang"</string>
<string name="screen_room_roles_and_permissions_admins">"Admin"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Ubah peran saya"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Turunkan ke anggota"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Turunkan ke moderator"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderasi anggota"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Pesan dan konten"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderator"</string>
<string name="screen_room_roles_and_permissions_reset">"Atur ulang perizinan"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Setelah Anda mengatur ulang perizinan, Anda akan kehilangan pengaturan Anda saat ini."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Atur ulang perizinan?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Peran"</string>
<string name="screen_room_roles_and_permissions_room_details">"Detail ruangan"</string>
<string name="screen_room_roles_and_permissions_title">"Peran dan perizinan"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Tambahkan alamat ruangan"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Minta untuk bergabung"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ya, aktifkan enkripsi"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Setelah diaktifkan, encryption untuk sebuah ruangan tidak dapat dinonaktifkan, Riwayat pesan hanya akan terlihat oleh anggota ruangan sejak mereka diundang atau sejak mereka bergabung dengan ruangan tersebut.
Tidak ada orang lain selain anggota ruangan yang dapat membaca pesan. Hal ini dapat mencegah bot dan jembatan bekerja dengan benar.
Kami tidak menyarankan untuk mengaktifkan enkripsi untuk ruangan yang dapat ditemukan dan diikuti oleh siapa pun."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Aktifkan enkripsi?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Setelah diaktifkan, enkripsi tidak dapat dinonaktifkan."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Enkripsi"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Aktifkan enkripsi ujung ke ujung"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Siapa pun dapat menemukan dan bergabung"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Siapa pun"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Orang hanya dapat bergabung jika mereka diundang"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Hanya undangan"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Akses ruangan"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Anggota space"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Space saat ini tidak didukung"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Anda akan memerlukan alamat ruangan untuk membuatnya terlihat dalam direktori."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Izinkan ruangan ini ditemukan dengan mencari direktori ruangan %1$s publik"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Terlihat di direktori ruangan publik"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Siapa pun"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Siapa yang bisa membaca riwayat"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Hanya anggota sejak mereka diundang"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Hanya anggota sejak memilih opsi ini"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Alamat ruangan adalah cara untuk menemukan dan mengakses ruangan. Ini juga memastikan Anda dapat dengan mudah berbagi ruangan dengan orang lain. Anda dapat memilih untuk menerbitkan ruangan Anda di direktori ruangan publik homeserver Anda."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Penerbitan ruangan"</string>
<string name="screen_security_and_privacy_title">"Keamanan &amp; privasi"</string>
</resources>

View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Per renderlo visibile nell\'elenco pubblico, avrai bisogno di un indirizzo."</string>
<string name="screen_edit_room_address_title">"Modifica indirizzo"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Si è verificato un errore durante l\'aggiornamento delle impostazioni di notifica."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Il tuo homeserver non supporta questa opzione nelle stanze crifrate, quindi potresti non ricevere notifiche in alcune stanze."</string>
<string name="screen_polls_history_title">"Sondaggi"</string>
<string name="screen_room_change_permissions_administrators">"Amministratore"</string>
<string name="screen_room_change_permissions_ban_people">"Escludi membri"</string>
<string name="screen_room_change_permissions_delete_messages">"Rimuovi messaggi"</string>
<string name="screen_room_change_permissions_everyone">"Membro"</string>
<string name="screen_room_change_permissions_invite_people">"Invita persone"</string>
<string name="screen_room_change_permissions_member_moderation">"Gestisci membri"</string>
<string name="screen_room_change_permissions_messages_and_content">"Messaggi e contenuti"</string>
<string name="screen_room_change_permissions_moderators">"Moderatore"</string>
<string name="screen_room_change_permissions_remove_people">"Rimuovi membri"</string>
<string name="screen_room_change_permissions_room_avatar">"Cambia avatar della stanza"</string>
<string name="screen_room_change_permissions_room_details">"Modifica dettagli"</string>
<string name="screen_room_change_permissions_room_name">"Cambia il nome della stanza"</string>
<string name="screen_room_change_permissions_room_topic">"Cambiare l\'argomento della stanza"</string>
<string name="screen_room_change_permissions_send_messages">"Inviare messaggi"</string>
<string name="screen_room_change_role_administrators_title">"Modifica amministratori"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Non potrai annullare questa azione. Stai promuovendo l\'utente al tuo stesso livello di potere."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Aggiungi amministratore?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Non potrai annullare questa azione. Stai trasferendo la proprietà agli utenti selezionati. Una volta abbandonato, questa azione sarà definitiva."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Trasferire proprietà?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Declassa"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Non potrai annullare questa modifica perché ti stai declassando, se sei l\'ultimo utente privilegiato nella stanza, sarà impossibile riottenere i privilegi."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Declassare te stesso?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (In attesa)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(In attesa)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Gli amministratori hanno automaticamente i privilegi di moderatore"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"I proprietari hanno automaticamente privilegi di amministratore."</string>
<string name="screen_room_change_role_moderators_title">"Modifica moderatori"</string>
<string name="screen_room_change_role_owners_title">"Scegli i proprietari"</string>
<string name="screen_room_change_role_section_administrators">"Amministratori"</string>
<string name="screen_room_change_role_section_moderators">"Moderatori"</string>
<string name="screen_room_change_role_section_users">"Membri"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Hai delle modifiche non salvate."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Salvare le modifiche?"</string>
<string name="screen_room_details_add_topic_title">"Aggiungi argomento"</string>
<string name="screen_room_details_badge_encrypted">"Cifrata"</string>
<string name="screen_room_details_badge_not_encrypted">"Non cifrata"</string>
<string name="screen_room_details_badge_public">"Stanza pubblica"</string>
<string name="screen_room_details_edit_room_title">"Modifica dettagli"</string>
<string name="screen_room_details_edition_error">"Si è verificato un errore sconosciuto e non è stato possibile modificare le informazioni."</string>
<string name="screen_room_details_edition_error_title">"Impossibile aggiornare la stanza"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"I messaggi sono protetti da lucchetti. Solo tu e i destinatari avete le chiavi univoche per sbloccarli."</string>
<string name="screen_room_details_encryption_enabled_title">"Crittografia messaggi abilitata"</string>
<string name="screen_room_details_error_loading_notification_settings">"Si è verificato un errore durante il caricamento delle impostazioni di notifica."</string>
<string name="screen_room_details_error_muting">"Impostazione del silenzioso fallita per questa stanza, riprova."</string>
<string name="screen_room_details_error_unmuting">"Disattivazione del silenzioso di questa stanza fallita, riprova."</string>
<string name="screen_room_details_invite_people_dont_close">"Non chiudere l\'app fino al completamento."</string>
<string name="screen_room_details_invite_people_preparing">"Preparazione degli inviti…"</string>
<string name="screen_room_details_invite_people_title">"Invita persone"</string>
<string name="screen_room_details_leave_conversation_title">"Abbandona la conversazione"</string>
<string name="screen_room_details_leave_room_title">"Esci dalla stanza"</string>
<string name="screen_room_details_media_gallery_title">"File e contenuti multimediali"</string>
<string name="screen_room_details_notification_mode_custom">"Personalizzato"</string>
<string name="screen_room_details_notification_mode_default">"Predefinito"</string>
<string name="screen_room_details_notification_title">"Notifiche"</string>
<string name="screen_room_details_pinned_events_row_title">"Messaggi fissati"</string>
<string name="screen_room_details_profile_row_title">"Profilo"</string>
<string name="screen_room_details_requests_to_join_title">"Richieste di accesso"</string>
<string name="screen_room_details_roles_and_permissions">"Ruoli e autorizzazioni"</string>
<string name="screen_room_details_room_name_label">"Nome stanza"</string>
<string name="screen_room_details_security_and_privacy_title">"Sicurezza e privacy"</string>
<string name="screen_room_details_security_title">"Sicurezza"</string>
<string name="screen_room_details_share_room_title">"Condividi stanza"</string>
<string name="screen_room_details_title">"Informazioni sulla stanza"</string>
<string name="screen_room_details_topic_title">"Argomento"</string>
<string name="screen_room_details_updating_room">"Aggiornamento della stanza…"</string>
<string name="screen_room_member_list_banned_empty">"Non ci sono utenti bannati."</string>
<plurals name="screen_room_member_list_banned_header_title">
<item quantity="one">"%1$d Bannato"</item>
<item quantity="other">"%1$d Bannati"</item>
</plurals>
<string name="screen_room_member_list_empty_search_subtitle">"Controlla l\'ortografia o prova una nuova ricerca"</string>
<string name="screen_room_member_list_empty_search_title">"Nessun risultato per “%1$s ”"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d Persona"</item>
<item quantity="other">"%1$d Persone"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Rimuovi ed escludi"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Rimuovi soltanto"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Riammetti"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Potrà entrare nuovamente in questa stanza se invitato."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Riammetti nella stanza"</string>
<string name="screen_room_member_list_mode_banned">"Esclusi"</string>
<string name="screen_room_member_list_mode_members">"Membri"</string>
<plurals name="screen_room_member_list_pending_header_title">
<item quantity="one">"%1$d Invitato"</item>
<item quantity="other">"%1$d Invitati"</item>
</plurals>
<string name="screen_room_member_list_pending_status">"In attesa"</string>
<string name="screen_room_member_list_role_administrator">"Amministratore"</string>
<string name="screen_room_member_list_role_moderator">"Moderatore"</string>
<string name="screen_room_member_list_role_owner">"Proprietario"</string>
<string name="screen_room_member_list_room_members_header_title">"Membri della stanza"</string>
<string name="screen_room_member_list_unbanning_user">"Riammissione di %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Consenti impostazione personalizzata"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"L\'attivazione di questa opzione sovrascriverà l\'impostazione predefinita"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Avvisami in questa chat per"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Puoi cambiarlo nelle tue %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"impostazioni globali"</string>
<string name="screen_room_notification_settings_default_setting_title">"Impostazione predefinita"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Rimuovi l\'impostazione personalizzata"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Si è verificato un errore durante il caricamento delle impostazioni di notifica."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Ripristino della modalità predefinita fallito, riprova."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Impossibile impostare la modalità, riprova."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Il tuo homeserver non supporta questa opzione nelle stanze cifrate, quindi non riceverai notifiche in questa stanza."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Tutti i messaggi"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Solo menzioni e parole chiave"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"In questa stanza, avvisami per"</string>
<string name="screen_room_roles_and_permissions_admins">"Amministratori"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Amministratori e proprietari"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Cambia il mio ruolo"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Declassa a membro"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Declassa a moderatore"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderazione dei membri"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Messaggi e contenuti"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatori"</string>
<string name="screen_room_roles_and_permissions_owners">"Proprietari"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Autorizzazioni"</string>
<string name="screen_room_roles_and_permissions_reset">"Reimpostare le autorizzazioni"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Una volta reimpostate le autorizzazioni, perderai le impostazioni correnti."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Reimpostare autorizzazioni?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Ruoli"</string>
<string name="screen_room_roles_and_permissions_room_details">"Dettagli della stanza"</string>
<string name="screen_room_roles_and_permissions_title">"Ruoli e autorizzazioni"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Aggiungi indirizzo"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Chiunque deve richiedere l\'accesso."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Chiedi di entrare"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Sì, attiva la crittografia"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Una volta attivata, la crittografia di una stanza non può essere disattivata, la cronologia dei messaggi sarà visibile solo ai membri della stanza da quando sono stati invitati o da quando sono entrati nella stanza.
Nessuno, oltre ai membri della stanza, sarà in grado di leggere i messaggi. Ciò potrebbe impedire ai bot e ai bridge di funzionare correttamente.
Non consigliamo di attivare la crittografia per le stanze che chiunque può trovare e in cui può entrare."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Attivare la crittografia?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Una volta attivata, la crittografia non può essere disattivata."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Crittografia"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Attiva la crittografia end-to-end"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Chiunque può partecipare."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Chiunque"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Solo le persone invitate possono entrare."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Solo su invito"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Accesso"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Membri dello spazio"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Gli spazi non sono attualmente supportati"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Per renderlo visibile nell\'elenco pubblico, avrai bisogno di un indirizzo."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Indirizzo"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Consenti la ricerca di questa stanza effettuando una ricerca nell\'elenco delle stanze pubbliche di %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Consenti di essere trovato effettuando una ricerca nell\'elenco pubblico."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Visibile nell\'elenco pubblico"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Chiunque"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Chi può leggere la cronologia messaggi"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Solo membri da quando sono stati invitati"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Solo membri da dopo aver selezionato questa opzione"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Gli indirizzi delle stanze sono modi per trovare e accedervi. In questo modo puoi anche condividere facilmente la tua stanze con altri.
Puoi scegliere di pubblicare la tua stanza nell\'elenco delle stanza pubbliche dell\'homeserver."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Pubblicazione della stanza"</string>
<string name="screen_security_and_privacy_room_visibility_section_footer">"Gli indirizzi sono un modo per trovare e accedere a stanze e spazi. Questo ti consente anche di condividerli facilmente con altri."</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Visibilità"</string>
<string name="screen_security_and_privacy_title">"Sicurezza e privacy"</string>
</resources>

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_notification_settings_edit_failed_updating_default_mode">"შეტყობინებების პარამეტრის განახლებისას მოხდა შეცდომა."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"თქვენი სახლის სერვერი არ უჭერს მხარს ამ პარამეტრს დაშიფრულ ოთახებში, ზოგიერთ ოთახში შეიძლება არ მიიღოთ შეტყობინება."</string>
<string name="screen_polls_history_title">"გამოკითხვები"</string>
<string name="screen_room_change_permissions_administrators">"მხოლოდ ადმინისტრატორები"</string>
<string name="screen_room_change_permissions_ban_people">"მომხმარებლების დაბლოკვა"</string>
<string name="screen_room_change_permissions_delete_messages">"შეტყობინებების წაშლა"</string>
<string name="screen_room_change_permissions_invite_people">"მომხმარებლების მოწვევა და გაწევრიანების მოთხოვნების დადასტურება"</string>
<string name="screen_room_change_permissions_messages_and_content">"შეტყობინებები და შინაარსი"</string>
<string name="screen_room_change_permissions_moderators">"ადმინისტრატორები და მოდერატორები"</string>
<string name="screen_room_change_permissions_remove_people">"მომხმარებლების გაგდება და გაწევრიანების მოთხოვნების უარყოფა"</string>
<string name="screen_room_change_permissions_room_avatar">"ოთახის სურათის შეცვლა"</string>
<string name="screen_room_change_permissions_room_details">"ოთახის რედაქტირება"</string>
<string name="screen_room_change_permissions_room_name">"ოთახის სახელის შეცვლა"</string>
<string name="screen_room_change_permissions_room_topic">"ოთახის თემის შეცვლა"</string>
<string name="screen_room_change_permissions_send_messages">"შეტყობინებების გაგზავნა"</string>
<string name="screen_room_change_role_administrators_title">"ადმინისტრატორების რედაქტირება"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"ამ მოქმედების გაუქმებას ვერ შეძლებთ. თქვენ ნიშნავთ ამ მომხმარებელს იმავე ძალაუფლების დონეზე, რომელიც გაქვთ თქვენ."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"ადმინისტრატორის დამატება?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"დაქვეითება"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"იმის გამო, რომ აქვეითებთ თქვენ თავს, ამ მოქმედებას ვერ გააუქმებთ. პრივილეგიების აღდგენა შეუძლებელია თუ თქვენ ბოლო პრივილეგირებული მომხმარებელი ხართ ამ ოთახში."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"გსურთ საკუთარი თავის დაქვეითება?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (მოლოდინი)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(მოლოდინში)"</string>
<string name="screen_room_change_role_moderators_title">"მოდერატორების რედაქტირება"</string>
<string name="screen_room_change_role_section_administrators">"ადმინისტრატორები"</string>
<string name="screen_room_change_role_section_moderators">"მოდერატორები"</string>
<string name="screen_room_change_role_section_users">"წევრები"</string>
<string name="screen_room_change_role_unsaved_changes_description">"თქვენ გაქვთ შეუნახავი ცვლილებები"</string>
<string name="screen_room_change_role_unsaved_changes_title">"შენახვა?"</string>
<string name="screen_room_details_add_topic_title">"თემის დამატება"</string>
<string name="screen_room_details_edit_room_title">"ოთახის რედაქტირება"</string>
<string name="screen_room_details_edition_error">"უცნობი შეცდომა მოხდა. ინფორმაციის შეცვლა ვერ მოხერხდა."</string>
<string name="screen_room_details_edition_error_title">"ოთახის განახლება შეუძლებელია"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"შეტყობინებები დაცულია საკეტებით. მხოლოდ თქვენ და მიმღებებს გაქვთ მათი განშიფვრის უნიკალური გასაღებები."</string>
<string name="screen_room_details_encryption_enabled_title">"შეტყობინების დაშიფვრა ჩართულია"</string>
<string name="screen_room_details_error_loading_notification_settings">"შეტყობინებების პარამეტრების ჩატვირთვისას მოხდა შეცდომა."</string>
<string name="screen_room_details_error_muting">"ამ ოთახის დადუმება ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა."</string>
<string name="screen_room_details_error_unmuting">"ამ ოთახის დადუმების მოხსნა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა."</string>
<string name="screen_room_details_invite_people_title">"ხალხის მოწვევა"</string>
<string name="screen_room_details_leave_conversation_title">"საუბრის დატოვება"</string>
<string name="screen_room_details_leave_room_title">"ოთახის დატოვება"</string>
<string name="screen_room_details_notification_mode_custom">"მორგებული"</string>
<string name="screen_room_details_notification_mode_default">"ნაგულისხმევი"</string>
<string name="screen_room_details_notification_title">"შეტყობინებები"</string>
<string name="screen_room_details_profile_row_title">"პროფილი"</string>
<string name="screen_room_details_roles_and_permissions">"როლები და ნებართვები"</string>
<string name="screen_room_details_room_name_label">"ოთახის სახელი"</string>
<string name="screen_room_details_security_title">"უსაფრთხოება"</string>
<string name="screen_room_details_share_room_title">"ოთახის გაზიარება"</string>
<string name="screen_room_details_title">"ოთახის ინფორმაცია"</string>
<string name="screen_room_details_topic_title">"თემა"</string>
<string name="screen_room_details_updating_room">"ოთახის განახლება…"</string>
<string name="screen_room_member_list_banned_empty">"ამ ოთახში არაა დაბლოკილი მომხმარებლები."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d ადამიანი"</item>
<item quantity="other">"%1$d ადამიანი"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"წევრის წაშლა და დაბლოკვა"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"მხოლოდ წევრის წაშლა"</string>
<string name="screen_room_member_list_manage_member_unban_action">"განბლოკვა"</string>
<string name="screen_room_member_list_manage_member_unban_message">"მოწვევის შემთხვევაში განბლოკილი მომხმარებელი ისევ შეძლებს ოთახს შეუერთდეს."</string>
<string name="screen_room_member_list_mode_banned">"დაბლოკილები"</string>
<string name="screen_room_member_list_mode_members">"წევრები"</string>
<string name="screen_room_member_list_role_administrator">"მხოლოდ ადმინისტრატორები"</string>
<string name="screen_room_member_list_role_moderator">"ადმინისტრატორები და მოდერატორები"</string>
<string name="screen_room_member_list_room_members_header_title">"ოთახის წევრები"</string>
<string name="screen_room_member_list_unbanning_user">"%1$s-ს განბლოკვა"</string>
<string name="screen_room_notification_settings_allow_custom">"მორგებული პარამეტრის დაშვება"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"ამის ჩართვა უგულებელყოფს თქვენს ნაგულისხმევ პარამეტრს"</string>
<string name="screen_room_notification_settings_custom_settings_title">"ამ ჩატში ჩემი შეტყობინება:"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"თქვენ შეგიძლიათ შეცვალოთ იგი თქვენს %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"გლობალური პარამეტრები"</string>
<string name="screen_room_notification_settings_default_setting_title">"Სტანდარტული პარამეტრები"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"მორგებული პარამეტრის წაშლა"</string>
<string name="screen_room_notification_settings_error_loading_settings">"შეტყობინებების პარამეტრების ჩატვირთვისას მოხდა შეცდომა."</string>
<string name="screen_room_notification_settings_error_restoring_default">"ნაგულისხმევი რეჟიმის აღდგენა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა."</string>
<string name="screen_room_notification_settings_error_setting_mode">"რეჟიმის დაყენება ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"თქვენი სახლის სერვერი არ უჭერს მხარს ამ პარამეტრს დაშიფრულ ოთახებში, თქვენ არ მიიღებთ შეტყობინებას ამ ოთახში."</string>
<string name="screen_room_notification_settings_mode_all_messages">"ყველა შეტყობინება"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"მხოლოდ ხსენებები და საკვანძო სიტყვები"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"ამ ოთახში, შემატყობინეთ:"</string>
<string name="screen_room_roles_and_permissions_admins">"ადმინისტრატორები"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"ჩემი როლის შეცვლა"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"დაქვეითება წევრამდე"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"დაქვეითება მოდერატორამდე"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"წევრების მოდერირება"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"შეტყობინებები და შინაარსი"</string>
<string name="screen_room_roles_and_permissions_moderators">"მოდერატორები"</string>
<string name="screen_room_roles_and_permissions_reset">"ნებართვების გადაყენება"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"ნებართვების გადაყენების შემთხვევაში მიმდინარე პარამეტრებს დაკარგავთ."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"გადავაყენოთ ცვლილებები?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"როლები"</string>
<string name="screen_room_roles_and_permissions_room_details">"ოთახის დეტალები"</string>
<string name="screen_room_roles_and_permissions_title">"როლები და ნებართვები"</string>
</resources>

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"디렉토리에 표시하려면 방 주소가 필요합니다."</string>
<string name="screen_edit_room_address_title">"방 주소"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"알림 설정 업데이트 중 오류가 발생했습니다."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"귀하의 홈서버는 암호화된 방에서 이 옵션을 지원하지 않으므로, 일부 방에서는 알림이 표시되지 않을 수 있습니다."</string>
<string name="screen_polls_history_title">"투표"</string>
<string name="screen_room_change_permissions_administrators">"관리자 전용"</string>
<string name="screen_room_change_permissions_ban_people">"사용자 차단"</string>
<string name="screen_room_change_permissions_delete_messages">"메시지 삭제"</string>
<string name="screen_room_change_permissions_invite_people">"사람들을 초대하고 가입 요청을 수락합니다"</string>
<string name="screen_room_change_permissions_messages_and_content">"메시지 및 콘텐츠"</string>
<string name="screen_room_change_permissions_moderators">"관리자 및 중재자"</string>
<string name="screen_room_change_permissions_remove_people">"사람들을 제거하고 가입 요청을 거부합니다"</string>
<string name="screen_room_change_permissions_room_avatar">"방 아바타 변경"</string>
<string name="screen_room_change_permissions_room_details">"방 편집"</string>
<string name="screen_room_change_permissions_room_name">"방 이름 변경"</string>
<string name="screen_room_change_permissions_room_topic">"방 화제 변경"</string>
<string name="screen_room_change_permissions_send_messages">"메시지 보내기"</string>
<string name="screen_room_change_role_administrators_title">"관리자 편집"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"이 작업은 실행 취소할 수 없습니다. 해당 사용자에게 당신과 동일한 권한 레벨을 부여하는 것입니다."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"관리자를 추가하시겠습니까?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"이 작업을 취소할 수 없습니다. 선택한 사용자에게 소유권을 이전합니다. 이 작업을 완료하면 변경 사항은 영구적으로 적용됩니다."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"소유권을 이전하시겠습니까?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"강등하다"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"이 변경 사항은 자신을 강등하는 것이므로 실행 취소할 수 없습니다. 해당 방에서 권한을 가진 마지막 사용자인 경우 권한을 다시 얻는 것은 불가능합니다."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"자신을 강등하시겠습니까?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (보류 중)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(보류 중)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"관리자는 자동으로 중재자 권한을 갖습니다."</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"소유자는 자동으로 관리자 권한을 갖습니다."</string>
<string name="screen_room_change_role_moderators_title">"편집 중재자"</string>
<string name="screen_room_change_role_owners_title">"소유자 선택"</string>
<string name="screen_room_change_role_section_administrators">"관리자"</string>
<string name="screen_room_change_role_section_moderators">"중재자"</string>
<string name="screen_room_change_role_section_users">"회원들"</string>
<string name="screen_room_change_role_unsaved_changes_description">"저장되지 않은 변경 사항이 있습니다."</string>
<string name="screen_room_change_role_unsaved_changes_title">"변경 사항을 저장하시겠습니까?"</string>
<string name="screen_room_details_add_topic_title">"화제 추가"</string>
<string name="screen_room_details_badge_encrypted">"암호화됨"</string>
<string name="screen_room_details_badge_not_encrypted">"암호화되지 않음"</string>
<string name="screen_room_details_badge_public">"공개 방"</string>
<string name="screen_room_details_edit_room_title">"방 편집"</string>
<string name="screen_room_details_edition_error">"알 수 없는 오류가 발생하여 정보를 변경할 수 없습니다."</string>
<string name="screen_room_details_edition_error_title">"방을 업데이트할 수 없습니다."</string>
<string name="screen_room_details_encryption_enabled_subtitle">"메시지는 잠금으로 보호됩니다. 귀하와 수신자만 잠금을 해제할 수 있는 고유한 키를 가지고 있습니다."</string>
<string name="screen_room_details_encryption_enabled_title">"메시지 암호화 활성화됨"</string>
<string name="screen_room_details_error_loading_notification_settings">"알림 설정 로딩 중 오류가 발생했습니다."</string>
<string name="screen_room_details_error_muting">"이 방의 음소거에 실패했습니다. 다시 시도하세요."</string>
<string name="screen_room_details_error_unmuting">"이 방의 음소거를 해제하지 못했습니다. 다시 시도하세요."</string>
<string name="screen_room_details_invite_people_title">"사람 초대하기"</string>
<string name="screen_room_details_leave_conversation_title">"대화에서 나가기"</string>
<string name="screen_room_details_leave_room_title">"방 떠나기"</string>
<string name="screen_room_details_media_gallery_title">"미디어 및 파일"</string>
<string name="screen_room_details_notification_mode_custom">"맞춤형"</string>
<string name="screen_room_details_notification_mode_default">"기본값"</string>
<string name="screen_room_details_notification_title">"알림"</string>
<string name="screen_room_details_pinned_events_row_title">"고정된 메세지"</string>
<string name="screen_room_details_profile_row_title">"프로필"</string>
<string name="screen_room_details_requests_to_join_title">"참여 요청"</string>
<string name="screen_room_details_roles_and_permissions">"역할 및 권한"</string>
<string name="screen_room_details_room_name_label">"방 이름"</string>
<string name="screen_room_details_security_and_privacy_title">"보안 및 개인정보 보호"</string>
<string name="screen_room_details_security_title">"보안"</string>
<string name="screen_room_details_share_room_title">"방 공유하기"</string>
<string name="screen_room_details_title">"방 정보"</string>
<string name="screen_room_details_topic_title">"주제"</string>
<string name="screen_room_details_updating_room">"방 업데이트 중…"</string>
<string name="screen_room_member_list_banned_empty">"이 방에는 차단된 사용자가 없습니다."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="other">"%1$d 사람"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"방에서 차단"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"회원만 삭제할 수 있습니다."</string>
<string name="screen_room_member_list_manage_member_unban_action">"금지 해제"</string>
<string name="screen_room_member_list_manage_member_unban_message">"초대받으면 이 방에 다시 들어올 수 있습니다."</string>
<string name="screen_room_member_list_manage_member_unban_title">"방에서 차단 해제"</string>
<string name="screen_room_member_list_mode_banned">"차단됨"</string>
<string name="screen_room_member_list_mode_members">"회원들"</string>
<string name="screen_room_member_list_role_administrator">"관리자 전용"</string>
<string name="screen_room_member_list_role_moderator">"관리자 및 중재자"</string>
<string name="screen_room_member_list_role_owner">"소유자"</string>
<string name="screen_room_member_list_room_members_header_title">"방 회원들"</string>
<string name="screen_room_member_list_unbanning_user">"차단 해제 %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"맞춤 설정 허용"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"이 기능을 활성화하면 기본 설정이 변경됩니다."</string>
<string name="screen_room_notification_settings_custom_settings_title">"이 채팅에서 알림 받기"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"%1$s 에서 변경할 수 있습니다."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"전역 설정"</string>
<string name="screen_room_notification_settings_default_setting_title">"기본 설정"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"맞춤 설정 제거"</string>
<string name="screen_room_notification_settings_error_loading_settings">"알림 설정 로딩 중 오류가 발생했습니다."</string>
<string name="screen_room_notification_settings_error_restoring_default">"기본 모드를 복원하는 데 실패했습니다. 다시 시도하세요."</string>
<string name="screen_room_notification_settings_error_setting_mode">"모드 설정이 실패했습니다. 다시 시도해 주세요."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"귀하의 홈 서버는 암호화된 방에서 이 옵션을 지원하지 않으므로, 이 방에서 알림을 받지 못합니다."</string>
<string name="screen_room_notification_settings_mode_all_messages">"모든 메시지"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"언급 및 키워드만"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"이 방에서, 알림을 주세요"</string>
<string name="screen_room_roles_and_permissions_admins">"관리자"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"관리자 및 소유자"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"내 역할 변경"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"회원으로 강등"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"중재자로 강등시키다"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"회원 조정"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"메시지 및 콘텐츠"</string>
<string name="screen_room_roles_and_permissions_moderators">"중재자"</string>
<string name="screen_room_roles_and_permissions_owners">"소유자"</string>
<string name="screen_room_roles_and_permissions_reset">"권한 재설정"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"권한을 재설정하면 현재 설정이 모두 삭제됩니다."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"권한을 재설정하시겠습니까?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"역할"</string>
<string name="screen_room_roles_and_permissions_room_details">"방 세부 정보"</string>
<string name="screen_room_roles_and_permissions_title">"역할 및 권한"</string>
<string name="screen_security_and_privacy_add_room_address_action">"방 주소 추가"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"누구나 방에 참여 요청을 할 수 있지만, 관리자나 운영자가 요청을 수락해야 합니다."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"참가 요청"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"예, 암호화 활성화"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"일단 활성화되면, 방의 암호화는 비활성화할 수 없습니다. 메시지 기록은 방에 초대된 후 또는 방에 참여한 이후부터 방 구성원만 볼 수 있습니다.
방 구성원 외에는 아무도 메시지를 읽을 수 없습니다. 이로 인해 봇과 브리지가 제대로 작동하지 않을 수 있습니다.
누구나 찾고 참여할 수 있는 방에는 암호화를 활성화하지 않는 것이 좋습니다."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"암호화 활성화?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"일단 활성화되면, 암호화는 비활성화할 수 없습니다."</string>
<string name="screen_security_and_privacy_encryption_section_header">"암호화"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"종단간 암호화 활성화"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"누구나 찾을 수 있고 참여할 수 있습니다."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"누구나"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"초대받은 사용자만 가입할 수 있습니다."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"초대 전용"</string>
<string name="screen_security_and_privacy_room_access_section_header">"방 액세스"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"스페이스 멤버들"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"스페이스는 현재 지원되지 않습니다"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"디렉토리에 표시하려면 방 주소가 필요합니다."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"%1$s 공개 방 디렉토리에서 이 방을 검색할 수 있도록 허용합니다"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"공개 룸 디렉토리에 표시됨"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"누구나"</string>
<string name="screen_security_and_privacy_room_history_section_header">"누가 기록을 읽을 수 있는가"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"초대받은 회원만 이용 가능합니다"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"이 옵션을 선택한 회원만 이용 가능합니다."</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"방 주소는 방을 찾고 액세스하는 방법입니다. 이를 통해 다른 사람들과 방을 쉽게 공유할 수 있습니다.
홈서버의 공개 방 디렉토리에 방을 공개할지 여부를 선택할 수 있습니다."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"방 게시"</string>
<string name="screen_security_and_privacy_title">"보안 및 개인정보 보호"</string>
</resources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_room_change_permissions_room_details">"Redaguoti kambarį"</string>
<string name="screen_room_details_add_topic_title">"Pridėti temą"</string>
<string name="screen_room_details_edit_room_title">"Redaguoti kambarį"</string>
<string name="screen_room_details_edition_error">"Įvyko nežinoma klaida ir informacijos pakeisti nepavyko."</string>
<string name="screen_room_details_edition_error_title">"Nepavyko atnaujinti kambario"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Žinutės yra užrakintos. Tik Jūs ir gavėjai turite unikalius raktus joms atrakinti."</string>
<string name="screen_room_details_encryption_enabled_title">"Įjungtas žinučių šifravimas"</string>
<string name="screen_room_details_invite_people_title">"Pakviesti žmonių"</string>
<string name="screen_room_details_leave_conversation_title">"Palikti pokalbį"</string>
<string name="screen_room_details_leave_room_title">"Palikti kambarį"</string>
<string name="screen_room_details_room_name_label">"Kambario pavadinimas"</string>
<string name="screen_room_details_security_title">"Saugumas"</string>
<string name="screen_room_details_share_room_title">"Bendrinti kambarį"</string>
<string name="screen_room_details_topic_title">"Tema"</string>
<string name="screen_room_details_updating_room">"Atnaujinamas kambarys…"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d asmuo"</item>
<item quantity="few">"%1$d asmenys"</item>
<item quantity="other">"%1$d asmenų"</item>
</plurals>
<string name="screen_room_member_list_room_members_header_title">"Kambario nariai"</string>
</resources>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Du trenger en adresse til rommet for å gjøre det synlig i katalogen."</string>
<string name="screen_edit_room_address_title">"Romadresse"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Det oppstod en feil under oppdatering av varslingsinnstillingen."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Hjemmeserveren din støtter ikke dette alternativet i krypterte rom, og det kan hende at du ikke blir varslet i enkelte rom."</string>
<string name="screen_polls_history_title">"Avstemninger"</string>
<string name="screen_room_change_permissions_administrators">"Kun for administratorer"</string>
<string name="screen_room_change_permissions_ban_people">"Forby folk"</string>
<string name="screen_room_change_permissions_delete_messages">"Fjern meldinger"</string>
<string name="screen_room_change_permissions_invite_people">"Inviter folk og godta forespørsler om å bli med"</string>
<string name="screen_room_change_permissions_messages_and_content">"Meldinger og innhold"</string>
<string name="screen_room_change_permissions_moderators">"Administratorer og moderatorer"</string>
<string name="screen_room_change_permissions_remove_people">"Fjern folk og avslå forespørsler om å bli med"</string>
<string name="screen_room_change_permissions_room_avatar">"Endre romavatar"</string>
<string name="screen_room_change_permissions_room_details">"Rediger rom"</string>
<string name="screen_room_change_permissions_room_name">"Endre romnavn"</string>
<string name="screen_room_change_permissions_room_topic">"Endre temaet til rommet"</string>
<string name="screen_room_change_permissions_send_messages">"Send meldinger"</string>
<string name="screen_room_change_role_administrators_title">"Rediger administratorer"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Du vil ikke kunne angre denne handlingen. Du forfremmer brukeren til å ha samme rettighetsnivå som deg."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Legg til administrator?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Du kan ikke angre denne handlingen. Du overfører eierskapet til de valgte brukerne. Når du forlater siden, vil dette være permanent."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Overføre eierskapet?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Degradere"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Du vil ikke kunne angre denne endringen ettersom du degraderer deg selv, og hvis du er den siste privilegerte brukeren i rommet, vil det være umulig å få tilbake privilegiene."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Degradere deg selv?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Venter)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Venter)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Administratorer har automatisk moderatorrettigheter"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Eiere har automatisk administratorrettigheter."</string>
<string name="screen_room_change_role_moderators_title">"Rediger moderatorer"</string>
<string name="screen_room_change_role_owners_title">"Velg eiere"</string>
<string name="screen_room_change_role_section_administrators">"Administratorer"</string>
<string name="screen_room_change_role_section_moderators">"Moderatorer"</string>
<string name="screen_room_change_role_section_users">"Medlemmer"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Du har endringer som ikke er lagret."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Lagre endringer?"</string>
<string name="screen_room_details_add_topic_title">"Legg til emne"</string>
<string name="screen_room_details_badge_encrypted">"Kryptert"</string>
<string name="screen_room_details_badge_not_encrypted">"Ikke kryptert"</string>
<string name="screen_room_details_badge_public">"Offentlig rom"</string>
<string name="screen_room_details_edit_room_title">"Rediger rom"</string>
<string name="screen_room_details_edition_error">"Det oppstod en ukjent feil, og informasjonen kunne ikke endres."</string>
<string name="screen_room_details_edition_error_title">"Kan ikke oppdatere rommet"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Meldingene er krypterte. Det er bare du og mottakerne som har de unike nøklene til å låse dem opp."</string>
<string name="screen_room_details_encryption_enabled_title">"Meldingskryptering aktivert"</string>
<string name="screen_room_details_error_loading_notification_settings">"Det oppstod en feil ved lasting av varslingsinnstillinger."</string>
<string name="screen_room_details_error_muting">"Mislyktes i å dempe dette rommet, prøv igjen."</string>
<string name="screen_room_details_error_unmuting">"Mislyktes i å oppheve dempingen av dette rommet, prøv igjen."</string>
<string name="screen_room_details_invite_people_dont_close">"Ikke lukk appen før den er ferdig."</string>
<string name="screen_room_details_invite_people_preparing">"Forbereder invitasjoner…"</string>
<string name="screen_room_details_invite_people_title">"Inviter folk"</string>
<string name="screen_room_details_leave_conversation_title">"Forlat samtalen"</string>
<string name="screen_room_details_leave_room_title">"Forlat rommet"</string>
<string name="screen_room_details_media_gallery_title">"Medier og filer"</string>
<string name="screen_room_details_notification_mode_custom">"Tilpasset"</string>
<string name="screen_room_details_notification_mode_default">"Standard"</string>
<string name="screen_room_details_notification_title">"Varslinger"</string>
<string name="screen_room_details_pinned_events_row_title">"Festede meldinger"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Forespørsler om å bli med"</string>
<string name="screen_room_details_roles_and_permissions">"Roller og tillatelser"</string>
<string name="screen_room_details_room_name_label">"Romnavn"</string>
<string name="screen_room_details_security_and_privacy_title">"Sikkerhet og personvern"</string>
<string name="screen_room_details_security_title">"Sikkerhet"</string>
<string name="screen_room_details_share_room_title">"Del rom"</string>
<string name="screen_room_details_title">"Informasjon om rommet"</string>
<string name="screen_room_details_topic_title">"Emne"</string>
<string name="screen_room_details_updating_room">"Oppdaterer rommet …"</string>
<string name="screen_room_member_list_banned_empty">"Det er ingen utestengte brukere i dette rommet."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d person"</item>
<item quantity="other">"%1$d personer"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Fjern og utesteng medlem"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Bare fjern medlem"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Opphev utestengelse"</string>
<string name="screen_room_member_list_manage_member_unban_message">"De vil kunne bli med i dette rommet igjen hvis de blir invitert."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Fjern utestengelsen fra rommet"</string>
<string name="screen_room_member_list_mode_banned">"Utestengt"</string>
<string name="screen_room_member_list_mode_members">"Medlemmer"</string>
<string name="screen_room_member_list_role_administrator">"Kun for administratorer"</string>
<string name="screen_room_member_list_role_moderator">"Administratorer og moderatorer"</string>
<string name="screen_room_member_list_role_owner">"Eier"</string>
<string name="screen_room_member_list_room_members_header_title">"Medlemmer av rommet"</string>
<string name="screen_room_member_list_unbanning_user">"Oppheve utestengelsen av %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Tillat egendefinert innstilling"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Hvis du slår på dette, overstyrer du standardinnstillingen"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Varsle meg i denne chatten om"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Du kan endre det i din %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"globale innstillinger"</string>
<string name="screen_room_notification_settings_default_setting_title">"Standard innstilling"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Fjern egendefinert innstilling"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Det oppstod en feil ved innlasting av varslingsinnstillinger."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Gjenoppretting av standardmodus mislyktes, prøv igjen."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Innstilling av modus mislyktes, prøv igjen."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Hjemmeserveren din støtter ikke dette alternativet i krypterte rom, og du vil ikke bli varslet i dette rommet."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Alle meldinger"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Bare omtaler og nøkkelord"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"I dette rommet, varsle meg om"</string>
<string name="screen_room_roles_and_permissions_admins">"Administratorer"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administratorer og eiere"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Endre rollen min"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Nedgradere til medlem"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Nedgradere til moderator"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderering av medlemmer"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Meldinger og innhold"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatorer"</string>
<string name="screen_room_roles_and_permissions_owners">"Eiere"</string>
<string name="screen_room_roles_and_permissions_reset">"Tilbakestill tillatelser"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Når du har tilbakestilt tillatelsene, mister du gjeldende innstillinger."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Vil du tilbakestille tillatelsene?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roller"</string>
<string name="screen_room_roles_and_permissions_room_details">"Romdetaljer"</string>
<string name="screen_room_roles_and_permissions_title">"Roller og tillatelser"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Legg til romadresse"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Alle kan be om å bli med i rommet, men en administrator eller moderator må godta forespørselen."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Be om å bli med"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ja, aktiver kryptering"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Når kryptering for et rom er aktivert, kan den ikke deaktiveres. Meldingshistorikken vil bare være synlig for rommedlemmer siden de ble invitert eller siden de ble med i rommet.
Ingen andre enn rommedlemmene vil kunne lese meldingene. Dette kan føre til at bots og broer ikke fungerer som de skal.
Vi anbefaler ikke å aktivere kryptering for rom som hvem som helst kan finne og bli med i."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Vil du aktivere kryptering?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Når kryptering er aktivert, kan det ikke deaktiveres."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Kryptering"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Aktiver ende-til-ende-kryptering"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Alle kan finne og bli med"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Alle"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Folk kan bare bli med hvis de er invitert"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Kun for inviterte"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Tilgang til rom"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Medlemmer av område"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Områder støttes ikke for øyeblikket"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Du trenger en adresse til rommet for å gjøre det synlig i katalogen."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Tillat at dette rommet blir funnet ved å søke %1$s offentlig romkatalog"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Synlig i offentlig romkatalog"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Alle"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Hvem kan lese historikk"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Medlemmer bare siden de ble invitert"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Kun medlemmer siden du valgte dette alternativet"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Romadresser er måter å finne og få tilgang til rom på. Dette sikrer også at du enkelt kan dele rommet ditt med andre.
Du kan velge å publisere rommet ditt i hjemeserverens offentlige romkatalog."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publisering av rom"</string>
<string name="screen_security_and_privacy_title">"Sikkerhet og personvern"</string>
</resources>

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Er is een fout opgetreden bij het bijwerken van de meldingsinstelling."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Je homeserver ondersteunt deze optie niet in versleutelde kamers; in sommige kamers krijg je mogelijk geen meldingen."</string>
<string name="screen_polls_history_title">"Peilingen"</string>
<string name="screen_room_change_permissions_administrators">"Alleen beheerders"</string>
<string name="screen_room_change_permissions_ban_people">"Personen verbannen"</string>
<string name="screen_room_change_permissions_delete_messages">"Berichten verwijderen"</string>
<string name="screen_room_change_permissions_invite_people">"Nodig personen uit en accepteer verzoeken om deel te nemen"</string>
<string name="screen_room_change_permissions_messages_and_content">"Berichten en inhoud"</string>
<string name="screen_room_change_permissions_moderators">"Beheerders en moderators"</string>
<string name="screen_room_change_permissions_remove_people">"Verwijder personen en weiger verzoeken om deel te nemen"</string>
<string name="screen_room_change_permissions_room_avatar">"Kamerafbeelding wijzigen"</string>
<string name="screen_room_change_permissions_room_details">"Kamer bewerken"</string>
<string name="screen_room_change_permissions_room_name">"Kamernaam wijzigen"</string>
<string name="screen_room_change_permissions_room_topic">"Kameronderwerp wijzigen"</string>
<string name="screen_room_change_permissions_send_messages">"Berichten verzenden"</string>
<string name="screen_room_change_role_administrators_title">"Beheerders bewerken"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Je kunt deze actie niet ongedaan maken. Je bevordert deze gebruiker tot hetzelfde machtsniveau als jij."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Beheerder toevoegen?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Degraderen"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Je kunt deze wijziging niet ongedaan maken omdat je jezelf degradeert. Als je de laatste gebruiker met bevoegdheden in de kamer bent, is het onmogelijk om deze bevoegdheden terug te krijgen."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Jezelf degraderen?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (In behandeling)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(In afwachting)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Beheerders hebben automatisch moderatorrechten"</string>
<string name="screen_room_change_role_moderators_title">"Moderators bewerken"</string>
<string name="screen_room_change_role_section_administrators">"Beheerders"</string>
<string name="screen_room_change_role_section_moderators">"Moderators"</string>
<string name="screen_room_change_role_section_users">"Leden"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Je hebt niet-opgeslagen wijzigingen"</string>
<string name="screen_room_change_role_unsaved_changes_title">"Wijzigingen opslaan?"</string>
<string name="screen_room_details_add_topic_title">"Onderwerp toevoegen"</string>
<string name="screen_room_details_badge_encrypted">"Versleuteld"</string>
<string name="screen_room_details_badge_not_encrypted">"Niet versleuteld"</string>
<string name="screen_room_details_badge_public">"Openbare kamer"</string>
<string name="screen_room_details_edit_room_title">"Kamer bewerken"</string>
<string name="screen_room_details_edition_error">"Er is een onbekende fout opgetreden en de informatie kon niet worden gewijzigd."</string>
<string name="screen_room_details_edition_error_title">"Kan kamer niet bijwerken"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Berichten zijn beveiligd met sloten. Alleen jij en de ontvangers hebben de unieke sleutels om ze te ontgrendelen."</string>
<string name="screen_room_details_encryption_enabled_title">"Berichtversleuteling ingeschakeld"</string>
<string name="screen_room_details_error_loading_notification_settings">"Er is een fout opgetreden bij het laden van de meldingsinstellingen."</string>
<string name="screen_room_details_error_muting">"Het dempen van deze kamer is mislukt. Probeer het opnieuw."</string>
<string name="screen_room_details_error_unmuting">"Het dempen opheffen voor deze kamer is mislukt. Probeer het opnieuw."</string>
<string name="screen_room_details_invite_people_title">"Mensen uitnodigen"</string>
<string name="screen_room_details_leave_conversation_title">"Gesprek verlaten"</string>
<string name="screen_room_details_leave_room_title">"Kamer verlaten"</string>
<string name="screen_room_details_notification_mode_custom">"Aangepast"</string>
<string name="screen_room_details_notification_mode_default">"Standaard"</string>
<string name="screen_room_details_notification_title">"Meldingen"</string>
<string name="screen_room_details_pinned_events_row_title">"Vastgezette berichten"</string>
<string name="screen_room_details_profile_row_title">"Profiel"</string>
<string name="screen_room_details_roles_and_permissions">"Rollen en rechten"</string>
<string name="screen_room_details_room_name_label">"Naam van de kamer"</string>
<string name="screen_room_details_security_title">"Beveiliging"</string>
<string name="screen_room_details_share_room_title">"Kamer delen"</string>
<string name="screen_room_details_title">"Kamer info"</string>
<string name="screen_room_details_topic_title">"Onderwerp"</string>
<string name="screen_room_details_updating_room">"Kamer bijwerken…"</string>
<string name="screen_room_member_list_banned_empty">"Er zijn geen verbannen gebruikers in deze kamer."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d persoon"</item>
<item quantity="other">"%1$d personen"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Lid verwijderen en verbannen"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Alleen lid verwijderen"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Ontbannen"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Ze kunnen opnieuw tot de kamer toetreden als ze worden uitgenodigd."</string>
<string name="screen_room_member_list_mode_banned">"Verbannen"</string>
<string name="screen_room_member_list_mode_members">"Leden"</string>
<string name="screen_room_member_list_role_administrator">"Alleen beheerders"</string>
<string name="screen_room_member_list_role_moderator">"Beheerders en moderators"</string>
<string name="screen_room_member_list_room_members_header_title">"Kamerleden"</string>
<string name="screen_room_member_list_unbanning_user">"%1$s ontbannen"</string>
<string name="screen_room_notification_settings_allow_custom">"Aanpassen toestaan"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Als je dit inschakelt, wordt je standaardinstelling overschreven"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Stuur me een melding in deze chat voor"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Je kunt het wijzigen in je %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"algemene instellingen"</string>
<string name="screen_room_notification_settings_default_setting_title">"Standaardinstelling"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Aanpassingen verwijderen"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Er is een fout opgetreden bij het laden van de meldingsinstellingen."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Het herstellen van de standaardmeldingen is mislukt. Probeer het opnieuw."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Het instellen van de meldingen is mislukt. Probeer het opnieuw."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Je homeserver ondersteunt deze optie niet in versleutelde kamers; in deze kamer krijg je geen meldingen."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Alle berichten"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Alleen vermeldingen en trefwoorden"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"In deze kamer, stuur me een melding voor"</string>
<string name="screen_room_roles_and_permissions_admins">"Beheerders"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Mijn rol wijzigen"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Degraderen tot lid"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Degraderen tot moderator"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderatie van leden"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Berichten en inhoud"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderators"</string>
<string name="screen_room_roles_and_permissions_reset">"Rechten opnieuw instellen"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Als je de rechten opnieuw instelt, raak je de huidige instellingen kwijt."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Rechten opnieuw instellen?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Rollen"</string>
<string name="screen_room_roles_and_permissions_room_details">"Kamergegevens"</string>
<string name="screen_room_roles_and_permissions_title">"Rollen en rechten"</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Vraag om toe te treden"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Iedereen"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Iedereen"</string>
</resources>

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju."</string>
<string name="screen_edit_room_address_title">"Adres pokoju"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Wystąpił błąd podczas aktualizacji ustawienia powiadomień."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z niektórych pokoi."</string>
<string name="screen_polls_history_title">"Ankiety"</string>
<string name="screen_room_change_permissions_administrators">"Tylko administratorzy"</string>
<string name="screen_room_change_permissions_ban_people">"Banowanie osób"</string>
<string name="screen_room_change_permissions_delete_messages">"Usuń wiadomości"</string>
<string name="screen_room_change_permissions_invite_people">"Zapraszanie osób i akceptowanie próśb o dołączenie"</string>
<string name="screen_room_change_permissions_messages_and_content">"Wiadomości i zawartość"</string>
<string name="screen_room_change_permissions_moderators">"Administratorzy i moderatorzy"</string>
<string name="screen_room_change_permissions_remove_people">"Usuwanie osób i odrzucanie próśb o dołączenie"</string>
<string name="screen_room_change_permissions_room_avatar">"Zmień awatar pokoju"</string>
<string name="screen_room_change_permissions_room_details">"Edytuj pokój"</string>
<string name="screen_room_change_permissions_room_name">"Zmień nazwę pokoju"</string>
<string name="screen_room_change_permissions_room_topic">"Zmień temat pokoju"</string>
<string name="screen_room_change_permissions_send_messages">"Wysyłanie wiadomości"</string>
<string name="screen_room_change_role_administrators_title">"Edytuj administratorów"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Tej akcji nie będzie można cofnąć. Promujesz użytkownika, który będzie posiadał takie same uprawnienia jak Ty."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Dodać administratora?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Tej akcji nie będzie można cofnąć. Przenosisz prawa własności na wybranych użytkowników. Po opuszczeniu tej strony zmiana będzie nieodwracalna."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Przenieść własność?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Zdegraduj"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Nie będzie można cofnąć tej zmiany, jeśli się zdegradujesz. Jeśli jesteś ostatnim uprzywilejowanym użytkownikiem w pokoju, nie będziesz w stanie odzyskać uprawnień."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Zdegradować siebie?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Oczekujące)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Oczekujący)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Administratorzy automatycznie mają uprawnienia moderatora"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Właściciele automatycznie mają uprawnienia administratora."</string>
<string name="screen_room_change_role_moderators_title">"Edytuj moderatorów"</string>
<string name="screen_room_change_role_owners_title">"Wybierz właścicieli"</string>
<string name="screen_room_change_role_section_administrators">"Administratorzy"</string>
<string name="screen_room_change_role_section_moderators">"Moderatorzy"</string>
<string name="screen_room_change_role_section_users">"Członków"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Masz niezapisane zmiany."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Zapisać zmiany?"</string>
<string name="screen_room_details_add_topic_title">"Dodaj temat"</string>
<string name="screen_room_details_badge_encrypted">"Szyfrowany"</string>
<string name="screen_room_details_badge_not_encrypted">"Nieszyfrowany"</string>
<string name="screen_room_details_badge_public">"Pokój publiczny"</string>
<string name="screen_room_details_edit_room_title">"Edytuj pokój"</string>
<string name="screen_room_details_edition_error">"Wystąpił nieznany błąd i nie można było zmienić informacji."</string>
<string name="screen_room_details_edition_error_title">"Nie można zaktualizować pokoju"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Wiadomości są zabezpieczone kłódkami. Tylko Ty i odbiorcy macie unikalne klucze do ich odblokowania."</string>
<string name="screen_room_details_encryption_enabled_title">"Szyfrowanie wiadomości włączone"</string>
<string name="screen_room_details_error_loading_notification_settings">"Wystąpił błąd podczas ładowania ustawień powiadomień."</string>
<string name="screen_room_details_error_muting">"Wyciszenie tego pokoju nie powiodło się, spróbuj ponownie."</string>
<string name="screen_room_details_error_unmuting">"Nie udało się wyłączyć wyciszenia tego pokoju. Spróbuj ponownie."</string>
<string name="screen_room_details_invite_people_dont_close">"Nie zamykaj aplikacji przed zakończeniem."</string>
<string name="screen_room_details_invite_people_preparing">"Przygotowywanie zaproszeń…"</string>
<string name="screen_room_details_invite_people_title">"Zaproś znajomych"</string>
<string name="screen_room_details_leave_conversation_title">"Opuść rozmowę"</string>
<string name="screen_room_details_leave_room_title">"Opuść pokój"</string>
<string name="screen_room_details_media_gallery_title">"Media i pliki"</string>
<string name="screen_room_details_notification_mode_custom">"Niestandardowe"</string>
<string name="screen_room_details_notification_mode_default">"Domyślny"</string>
<string name="screen_room_details_notification_title">"Powiadomienia"</string>
<string name="screen_room_details_pinned_events_row_title">"Przypięte wiadomości"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Prośby o dołączenie"</string>
<string name="screen_room_details_roles_and_permissions">"Role i uprawnienia"</string>
<string name="screen_room_details_room_name_label">"Nazwa pokoju"</string>
<string name="screen_room_details_security_and_privacy_title">"Bezpieczeństwo i prywatność"</string>
<string name="screen_room_details_security_title">"Bezpieczeństwo"</string>
<string name="screen_room_details_share_room_title">"Udostępnij pokój"</string>
<string name="screen_room_details_title">"Informacje pokoju"</string>
<string name="screen_room_details_topic_title">"Temat"</string>
<string name="screen_room_details_updating_room">"Aktualizuję pokój…"</string>
<string name="screen_room_member_list_banned_empty">"W tym pokoju nie ma zbanowanych użytkowników."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d osoba"</item>
<item quantity="few">"%1$d osoby"</item>
<item quantity="many">"%1$d osób"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Usuń i zbanuj członka"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Tylko usuń członka"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Odbanuj"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Odbanuj z pokoju"</string>
<string name="screen_room_member_list_mode_banned">"Zbanowanych"</string>
<string name="screen_room_member_list_mode_members">"Członków"</string>
<string name="screen_room_member_list_role_administrator">"Tylko administratorzy"</string>
<string name="screen_room_member_list_role_moderator">"Administratorzy i moderatorzy"</string>
<string name="screen_room_member_list_role_owner">"Właściciel"</string>
<string name="screen_room_member_list_room_members_header_title">"Członkowie pokoju"</string>
<string name="screen_room_member_list_unbanning_user">"Odbanowanie %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Zezwalaj na ustawienia niestandardowe"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Włączenie tej opcji nadpisze ustawienie domyślne"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Powiadamiaj mnie o tym czacie przez"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Możesz to zmienić w swoim %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"ustawienia globalne"</string>
<string name="screen_room_notification_settings_default_setting_title">"Ustawienie domyślne"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Usuń ustawienia własne"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Wystąpił błąd podczas ładowania ustawień powiadomień."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Nie udało się przywrócić trybu domyślnego, spróbuj ponownie."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Nie udało się ustawić trybu, spróbuj ponownie."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z tego pokoju."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Wszystkie wiadomości"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Tylko wzmianki i słowa kluczowe"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"W tym pokoju, powiadamiaj mnie przez"</string>
<string name="screen_room_roles_and_permissions_admins">"Administratorzy"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administratorzy i właściciele"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Zmień moją rolę"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Zdegraduj do członka"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Zdegraduj do moderatora"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderacja członków"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Wiadomości i zawartość"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatorzy"</string>
<string name="screen_room_roles_and_permissions_owners">"Właściciele"</string>
<string name="screen_room_roles_and_permissions_reset">"Resetuj uprawnienia"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Po zresetowaniu uprawnień utracisz bieżące ustawienia."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Zresetować uprawnienia?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Role"</string>
<string name="screen_room_roles_and_permissions_room_details">"Szczegóły pokoju"</string>
<string name="screen_room_roles_and_permissions_title">"Role i uprawnienia"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Dodaj adres pokoju"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić żądanie."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Poproś o dołączenie"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Tak, włącz szyfrowanie"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Po włączeniu szyfrowanie pokoju nie może zostać wyłączone, a historia wiadomości będzie widoczna tylko dla członków od momentu, w którym dołączyli lub zostali zaproszeni.
Nikt poza członkami pokoju nie będzie mógł czytać wiadomości. Może to wpłynąć na prawidłowe działanie botów lub mostków.
Odradzamy włączanie szyfrowania dla pokoi, które każdy może znaleźć i do których każdy może dołączyć."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Włączyć szyfrowanie?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Po włączeniu szyfrowania nie można wyłączyć."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Szyfrowanie"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Włącz szyfrowanie end-to-end"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Każdy może znaleźć i dołączyć"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Wszyscy"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Tylko osoby z zaproszeniem mogą dołączyć"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Tylko zaproszenie"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Dostęp do pokoju"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Członkowie przestrzeni"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Przestrzenie nie są obecnie wspierane"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Adres pokoju"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Zezwól na znalezienie tego pokoju wyszukując %1$s w katalogu pokoi publicznych"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Widoczny w katalogu pokoi publicznych"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Wszyscy"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Kto może czytać historię"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Od momentu kiedy członkowie zostali zaproszeni"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Członkowie od momentu włączenia tej opcji"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Adresy pokoju umożliwiają łatwe znalezienie i dołączenie do pokojów.
Również możesz się zdecydować na upublicznienie Twojego serwera w katalogu pokoi publicznych."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publikowanie pokoju"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Widoczność pokoju"</string>
<string name="screen_security_and_privacy_title">"Bezpieczeństwo i prywatność"</string>
</resources>

View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Você precisará de um endereço para torná-la visível no diretório."</string>
<string name="screen_edit_room_address_title">"Editar endereço"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Ocorreu um erro ao atualizar a configuração de notificação."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Seu servidor-casa não suporta esta opção em salas criptografadas. Você pode não ser notificado em algumas salas."</string>
<string name="screen_polls_history_title">"Enquetes"</string>
<string name="screen_room_change_permissions_administrators">"Administradores"</string>
<string name="screen_room_change_permissions_ban_people">"Banir pessoas"</string>
<string name="screen_room_change_permissions_delete_messages">"Remover mensagens"</string>
<string name="screen_room_change_permissions_everyone">"Membro"</string>
<string name="screen_room_change_permissions_invite_people">"Convidar pessoas"</string>
<string name="screen_room_change_permissions_member_moderation">"Gerenciar membros"</string>
<string name="screen_room_change_permissions_messages_and_content">"Mensagens e conteúdo"</string>
<string name="screen_room_change_permissions_moderators">"Moderador"</string>
<string name="screen_room_change_permissions_remove_people">"Remover pessoas"</string>
<string name="screen_room_change_permissions_room_avatar">"Alterar avatar da sala"</string>
<string name="screen_room_change_permissions_room_details">"Editar detalhes"</string>
<string name="screen_room_change_permissions_room_name">"Alterar nome da sala"</string>
<string name="screen_room_change_permissions_room_topic">"Alterar tópico da sala"</string>
<string name="screen_room_change_permissions_send_messages">"Enviar mensagens"</string>
<string name="screen_room_change_role_administrators_title">"Editar administradores"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Você não poderá desfazer essa ação. Você está promovendo o usuário a ter o mesmo nível de poder que você."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Adicionar administrador?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Você não poderá desfazer isto. Você está transferindo a posse desta sala para os usuários selecionados. Ao sair, isto será permanente."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Transferir posse?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Rebaixar"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Você não poderá desfazer essa alteração, pois estará removendo seus próprios privilégios. Se você for o último usuário privilegiado na sala, será impossível recuperar os privilégios."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Rebaixar seu próprio privilégio?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (pendente)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(pendente)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Os administradores têm privilégios de moderador automaticamente"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Proprietários automaticamente têm privilégios de administradores."</string>
<string name="screen_room_change_role_moderators_title">"Editar moderadores"</string>
<string name="screen_room_change_role_owners_title">"Escolher Proprietários"</string>
<string name="screen_room_change_role_section_administrators">"Administradores"</string>
<string name="screen_room_change_role_section_moderators">"Moderadores"</string>
<string name="screen_room_change_role_section_users">"Membros"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Você tem alterações não salvas."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Salvar alterações?"</string>
<string name="screen_room_details_add_topic_title">"Adicionar tópico"</string>
<string name="screen_room_details_badge_encrypted">"Criptografado"</string>
<string name="screen_room_details_badge_not_encrypted">"Não criptografado"</string>
<string name="screen_room_details_badge_public">"Sala pública"</string>
<string name="screen_room_details_edit_room_title">"Editar detalhes"</string>
<string name="screen_room_details_edition_error">"Ocorreu um erro desconhecido e as informações não puderam ser alteradas."</string>
<string name="screen_room_details_edition_error_title">"Não foi possível atualizar a sala"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"As mensagens são protegidas com cadeados. Somente você e os destinatários têm as chaves exclusivas para desbloqueá-los."</string>
<string name="screen_room_details_encryption_enabled_title">"Criptografia de mensagens ativada"</string>
<string name="screen_room_details_error_loading_notification_settings">"Ocorreu um erro ao carregar as configurações de notificação."</string>
<string name="screen_room_details_error_muting">"Falha ao silenciar esta sala, tente novamente."</string>
<string name="screen_room_details_error_unmuting">"Falha ao desilenciar esta sala. Tente novamente."</string>
<string name="screen_room_details_invite_people_dont_close">"Não feche o aplicativo até terminar."</string>
<string name="screen_room_details_invite_people_preparing">"Preparando convites…"</string>
<string name="screen_room_details_invite_people_title">"Convidar pessoas"</string>
<string name="screen_room_details_leave_conversation_title">"Sair da conversa"</string>
<string name="screen_room_details_leave_room_title">"Sair da sala"</string>
<string name="screen_room_details_media_gallery_title">"Mídia e arquivos"</string>
<string name="screen_room_details_notification_mode_custom">"Personalizado"</string>
<string name="screen_room_details_notification_mode_default">"Padrão"</string>
<string name="screen_room_details_notification_title">"Notificações"</string>
<string name="screen_room_details_pinned_events_row_title">"Mensagens fixadas"</string>
<string name="screen_room_details_profile_row_title">"Perfil"</string>
<string name="screen_room_details_requests_to_join_title">"Pedidos de entrada"</string>
<string name="screen_room_details_roles_and_permissions">"Cargos e permissões"</string>
<string name="screen_room_details_room_name_label">"Nome da sala"</string>
<string name="screen_room_details_security_and_privacy_title">"Segurança e privacidade"</string>
<string name="screen_room_details_security_title">"Segurança"</string>
<string name="screen_room_details_share_room_title">"Compartilhar sala"</string>
<string name="screen_room_details_title">"Informação da sala"</string>
<string name="screen_room_details_topic_title">"Tópico"</string>
<string name="screen_room_details_updating_room">"Atualizando a sala…"</string>
<string name="screen_room_member_list_banned_empty">"Não há usuários banidos."</string>
<plurals name="screen_room_member_list_banned_header_title">
<item quantity="one">"%1$d banido"</item>
<item quantity="other">"%1$d banidos"</item>
</plurals>
<string name="screen_room_member_list_empty_search_subtitle">"Confira a ortografia ou tente uma nova busca"</string>
<string name="screen_room_member_list_empty_search_title">"Nenhum resultado para “%1$s”"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d pessoa"</item>
<item quantity="other">"%1$d pessoas"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Banir da sala"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Somente remover o membro"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Desbanir"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Esta pessoa poderá entrar nesta sala novamente se for convidada."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Desbanir da sala"</string>
<string name="screen_room_member_list_mode_banned">"Banidos"</string>
<string name="screen_room_member_list_mode_members">"Membros"</string>
<plurals name="screen_room_member_list_pending_header_title">
<item quantity="one">"%1$d convidado"</item>
<item quantity="other">"%1$d convidados"</item>
</plurals>
<string name="screen_room_member_list_pending_status">"Pendente"</string>
<string name="screen_room_member_list_role_administrator">"Administradores"</string>
<string name="screen_room_member_list_role_moderator">"Moderador"</string>
<string name="screen_room_member_list_role_owner">"Proprietário"</string>
<string name="screen_room_member_list_room_members_header_title">"Membros da sala"</string>
<string name="screen_room_member_list_unbanning_user">"Desbanindo %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Permitir configuração personalizada"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Ativar isso substituirá sua configuração padrão"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Me notifique nesta conversa de"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Você pode alterá-la nas suas %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"configurações globais"</string>
<string name="screen_room_notification_settings_default_setting_title">"Configuração padrão"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Remover configuração personalizada"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Ocorreu um erro ao carregar as configurações de notificação."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Falha ao restaurar o modo padrão, tente novamente."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Falha ao definir o modo, tente novamente."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Seu servidor-casa não suporta esta opção em salas criptografadas, você não será notificado nesta sala."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Todas as mensagens"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Somente menções e palavras-chave"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Nesta sala, notifique-me de"</string>
<string name="screen_room_roles_and_permissions_admins">"Administradores"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administradores e proprietários"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Alterar meu cargo"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Rebaixar para membro"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Rebaixar para moderador"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderação de membros"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Mensagens e conteúdo"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderadores"</string>
<string name="screen_room_roles_and_permissions_owners">"Proprietários"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Permissões"</string>
<string name="screen_room_roles_and_permissions_reset">"Redefinir permissões"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Depois de redefinir as permissões, você perderá as configurações atuais."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Redefinir permissões?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Cargos"</string>
<string name="screen_room_roles_and_permissions_room_details">"Detalhes da sala"</string>
<string name="screen_room_roles_and_permissions_title">"Cargos e permissões"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Adicionar endereço"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Qualquer um pode pedir acesso, mas um administrador terá que aceitar o pedido."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Pedir para entrar"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Sim, ativar a criptografia"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Uma vez ativada, a criptografia de uma sala não pode ser desativada. O histórico de mensagens só será visível para os membros da sala desde que foram convidados ou desde que entraram na sala.
Ninguém além dos membros da sala poderá ler as mensagens. Isso pode impedir que os bots e as pontes funcionem corretamente.
Não recomendamos que você ative a criptografia para salas que qualquer pessoa possa encontrar e participar."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Ativar a criptografia?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Uma vez ativada, a criptografia não poderá ser desativada."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Criptografia"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Ativar a criptografia de ponta a ponta"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Qualquer um pode entrar"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Qualquer pessoa"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Apenas pessoas convidadas podem entrar."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Privado"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Acesso"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Membros do espaço"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"No momento, não há suporte aos espaços"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Você precisará de um endereço para torná-la visível no diretório."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Endereço publicado"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Permitir que esta sala seja encontrada pesquisando diretório de salas públicas de %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Permite que seja encontrada ao buscar no diretório público."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Visível no diretório público"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Qualquer pessoa"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Quem pode ler o histórico"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Somente membros, desde que foram convidados"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Somente para membros após selecionar esta opção"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Os endereços das salas são formas de encontrar e acessar as salas. Isso também garante que você possa compartilhar facilmente sua sala com outras pessoas.
Você pode optar por publicar sua sala no diretório público de salas do seu servidor-casa."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publicação da sala"</string>
<string name="screen_security_and_privacy_room_visibility_section_footer">"Os endereços das salas são formas de encontrar e acessar as salas. Isso também garante que você possa compartilhá-las facilmente com outras pessoas."</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Visibilidade"</string>
<string name="screen_security_and_privacy_title">"Segurança e privacidade"</string>
</resources>

View File

@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"É necessário um endereço para tornar a sala visível no diretório."</string>
<string name="screen_edit_room_address_title">"Endereço da sala"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Erro ao atualizar a configuração de notificação."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"O teu servidor não suporta esta opção em salas cifradas, pelo que poderás não ser notificado em algumas salas."</string>
<string name="screen_polls_history_title">"Sondagens"</string>
<string name="screen_room_change_permissions_administrators">"Apenas administradores"</string>
<string name="screen_room_change_permissions_ban_people">"Banir pessoas"</string>
<string name="screen_room_change_permissions_delete_messages">"Remover mensagens"</string>
<string name="screen_room_change_permissions_invite_people">"Convidar pessoas e aceitar pedidos de entrada"</string>
<string name="screen_room_change_permissions_messages_and_content">"Mensagens e conteúdo"</string>
<string name="screen_room_change_permissions_moderators">"Administradores e moderadores"</string>
<string name="screen_room_change_permissions_remove_people">"Remover pessoas e rejeitar pedidos de entrada"</string>
<string name="screen_room_change_permissions_room_avatar">"Alterar o ícone da sala"</string>
<string name="screen_room_change_permissions_room_details">"Editar sala"</string>
<string name="screen_room_change_permissions_room_name">"Altera o nome da sala"</string>
<string name="screen_room_change_permissions_room_topic">"Alterar a descrição da sala"</string>
<string name="screen_room_change_permissions_send_messages">"Enviar mensagens"</string>
<string name="screen_room_change_role_administrators_title">"Editar Administradores"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Não poderás desfazer esta ação. Estás a promover o utilizador para ter o mesmo nível de poder que tu."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Adicionar administrador?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Não será possível reverter esta ação. Estás a transferir a posse para os utilizadores selecionados. Será permanente depois de saíres."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Transferir posse?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Despromover"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Não poderás desfazer esta alteração, uma vez que te estás a despromover. Se fores o último utilizador privilegiado na sala, será impossível recuperar os privilégios."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Despromover-te?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (pendente)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(pendente)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Os administradores têm automaticamente privilégios de moderador"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Os donos têm permissões de administrador automaticamente"</string>
<string name="screen_room_change_role_moderators_title">"Editar Moderadores"</string>
<string name="screen_room_change_role_owners_title">"Escolher donos"</string>
<string name="screen_room_change_role_section_administrators">"Administradores"</string>
<string name="screen_room_change_role_section_moderators">"Moderadores"</string>
<string name="screen_room_change_role_section_users">"Participantes"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Tens alterações por guardar."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Guardar alterações?"</string>
<string name="screen_room_details_add_topic_title">"Adicionar descrição"</string>
<string name="screen_room_details_badge_encrypted">"Cifrada"</string>
<string name="screen_room_details_badge_not_encrypted">"Não cifrada"</string>
<string name="screen_room_details_badge_public">"Sala pública"</string>
<string name="screen_room_details_edit_room_title">"Editar sala"</string>
<string name="screen_room_details_edition_error">"Ocorreu um erro desconhecido e não foi possível alterar a informação."</string>
<string name="screen_room_details_edition_error_title">"Não foi possível atualizar a sala"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"As mensagens são protegidas por cadeados. Apenas tu e os destinatários têm as chaves únicas para os desbloquear."</string>
<string name="screen_room_details_encryption_enabled_title">"Cifragem de mensagens ativada"</string>
<string name="screen_room_details_error_loading_notification_settings">"Erro ao carregar as configurações de notificação."</string>
<string name="screen_room_details_error_muting">"Não foi possível silenciar esta sala, por favor tenta novamente."</string>
<string name="screen_room_details_error_unmuting">"Não foi possível dessilenciar esta sala, por favor tenta novamente."</string>
<string name="screen_room_details_invite_people_dont_close">"Não feches a aplicação até concluir."</string>
<string name="screen_room_details_invite_people_preparing">"A preparar convites…"</string>
<string name="screen_room_details_invite_people_title">"Convidar pessoas"</string>
<string name="screen_room_details_leave_conversation_title">"Sair da conversa"</string>
<string name="screen_room_details_leave_room_title">"Sair da sala"</string>
<string name="screen_room_details_media_gallery_title">"Multimédia e ficheiros"</string>
<string name="screen_room_details_notification_mode_custom">"Personalizado"</string>
<string name="screen_room_details_notification_mode_default">"Predefinição"</string>
<string name="screen_room_details_notification_title">"Notificações"</string>
<string name="screen_room_details_pinned_events_row_title">"Mensagens afixadas"</string>
<string name="screen_room_details_profile_row_title">"Perfil"</string>
<string name="screen_room_details_requests_to_join_title">"Pedidos de entrada"</string>
<string name="screen_room_details_roles_and_permissions">"Cargos e permissões"</string>
<string name="screen_room_details_room_name_label">"Nome da sala"</string>
<string name="screen_room_details_security_and_privacy_title">"Segurança e privacidade"</string>
<string name="screen_room_details_security_title">"Segurança"</string>
<string name="screen_room_details_share_room_title">"Partilhar sala"</string>
<string name="screen_room_details_title">"Informação da sala"</string>
<string name="screen_room_details_topic_title">"Descrição"</string>
<string name="screen_room_details_updating_room">"A atualizar sala…"</string>
<string name="screen_room_member_list_banned_empty">"Não há nenhum utilizador banido desta sala."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d pessoa"</item>
<item quantity="other">"%1$d pessoas"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Remover e banir participante"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Remover apenas"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Anular banimento"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Poderão juntar-se novamente a esta sala se forem convidados."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Desbanir da sala"</string>
<string name="screen_room_member_list_mode_banned">"Banidos"</string>
<string name="screen_room_member_list_mode_members">"Participantes"</string>
<string name="screen_room_member_list_role_administrator">"Apenas administradores"</string>
<string name="screen_room_member_list_role_moderator">"Administradores e moderadores"</string>
<string name="screen_room_member_list_role_owner">"Dono / Dona"</string>
<string name="screen_room_member_list_room_members_header_title">"Participantes"</string>
<string name="screen_room_member_list_unbanning_user">"A anular banimento de %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Permitir configuração personalizada"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Ativar esta opção substitui a tua configuração predefinida"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Nesta conversa, notifica-me se"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Podes alterá-lo nas tuas %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"configurações globais"</string>
<string name="screen_room_notification_settings_default_setting_title">"Predefinição"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Remover configuração personalizada"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Erro ao carregar as configurações de notificação."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Falha ao restaurar o modo predefinido, tenta novamente."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Falha ao definir o modo, tenta novamente."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"O teu servidor não suporta esta opção em salas cifradas, pelo que não serás notificado nesta sala."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Qualquer mensagem"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Menções ou palavras-chave"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Nesta sala, notifica-me se"</string>
<string name="screen_room_roles_and_permissions_admins">"Administradores"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administradores e donos"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Alterar o meu cargo"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Despromover para participante"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Despromover para moderador"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderação de participantes"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Mensagens e conteúdo"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderadores"</string>
<string name="screen_room_roles_and_permissions_owners">"Donos"</string>
<string name="screen_room_roles_and_permissions_reset">"Repor permissões"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Ao repores as permissões, perderás as configurações atuais."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Repor as permissões?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Cargos"</string>
<string name="screen_room_roles_and_permissions_room_details">"Detalhes da sala"</string>
<string name="screen_room_roles_and_permissions_title">"Cargos e permissões"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Adicionar endereço de sala"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou moderador tem que aceitar o pedido."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Pedir para participar"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Sim, ativar cifragem"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Uma vez ativada, a cifragem não pode ser desativada. O histórico de mensagens só será visível a membros a partir do momento em que foram convidados ou que entraram na sala.
Ninguém além dos membros poderão ler quaisquer mensagens. Isto pode impedir que robôs (\"bots\") e pontes (\"bridges\") funcionem devidamente.
Não recomendamos ativar a cifragem em salas que qualquer pessoa possa encontrar e entrar."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Ativar cifragem?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Uma vez ativada, a cifragem não pode ser desativada."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Cifragem"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Ativar cifragem ponta-a-ponta"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Qualquer pessoa pode encontrar a sala e entrar"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Qualquer pessoa"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Só é possível entrar tendo um convite"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Apenas por convite"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Acesso à sala"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Membros do espaço"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Os espaços ainda não estão implementados"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"É necessário um endereço para tornar a sala visível no diretório."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Endereço da sala"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Permite que esta sala seja encontrada através do diretório público do %1$s."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Visível no diretório público de salas"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Qualquer pessoa"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Quem pode ler o histórico de mensagens"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Apenas membros, desde o momento em que forem convidados"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Apenas membros, desde o memento em que esta opção for selecionada"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Estes endereços permitem encontrar e aceder a sala, bem como a sua fácil partilha com outros.
Podes escolher publicar a sala no diretório público do teu servidor."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publicar sala"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Visibilidade da sala"</string>
<string name="screen_security_and_privacy_title">"Segurança e privacidade"</string>
</resources>

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Veți avea nevoie de o adresă de cameră pentru a o face vizibilă în director."</string>
<string name="screen_edit_room_address_title">"Adresa camerei"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"A apărut o eroare în timpul actualizării setărilor pentru notificari."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Serverul dumneavoastră nu acceptă această opțiune în camerele criptate, este posibil să nu primiți notificări în unele camere."</string>
<string name="screen_polls_history_title">"Sondaje"</string>
<string name="screen_room_change_permissions_administrators">"Doar administratori"</string>
<string name="screen_room_change_permissions_ban_people">"Interziceți persoane"</string>
<string name="screen_room_change_permissions_delete_messages">"Ștergeți mesajele"</string>
<string name="screen_room_change_permissions_invite_people">"Invitați persoane și acceptați cereri de alaturare"</string>
<string name="screen_room_change_permissions_messages_and_content">"Mesaje și conținut"</string>
<string name="screen_room_change_permissions_moderators">"Administratori și moderatori"</string>
<string name="screen_room_change_permissions_remove_people">"Îndepărtați persoane și refuzați cereri de alăturare"</string>
<string name="screen_room_change_permissions_room_avatar">"Schimbați avatarul camerei"</string>
<string name="screen_room_change_permissions_room_details">"Editați camera"</string>
<string name="screen_room_change_permissions_room_name">"Schimbă numele camerei"</string>
<string name="screen_room_change_permissions_room_topic">"Schimbați subiectul camerei"</string>
<string name="screen_room_change_permissions_send_messages">"Trimiteți mesaje"</string>
<string name="screen_room_change_role_administrators_title">"Editați administratorii"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Promovați utilizatorul să aibă același nivel de putere ca dumneavoastră. Nu veți putea anula această acțiune."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Adăugați administrator?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Nu veți putea anula această acțiune. Transferați dreptul de proprietate către utilizatorii selectați. Odată ce părăsiți această pagină, acțiunea va fi definitivă."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Transferați proprietatea?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Retrogradare"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Nu veți putea anula această modificare, deoarece vă retrogradați. Dacă sunteți ultimul utilizator privilegiat din cameră, va fi imposibil să recâștigați privilegiile."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Vreți să vă retrogradați?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (În așteptare)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(În așteptare)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Administratorii au automat privilegii de moderator"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Proprietarii au automat privilegii de administrator."</string>
<string name="screen_room_change_role_moderators_title">"Editați moderatorii"</string>
<string name="screen_room_change_role_owners_title">"Alegeți proprietari"</string>
<string name="screen_room_change_role_section_administrators">"Administratori"</string>
<string name="screen_room_change_role_section_moderators">"Moderatori"</string>
<string name="screen_room_change_role_section_users">"Membri"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Aveți modificări nesalvate."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Salvați modificările?"</string>
<string name="screen_room_details_add_topic_title">"Adăugare subiect"</string>
<string name="screen_room_details_badge_encrypted">"Criptat"</string>
<string name="screen_room_details_badge_not_encrypted">"Necriptat"</string>
<string name="screen_room_details_badge_public">"Cameră publică"</string>
<string name="screen_room_details_edit_room_title">"Editați camera"</string>
<string name="screen_room_details_edition_error">"A apărut o eroare la actualizarea detaliilor camerei"</string>
<string name="screen_room_details_edition_error_title">"Nu s-a putut actualiza camera"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Mesajele sunt securizate cu încuietori. Doar dumneavoastră și destinatarii aveți cheile unice pentru a le debloca."</string>
<string name="screen_room_details_encryption_enabled_title">"Criptarea mesajelor este activată"</string>
<string name="screen_room_details_error_loading_notification_settings">"A apărut o eroare la încărcarea setărilor pentru notificari."</string>
<string name="screen_room_details_error_muting">"Dezactivarea notificarilor pentru această cameră a eșuat, încercați din nou."</string>
<string name="screen_room_details_error_unmuting">"Activarea notificarilor pentru această cameră a eșuat, încercați din nou."</string>
<string name="screen_room_details_invite_people_dont_close">"Nu închideți aplicația până nu se termină."</string>
<string name="screen_room_details_invite_people_preparing">"Se pregătesc invitațiile…"</string>
<string name="screen_room_details_invite_people_title">"Invitați prieteni"</string>
<string name="screen_room_details_leave_conversation_title">"Părăsiți conversația"</string>
<string name="screen_room_details_leave_room_title">"Părăsiți camera"</string>
<string name="screen_room_details_media_gallery_title">"Media și fișiere"</string>
<string name="screen_room_details_notification_mode_custom">"Personalizat"</string>
<string name="screen_room_details_notification_mode_default">"Implicit"</string>
<string name="screen_room_details_notification_title">"Notificări"</string>
<string name="screen_room_details_pinned_events_row_title">"Mesaje fixate"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Cereri de alăturare"</string>
<string name="screen_room_details_roles_and_permissions">"Roluri și permisiuni"</string>
<string name="screen_room_details_room_name_label">"Numele camerei"</string>
<string name="screen_room_details_security_and_privacy_title">"Securitate &amp; confidențialitate"</string>
<string name="screen_room_details_security_title">"Securitate"</string>
<string name="screen_room_details_share_room_title">"Partajați camera"</string>
<string name="screen_room_details_title">"Informatii camera"</string>
<string name="screen_room_details_topic_title">"Subiect"</string>
<string name="screen_room_details_updating_room">"Se actualizează camera…"</string>
<string name="screen_room_member_list_banned_empty">"Nu există utilizatori interziși în această cameră."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"o persoană"</item>
<item quantity="other">"%1$d persoane"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Îndepărtați și interziceți membrul"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Doar înlăturare"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Anulare excludere"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Se vor putea alătura din nou acestei săli dacă sunt invitați."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Revocati excluderea din camera"</string>
<string name="screen_room_member_list_mode_banned">"Excluși"</string>
<string name="screen_room_member_list_mode_members">"Membri"</string>
<string name="screen_room_member_list_role_administrator">"Doar administratori"</string>
<string name="screen_room_member_list_role_moderator">"Administratori și moderatori"</string>
<string name="screen_room_member_list_role_owner">"Proprietar"</string>
<string name="screen_room_member_list_room_members_header_title">"Membrii camerei"</string>
<string name="screen_room_member_list_unbanning_user">"Se anulează interzicerea lui %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Permiteți setări personalizate"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Activarea acestei opțiuni va anula setările implicite."</string>
<string name="screen_room_notification_settings_custom_settings_title">"Anunțați-mă în acestă cameră pentru"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Îl puteți schimba în %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"Setări generale"</string>
<string name="screen_room_notification_settings_default_setting_title">"Setare implicită"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Ștergeți setarea personalizată"</string>
<string name="screen_room_notification_settings_error_loading_settings">"A apărut o eroare la încărcarea setărilor pentry notificari."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Nu s-a reușit restaurarea modului implicit, vă rugăm să încercați din nou."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Nu s-a reușit setarea modului, vă rugăm să încercați din nou."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Serverul dumneavoastră nu acceptă această opțiune în camerele criptate, nu veți primi notificări în această cameră."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Toate mesajele"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Numai mențiuni și cuvinte cheie"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"În această cameră, anunțați-mă pentru"</string>
<string name="screen_room_roles_and_permissions_admins">"Administratori"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administratori și proprietari"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Schimbare rol"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Degradare la membru"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Degradare la moderator"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderarea membrilor"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Mesaje și conținut"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatori"</string>
<string name="screen_room_roles_and_permissions_owners">"Proprietari"</string>
<string name="screen_room_roles_and_permissions_reset">"Resetați permisiunile"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"După ce resetați permisiunile, veți pierde setările curente."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Resetați permisiunile?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roluri"</string>
<string name="screen_room_roles_and_permissions_room_details">"Detaliile camerei"</string>
<string name="screen_room_roles_and_permissions_title">"Roluri și permisiuni"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Adăugați adresa camerei"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Oricine poate cere să se alăture camerei, dar un administrator sau moderator va trebui să accepte cererea."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Cereți să vă alăturați"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Da, activați criptarea"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Odată activată, criptarea pentru o cameră nu poate fi dezactivată. Mesajele anterioare vor fi vizibile numai pentru membrii camerei de la momentul la care au fost invitați sau de la momentul la care s-au alăturat camerei.
Nimeni în afară de membrii camerei nu va putea citi messaje. Acest lucru poate împiedica funcționarea corectă a boților și a punților.
Nu recomandăm activarea criptării pentru camerele pe care oricine le poate găsi și la care se poate alătura."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Activați criptarea?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Odată activată, criptarea nu poate fi dezactivată."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Criptare"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Activați criptarea end-to-end"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Oricine poate găsi și alătura camerei"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Oricine"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Persoanele se pot alătura numai dacă invitate"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Doar pe bază de invitație"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Acces la cameră"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Membrii spațiului"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Spațiile nu sunt momentan suportate."</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Veți avea nevoie de o adresă de cameră pentru a o face vizibilă în director."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Permiteți găsirea acestei camere prin căutarea în directorul de camere publice al %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Vizibilă în directorul de camere publice"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Oricine"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Cine poate citi mesajele anterioare"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Doar pentru membri, de la momentul în care au fost invitați"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Doar pentru membri, după selectarea acestei opțiuni"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Adresele camerelor sunt modalități de a găsi și accesa camere. Acest lucru vă asigură, de asemenea, că puteți partaja cu ușurință camera dumneavoastră cu alte persoane.
Puteți alege să publicați camera în directorul public al camerelor serverului dumneavoastră."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Publicare cameră"</string>
<string name="screen_security_and_privacy_title">"Securitate &amp; confidențialitate"</string>
</resources>

View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Вам понадобится адрес комнаты, чтобы сделать ее видимой в каталоге."</string>
<string name="screen_edit_room_address_title">"Редактировать адрес комнаты"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Произошла ошибка при обновлении настройки уведомления."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш домашний сервер не поддерживает эту опцию в зашифрованных комнатах, в некоторых комнатах вы можете не получать уведомления."</string>
<string name="screen_polls_history_title">"Опросы"</string>
<string name="screen_room_change_permissions_administrators">"Только администраторы"</string>
<string name="screen_room_change_permissions_ban_people">"Блокировать людей могут"</string>
<string name="screen_room_change_permissions_delete_messages">"Удалить сообщения"</string>
<string name="screen_room_change_permissions_everyone">"Участник"</string>
<string name="screen_room_change_permissions_invite_people">"Пригласить людей"</string>
<string name="screen_room_change_permissions_member_moderation">"Список участников"</string>
<string name="screen_room_change_permissions_messages_and_content">"Сообщения и содержание"</string>
<string name="screen_room_change_permissions_moderators">"Модератор"</string>
<string name="screen_room_change_permissions_remove_people">"Удалять участников"</string>
<string name="screen_room_change_permissions_room_avatar">"Менять изображение комнаты могут"</string>
<string name="screen_room_change_permissions_room_details">"Редактировать комнату"</string>
<string name="screen_room_change_permissions_room_name">"Менять название комнаты могут"</string>
<string name="screen_room_change_permissions_room_topic">"Менять тему комнаты могут"</string>
<string name="screen_room_change_permissions_send_messages">"Отправлять сообщения могут"</string>
<string name="screen_room_change_role_administrators_title">"Редактировать роль администраторов"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Вы не сможете отменить это действие. Вы устанавливаете уровень пользователю соответствующий вашему."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Добавить администратора?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Отменить данное действие будет невозможно. Владение передастся выбранным пользователям. После вашего выхода действие станет необратимым."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Передать владение?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Понизить уровень"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Вы не сможете отменить это изменение, так как понижаете себя статус. Если вы являетесь последним привилегированным пользователем в комнате, восстановить привилегии будет невозможно."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Понизить свой уровень?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Ожидание)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(В ожидании)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Администраторы автоматически получают права модератора"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Владельцы автоматически получают права администратора."</string>
<string name="screen_room_change_role_moderators_title">"Редактировать роль модераторов"</string>
<string name="screen_room_change_role_owners_title">"Назначить владельцев"</string>
<string name="screen_room_change_role_section_administrators">"Администраторы"</string>
<string name="screen_room_change_role_section_moderators">"Модераторы"</string>
<string name="screen_room_change_role_section_users">"Участники"</string>
<string name="screen_room_change_role_unsaved_changes_description">"У вас есть несохраненные изменения."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Сохранить изменения?"</string>
<string name="screen_room_details_add_topic_title">"Добавить тему"</string>
<string name="screen_room_details_badge_encrypted">"Зашифровано"</string>
<string name="screen_room_details_badge_not_encrypted">"Шифрования нет"</string>
<string name="screen_room_details_badge_public">"Общедоступная комната"</string>
<string name="screen_room_details_edit_room_title">"Редактировать комнату"</string>
<string name="screen_room_details_edition_error">"Произошла неизвестная ошибка и информацию не удалось изменить."</string>
<string name="screen_room_details_edition_error_title">"Не удалось обновить комнату"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Сообщения зашифрованы. Только у вас и у получателей есть уникальные ключи для их разблокировки."</string>
<string name="screen_room_details_encryption_enabled_title">"Шифрование сообщений включено"</string>
<string name="screen_room_details_error_loading_notification_settings">"Произошла ошибка при загрузке настроек уведомлений."</string>
<string name="screen_room_details_error_muting">"Не удалось отключить звук в этой комнате, попробуйте еще раз."</string>
<string name="screen_room_details_error_unmuting">"Не удалось включить звук в эту комнату, попробуйте еще раз."</string>
<string name="screen_room_details_invite_people_dont_close">"Не закрывайте приложение, пока не закончите."</string>
<string name="screen_room_details_invite_people_preparing">"Подготовка приглашений…"</string>
<string name="screen_room_details_invite_people_title">"Пригласить в комнату"</string>
<string name="screen_room_details_leave_conversation_title">"Покинуть беседу"</string>
<string name="screen_room_details_leave_room_title">"Покинуть комнату"</string>
<string name="screen_room_details_media_gallery_title">"Медиа и файлы"</string>
<string name="screen_room_details_notification_mode_custom">"Пользовательский"</string>
<string name="screen_room_details_notification_mode_default">"По умолчанию"</string>
<string name="screen_room_details_notification_title">"Уведомления"</string>
<string name="screen_room_details_pinned_events_row_title">"Закрепленные сообщения"</string>
<string name="screen_room_details_profile_row_title">"Профиль"</string>
<string name="screen_room_details_requests_to_join_title">"Запросы на вступление"</string>
<string name="screen_room_details_roles_and_permissions">"Роли и разрешения"</string>
<string name="screen_room_details_room_name_label">"Название комнаты"</string>
<string name="screen_room_details_security_and_privacy_title">"Безопасность и конфиденциальность"</string>
<string name="screen_room_details_security_title">"Безопасность"</string>
<string name="screen_room_details_share_room_title">"Поделиться комнатой"</string>
<string name="screen_room_details_title">"Информация о комнате"</string>
<string name="screen_room_details_topic_title">"Тема"</string>
<string name="screen_room_details_updating_room">"Обновление комнаты…"</string>
<string name="screen_room_member_list_banned_empty">"В этой комнате нет заблокированных пользователей."</string>
<string name="screen_room_member_list_empty_search_subtitle">"Проверьте правописание или попробуйте новый поиск"</string>
<string name="screen_room_member_list_empty_search_title">"Отсутствует результат по запросу “%1$s”"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d пользователь"</item>
<item quantity="few">"%1$d пользователя"</item>
<item quantity="many">"%1$d пользователей"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Удалить и заблокировать участника"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Только удалить участника"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Разблокировать"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Они снова смогут присоединиться в эту комнату если их пригласят."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Разблокировать в комнате"</string>
<string name="screen_room_member_list_mode_banned">"Заблокированные"</string>
<string name="screen_room_member_list_mode_members">"Участники"</string>
<string name="screen_room_member_list_pending_status">"В ожидании"</string>
<string name="screen_room_member_list_role_administrator">"Только администраторы"</string>
<string name="screen_room_member_list_role_moderator">"Модератор"</string>
<string name="screen_room_member_list_role_owner">"Владелец"</string>
<string name="screen_room_member_list_room_members_header_title">"Участники комнаты"</string>
<string name="screen_room_member_list_unbanning_user">"Разблокировка %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Разрешить пользовательские настройки"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Включение этого параметра отменяет настройки по умолчанию"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Уведомлять меня в этом чате"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Вы можете изменить его в своем %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"основные настройки"</string>
<string name="screen_room_notification_settings_default_setting_title">"Настройка по умолчанию"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Удалить пользовательскую настройку"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Произошла ошибка при загрузке настроек уведомлений."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Не удалось восстановить режим по умолчанию, попробуйте еще раз."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Не удалось настроить режим, попробуйте еще раз."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Ваш домашний сервер не поддерживает эту опцию в зашифрованных комнатах, вы не будете получать уведомления в этой комнате."</string>
<string name="screen_room_notification_settings_mode_all_messages">"О всех сообщениях"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Только упоминания и ключевые слова"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"В этой комнате уведомлять меня"</string>
<string name="screen_room_roles_and_permissions_admins">"Администраторы"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Администраторы и владельцы"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Изменить мою роль"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Понизить до участника"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Понизить до модератора"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Модерация участников"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Сообщения и содержание"</string>
<string name="screen_room_roles_and_permissions_moderators">"Модераторы"</string>
<string name="screen_room_roles_and_permissions_owners">"Владельцы"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Разрешения"</string>
<string name="screen_room_roles_and_permissions_reset">"Сбросить разрешения"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Как только вы сбросите разрешения, все текущие настройки будут утеряны."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Сбросить разрешения?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Роли"</string>
<string name="screen_room_roles_and_permissions_room_details">"Информация о комнате"</string>
<string name="screen_room_roles_and_permissions_title">"Роли и разрешения"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Добавить адрес"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Каждый должен запросить доступ."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Попросить присоединиться"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Да, включить шифрование"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Шифрование комнаты нельзя будет отключить, история сообщений будет видна только участникам комнаты с момента их приглашения или с момента присоединения к комнате.
Никто, кроме членов комнаты, не сможет читать сообщения. Это может помешать ботам и мостам работать корректно.
Мы не рекомендуем включать шифрование для комнат, в которые может найти и присоединиться любой желающий."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Включить шифрование?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"После включения, шифрование не может быть отключено."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Шифрование"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Включить сквозное шифрование"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Любой желающий может найти и присоединиться"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Любой"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Присоединиться могут только приглашенные люди."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Только по приглашению"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Доступ"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Участники пространства"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Пространства в настоящее время не поддерживаются."</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Вам понадобится адрес комнаты, чтобы сделать ее видимой в каталоге."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Адрес"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Опубликовать %1$s в каталоге публичных комнат"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Разрешить поиск в публичном каталоге."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Доступна в списке публичных комнат"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Любой"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Кто может читать историю"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Участники только с тех пор, как они были приглашены"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Только для участников с момента выбора этой опции"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Адреса комнат — это способ найти комнату и получить к ней доступ. Это также гарантирует, что вы сможете легко поделиться своей комнатой с другими.
Вы можете опубликовать свою комнату в каталоге общедоступных комнат на домашнем сервере."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Публикация комнат"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Видимость"</string>
<string name="screen_security_and_privacy_title">"Безопасность и конфиденциальность"</string>
</resources>

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Budete potrebovať adresu miestnosti, aby bola viditeľná v adresári."</string>
<string name="screen_edit_room_address_title">"Adresa miestnosti"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Pri aktualizácii nastavenia oznámenia došlo k chybe."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Váš domovský server nepodporuje túto možnosť v šifrovaných miestnostiach, v niektorých miestnostiach nemusíte dostať upozornenie."</string>
<string name="screen_polls_history_title">"Ankety"</string>
<string name="screen_room_change_permissions_administrators">"Iba správcovia"</string>
<string name="screen_room_change_permissions_ban_people">"Zakázať ľudí"</string>
<string name="screen_room_change_permissions_delete_messages">"Odstrániť správy"</string>
<string name="screen_room_change_permissions_invite_people">"Pozvite ľudí a prijmite žiadosti o pripojenie"</string>
<string name="screen_room_change_permissions_messages_and_content">"Správy a obsah"</string>
<string name="screen_room_change_permissions_moderators">"Správcovia a moderátori"</string>
<string name="screen_room_change_permissions_remove_people">"Odstrániť ľudí a odmietnuť žiadosti o pripojenie"</string>
<string name="screen_room_change_permissions_room_avatar">"Zmeniť obrázok miestnosti"</string>
<string name="screen_room_change_permissions_room_details">"Upraviť miestnosť"</string>
<string name="screen_room_change_permissions_room_name">"Zmeniť názov miestnosti"</string>
<string name="screen_room_change_permissions_room_topic">"Zmeniť tému miestnosti"</string>
<string name="screen_room_change_permissions_send_messages">"Odoslať správy"</string>
<string name="screen_room_change_role_administrators_title">"Upraviť správcov"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Túto akciu nebudete môcť vrátiť späť. Zvyšujete úroveň používateľa na rovnakú úroveň výkonu ako máte vy."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Pridať správcu?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Túto akciu nebude možné vrátiť späť. Prenášate vlastníctvo na vybraných používateľov. Po opustení bude táto akcia trvalá."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Previesť vlastníctvo?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Znížiť"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Túto zmenu nebudete môcť vrátiť späť, pretože znižujete svoju úroveň. Ak ste posledným privilegovaným používateľom v miestnosti, nebude možné získať znova oprávnenia."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Znížiť svoju úroveň?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Čaká sa)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Čaká sa)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Správcovia majú automaticky oprávnenia moderátora"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Vlastníci majú automaticky správcovské oprávnenia."</string>
<string name="screen_room_change_role_moderators_title">"Upraviť moderátorov"</string>
<string name="screen_room_change_role_owners_title">"Vybrať vlastníkov"</string>
<string name="screen_room_change_role_section_administrators">"Správcovia"</string>
<string name="screen_room_change_role_section_moderators">"Moderátori"</string>
<string name="screen_room_change_role_section_users">"Členovia"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Máte neuložené zmeny."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Uložiť zmeny?"</string>
<string name="screen_room_details_add_topic_title">"Pridať tému"</string>
<string name="screen_room_details_badge_encrypted">"Zašifrované"</string>
<string name="screen_room_details_badge_not_encrypted">"Nešifrované"</string>
<string name="screen_room_details_badge_public">"Verejná miestnosť"</string>
<string name="screen_room_details_edit_room_title">"Upraviť miestnosť"</string>
<string name="screen_room_details_edition_error">"Vyskytla sa neznáma chyba a informácie nebolo možné zmeniť."</string>
<string name="screen_room_details_edition_error_title">"Nepodarilo sa aktualizovať miestnosť"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Správy sú zabezpečené zámkami. Jedine vy a príjemcovia máte jedinečné kľúče na ich odomknutie."</string>
<string name="screen_room_details_encryption_enabled_title">"Šifrovanie správ je zapnuté"</string>
<string name="screen_room_details_error_loading_notification_settings">"Pri načítaní nastavení oznámení došlo k chybe."</string>
<string name="screen_room_details_error_muting">"Nepodarilo sa stlmiť túto miestnosť, skúste to prosím znova."</string>
<string name="screen_room_details_error_unmuting">"Nepodarilo sa zrušiť stlmenie tejto miestnosti, skúste to prosím znova."</string>
<string name="screen_room_details_invite_people_dont_close">"Nezatvárajte aplikáciu, kým sa neukončí pozývanie."</string>
<string name="screen_room_details_invite_people_preparing">"Príprava pozvánok…"</string>
<string name="screen_room_details_invite_people_title">"Pozvať ľudí"</string>
<string name="screen_room_details_leave_conversation_title">"Opustiť konverzáciu"</string>
<string name="screen_room_details_leave_room_title">"Opustiť miestnosť"</string>
<string name="screen_room_details_media_gallery_title">"Médiá a súbory"</string>
<string name="screen_room_details_notification_mode_custom">"Vlastné"</string>
<string name="screen_room_details_notification_mode_default">"Predvolené"</string>
<string name="screen_room_details_notification_title">"Oznámenia"</string>
<string name="screen_room_details_pinned_events_row_title">"Pripnuté správy"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Žiadosti o vstup"</string>
<string name="screen_room_details_roles_and_permissions">"Roly a povolenia"</string>
<string name="screen_room_details_room_name_label">"Názov miestnosti"</string>
<string name="screen_room_details_security_and_privacy_title">"Bezpečnosť a súkromie"</string>
<string name="screen_room_details_security_title">"Bezpečnosť"</string>
<string name="screen_room_details_share_room_title">"Zdieľať miestnosť"</string>
<string name="screen_room_details_title">"Informácie o miestnosti"</string>
<string name="screen_room_details_topic_title">"Téma"</string>
<string name="screen_room_details_updating_room">"Aktualizácia miestnosti…"</string>
<string name="screen_room_member_list_banned_empty">"Neexistujú žiadni zablokovaní používatelia."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d osoba"</item>
<item quantity="few">"%1$d osoby"</item>
<item quantity="other">"%1$d osôb"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Odstrániť a zakázať člena"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Iba odstrániť člena"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Zrušiť zákaz"</string>
<string name="screen_room_member_list_manage_member_unban_message">"V prípade pozvania sa budú môcť znova pripojiť k tejto miestnosti."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Zrušiť zákaz prístupu do miestnosti"</string>
<string name="screen_room_member_list_mode_banned">"Zakázaní"</string>
<string name="screen_room_member_list_mode_members">"Členovia"</string>
<string name="screen_room_member_list_role_administrator">"Iba správcovia"</string>
<string name="screen_room_member_list_role_moderator">"Správcovia a moderátori"</string>
<string name="screen_room_member_list_role_owner">"Vlastník"</string>
<string name="screen_room_member_list_room_members_header_title">"Členovia miestnosti"</string>
<string name="screen_room_member_list_unbanning_user">"Zrušenie zákazu %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Povoliť vlastné nastavenie"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Zapnutím tohto nastavenia sa prepíše vaše predvolené nastavenie"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Upozorniť ma v tejto konverzácii na"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Môžete to zmeniť vo svojich %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"všeobecných nastaveniach"</string>
<string name="screen_room_notification_settings_default_setting_title">"Predvolené nastavenie"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Odstrániť vlastné nastavenie"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Pri načítavaní nastavení oznámení došlo k chybe."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Nepodarilo sa obnoviť predvolený režim, skúste to prosím znova."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Nepodarilo sa nastaviť režim, skúste to prosím znova."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Váš domovský server nepodporuje túto možnosť v šifrovaných miestnostiach, v tejto miestnosti nedostanete upozornenie."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Všetky správy"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Iba zmienky a kľúčové slová"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"V tejto miestnosti ma upozorniť na"</string>
<string name="screen_room_roles_and_permissions_admins">"Správcovia"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Správcovia a vlastníci"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Zmeniť moje oprávnenia"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Znížiť úroveň na člena"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Znížiť úroveň na moderátora"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Moderovanie členov"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Správy a obsah"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderátori"</string>
<string name="screen_room_roles_and_permissions_owners">"Vlastníci"</string>
<string name="screen_room_roles_and_permissions_reset">"Obnoviť povolenia"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Po obnovení oprávnení prídete o aktuálne nastavenia."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Obnoviť oprávnenia?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roly"</string>
<string name="screen_room_roles_and_permissions_room_details">"Podrobnosti o miestnosti"</string>
<string name="screen_room_roles_and_permissions_title">"Roly a povolenia"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Pridať adresu miestnosti"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Ktokoľvek môže požiadať o pripojenie do miestnosti, ale správca alebo moderátor bude musieť žiadosť prijať."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Požiadať o pripojenie"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Áno, povoliť šifrovanie"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Po aktivácii nie je možné zakázať šifrovanie pre miestnosť. História správ bude viditeľná len pre členov miestnosti, odkedy boli pozvaní alebo keď vstúpili do miestnosti.
Nikto okrem členov miestnosti nebude môcť čítať správy.
To môže brániť správnemu fungovaniu robotov a premostení. Neodporúčame povoliť šifrovanie pre miestnosti, ktoré môže ktokoľvek nájsť a pripojiť sa k nim."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Povoliť šifrovanie?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Po zapnutí už šifrovanie nie je možné vypnúť."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Šifrovanie"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Povoliť end-to-end šifrovanie"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Ktokoľvek môže nájsť a pripojiť sa"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Ktokoľvek"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Ľudia sa môžu pripojiť len vtedy, ak sú pozvaní"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Iba na pozvánku"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Prístup do miestnosti"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Členovia priestoru"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Priestory momentálne nie sú podporované"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Budete potrebovať adresu miestnosti, aby bola viditeľná v adresári."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Adresa miestnosti"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Umožniť vyhľadanie tejto miestnosti v adresári verejných miestností %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Viditeľné v adresári verejných miestností"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Ktokoľvek"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Kto môže čítať históriu"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Len pre členov, odkedy boli pozvaní"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Len členovia od zvolenia tejto možnosti"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Adresy miestností predstavujú spôsoby, ako nájsť a získať prístup k miestnostiam. To tiež zaisťuje, že môžete jednoducho zdieľať svoju miestnosť s ostatnými.
Môžete sa rozhodnúť zverejniť svoju miestnosť v adresári verejných miestností vášho domovského servera."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Zverejnenie miestnosti"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Viditeľnosť miestnosti"</string>
<string name="screen_security_and_privacy_title">"Bezpečnosť a súkromie"</string>
</resources>

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Du behöver en rumsadress för att göra den synlig i katalogen."</string>
<string name="screen_edit_room_address_title">"Rumsadress"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Ett fel uppstod vid uppdatering av aviseringsinställningen."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Din hemserver stöder inte det här alternativet i krypterade rum, du kanske inte aviseras i vissa rum."</string>
<string name="screen_polls_history_title">"Omröstningar"</string>
<string name="screen_room_change_permissions_administrators">"Endast administratörer"</string>
<string name="screen_room_change_permissions_ban_people">"Banna personer"</string>
<string name="screen_room_change_permissions_delete_messages">"Ta bort meddelanden"</string>
<string name="screen_room_change_permissions_invite_people">"Bjuda in personer och acceptera förfrågningar om att gå med"</string>
<string name="screen_room_change_permissions_messages_and_content">"Meddelanden och innehåll"</string>
<string name="screen_room_change_permissions_moderators">"Administratörer och moderatorer"</string>
<string name="screen_room_change_permissions_remove_people">"Ta bort personer och avslå förfrågningar om att gå med"</string>
<string name="screen_room_change_permissions_room_avatar">"Byt rumsavatar"</string>
<string name="screen_room_change_permissions_room_details">"Redigera rummet"</string>
<string name="screen_room_change_permissions_room_name">"Byt rumsnamn"</string>
<string name="screen_room_change_permissions_room_topic">"Byt rumsämne"</string>
<string name="screen_room_change_permissions_send_messages">"Skicka meddelanden"</string>
<string name="screen_room_change_role_administrators_title">"Redigera administratörer"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Du kommer inte att kunna ångra den här åtgärden. Du befordrar användaren till att ha samma behörighetsnivå som du."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Lägg till Admin?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Du kommer inte att kunna ångra den här åtgärden. Du överför ägarskapet till de valda användarna. När du lämnar kommer detta att vara permanent."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Överför ägarskap?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Degradera"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Du kommer inte att kunna ångra denna ändring eftersom du degraderar dig själv, om du är den sista privilegierade användaren i rummet kommer det att vara omöjligt att återfå privilegier."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Degradera dig själv?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Väntar)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Väntar)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Administratörer har automatiskt moderatorbehörighet"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Ägare har automatiskt administratörsbehörighet."</string>
<string name="screen_room_change_role_moderators_title">"Redigera moderatorer"</string>
<string name="screen_room_change_role_owners_title">"Välj ägare"</string>
<string name="screen_room_change_role_section_administrators">"Administratörer"</string>
<string name="screen_room_change_role_section_moderators">"Moderatorer"</string>
<string name="screen_room_change_role_section_users">"Medlemmar"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Du har osparade ändringar."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Spara ändringar?"</string>
<string name="screen_room_details_add_topic_title">"Lägg till ämne"</string>
<string name="screen_room_details_badge_encrypted">"Krypterat"</string>
<string name="screen_room_details_badge_not_encrypted">"Inte krypterat"</string>
<string name="screen_room_details_badge_public">"Offentligt rum"</string>
<string name="screen_room_details_edit_room_title">"Redigera rummet"</string>
<string name="screen_room_details_edition_error">"Ett okänt fel uppstod och informationen kunde inte ändras."</string>
<string name="screen_room_details_edition_error_title">"Kunde inte uppdatera rummet"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Meddelanden är säkrade med lås. Bara du och mottagarna har de unika nycklarna för att låsa upp dem."</string>
<string name="screen_room_details_encryption_enabled_title">"Meddelandekryptering aktiverad"</string>
<string name="screen_room_details_error_loading_notification_settings">"Ett fel uppstod vid laddning av aviseringsinställningar."</string>
<string name="screen_room_details_error_muting">"Misslyckades att tysta det här rummet, vänligen pröva igen."</string>
<string name="screen_room_details_error_unmuting">"Misslyckades att avtysta det här rummet, vänligen pröva igen."</string>
<string name="screen_room_details_invite_people_title">"Bjud in personer"</string>
<string name="screen_room_details_leave_conversation_title">"Lämna konversation"</string>
<string name="screen_room_details_leave_room_title">"Lämna rum"</string>
<string name="screen_room_details_media_gallery_title">"Media och filer"</string>
<string name="screen_room_details_notification_mode_custom">"Anpassad"</string>
<string name="screen_room_details_notification_mode_default">"Förval"</string>
<string name="screen_room_details_notification_title">"Aviseringar"</string>
<string name="screen_room_details_pinned_events_row_title">"Fästa meddelanden"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Begäran om att gå med"</string>
<string name="screen_room_details_roles_and_permissions">"Roller och behörigheter"</string>
<string name="screen_room_details_room_name_label">"Rumsnamn"</string>
<string name="screen_room_details_security_and_privacy_title">"Säkerhet och sekretess"</string>
<string name="screen_room_details_security_title">"Säkerhet"</string>
<string name="screen_room_details_share_room_title">"Dela rum"</string>
<string name="screen_room_details_title">"Rumsinfo"</string>
<string name="screen_room_details_topic_title">"Ämne"</string>
<string name="screen_room_details_updating_room">"Uppdaterar rummet …"</string>
<string name="screen_room_member_list_banned_empty">"Det finns inga bannade användare i det här rummet."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d person"</item>
<item quantity="other">"%1$d personer"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Ta bort och banna medlem"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Ta bara bort medlem"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Avbanna"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Denne kommer kunna gå med i rummet igen om denne bjuds in"</string>
<string name="screen_room_member_list_manage_member_unban_title">"Avbanna från rummet"</string>
<string name="screen_room_member_list_mode_banned">"Bannade"</string>
<string name="screen_room_member_list_mode_members">"Medlemmar"</string>
<string name="screen_room_member_list_role_administrator">"Endast administratörer"</string>
<string name="screen_room_member_list_role_moderator">"Administratörer och moderatorer"</string>
<string name="screen_room_member_list_role_owner">"Ägare"</string>
<string name="screen_room_member_list_room_members_header_title">"Rumsmedlemmar"</string>
<string name="screen_room_member_list_unbanning_user">"Avbannar %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Tillåt anpassad inställning"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Om du aktiverar detta åsidosätts din standardinställning"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Meddela mig i den här chatten för"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Du kan ändra det i dina %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"globala inställningar"</string>
<string name="screen_room_notification_settings_default_setting_title">"Standardinställning"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Ta bort anpassad inställning"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Ett fel uppstod vid laddning av aviseringsinställningarna."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Misslyckades att återställa standardläget, vänligen försök igen."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Misslyckades att ställa in läget, vänligen pröva igen."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Din hemserver stöder inte det här alternativet i krypterade rum, du blir inte aviserad i det här rummet."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Alla meddelanden"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Endast omnämnanden och nyckelord"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"I det här rummet, meddela mig för"</string>
<string name="screen_room_roles_and_permissions_admins">"Administratörer"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Administratörer och ägare"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Ändra min roll"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Degradera till medlem"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Degradera till moderator"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Medlemsmoderering"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Meddelanden och innehåll"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatorer"</string>
<string name="screen_room_roles_and_permissions_owners">"Ägare"</string>
<string name="screen_room_roles_and_permissions_reset">"Återställ behörigheter"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"När du har återställt behörigheterna kommer du att förlora de aktuella inställningarna."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Återställ behörigheter?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roller"</string>
<string name="screen_room_roles_and_permissions_room_details">"Rumsdetaljer"</string>
<string name="screen_room_roles_and_permissions_title">"Roller och behörigheter"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Lägg till rumsadress"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Vem som helst kan be om att gå med i rummet men en administratör eller moderator måste acceptera begäran."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Be om att gå med"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ja, aktivera kryptering"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"När det är aktiverat kan kryptering för ett rum inte inaktiveras, meddelandehistoriken visas bara för rumsmedlemmar sedan de blev inbjudna eller sedan de gick med i rummet.
Ingen förutom rumsmedlemmarna kommer att kunna läsa meddelanden. Detta kan förhindra att bots och bridges fungerar korrekt.
Vi rekommenderar inte att aktivera kryptering för rum som vem som helst kan hitta och gå med i."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Aktivera kryptering?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Efter aktivering kan kryptering inte inaktiveras."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Kryptering"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Aktivera totalsträckskryptering"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Vem som helst kan hitta och gå med"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Vem som helst"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Användare kan bara gå med om de är inbjudna"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Endast inbjudan"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Tillgång till rum"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Utrymmesmedlemmar"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Utrymmen stöds för närvarande inte"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Du behöver en rumsadress för att göra den synlig i katalogen."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Tillåt att detta rum hittas genom att söka i den offentliga rumskatalogen på %1$s"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Synlig i katalogen för offentliga rum"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Vem som helst"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Vem kan läsa historik"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Endast medlemmar sedan de bjöds in"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Endast medlemmar sedan det här alternativet har valts"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Rumsadresser är sätt att hitta och komma åt rum. Detta säkerställer också att du enkelt kan dela ditt rum med andra.
Du kan välja att publicera ditt rum i din hemservers offentliga rumskatalog."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Rumspublicering"</string>
<string name="screen_security_and_privacy_title">"Säkerhet och sekretess"</string>
</resources>

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Dizinde görünür hale getirmek için bir oda adresine ihtiyacınız olacak."</string>
<string name="screen_edit_room_address_title">"Oda adresi"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Bildirim ayarı güncellenirken bir hata oluştu."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Ana sunucunuz şifreli odalarda bu seçeneği desteklemiyor, bazı odalarda bildirim almayabilirsiniz."</string>
<string name="screen_polls_history_title">"Anketler"</string>
<string name="screen_room_change_permissions_administrators">"Yalnızca yöneticiler"</string>
<string name="screen_room_change_permissions_ban_people">"İnsanları yasakla"</string>
<string name="screen_room_change_permissions_delete_messages">"Mesajları kaldır"</string>
<string name="screen_room_change_permissions_invite_people">"Kişileri davet etme ve katılma isteklerini kabul etme"</string>
<string name="screen_room_change_permissions_messages_and_content">"Mesajlar ve içerik"</string>
<string name="screen_room_change_permissions_moderators">"Yöneticiler ve moderatörler"</string>
<string name="screen_room_change_permissions_remove_people">"Kişileri kaldırma ve katılma isteklerini reddetme"</string>
<string name="screen_room_change_permissions_room_avatar">"Oda resmini değiştir"</string>
<string name="screen_room_change_permissions_room_details">"Odayı Düzenle"</string>
<string name="screen_room_change_permissions_room_name">"Oda adını değiştir"</string>
<string name="screen_room_change_permissions_room_topic">"Oda konusunu değiştir"</string>
<string name="screen_room_change_permissions_send_messages">"Mesaj gönder"</string>
<string name="screen_room_change_role_administrators_title">"Yöneticileri Düzenle"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Bu eylemi geri alamazsınız. Kullanıcıyı sizinle aynı güç seviyesine sahip olacak şekilde terfi ettiriyorsunuz."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Yönetici Ekle?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Rütbe Düşür"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Rütbenizi düşürdüğünüz için bu değişikliği geri alamazsınız, eğer odadaki son ayrıcalıklı kullanıcı sizseniz ayrıcalıkları yeniden kazanmanız mümkün olmayacaktır."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Rütbeni düşür?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Beklemede)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Beklemede)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Yöneticiler otomatik olarak moderatör ayrıcalıklarına sahiptir"</string>
<string name="screen_room_change_role_moderators_title">"Moderatörleri Düzenle"</string>
<string name="screen_room_change_role_section_administrators">"Yöneticiler"</string>
<string name="screen_room_change_role_section_moderators">"Moderatörler"</string>
<string name="screen_room_change_role_section_users">"Üyeler"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Kaydedilmemiş değişiklikleriniz var."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Değişiklikleri Kaydet?"</string>
<string name="screen_room_details_add_topic_title">"Konu ekle"</string>
<string name="screen_room_details_badge_encrypted">"Şifrelenmiş"</string>
<string name="screen_room_details_badge_not_encrypted">"Şifrelenmemiş"</string>
<string name="screen_room_details_badge_public">"Herkese açık oda"</string>
<string name="screen_room_details_edit_room_title">"Odayı Düzenle"</string>
<string name="screen_room_details_edition_error">"Bilinmeyen bir hata oluştu ve bilgiler değiştirilemedi."</string>
<string name="screen_room_details_edition_error_title">"Oda güncellenemiyor"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Mesajlar kilitlerle güvence altına alınır. Yalnızca siz ve alıcılar, bunların kilidini açmak için benzersiz anahtarlara sahipsiniz."</string>
<string name="screen_room_details_encryption_enabled_title">"Mesaj şifrelemesi etkinleştirildi"</string>
<string name="screen_room_details_error_loading_notification_settings">"Bildirim ayarları yüklenirken bir hata oluştu."</string>
<string name="screen_room_details_error_muting">"Bu odayı sessize alma başarısız oldu, lütfen tekrar deneyin."</string>
<string name="screen_room_details_error_unmuting">"Bu odanın sesi açılamadı, lütfen tekrar deneyin."</string>
<string name="screen_room_details_invite_people_title">"İnsanları davet et"</string>
<string name="screen_room_details_leave_conversation_title">"Sohbeti bırak"</string>
<string name="screen_room_details_leave_room_title">"Odadan ayrıl"</string>
<string name="screen_room_details_media_gallery_title">"Medya ve dosyalar"</string>
<string name="screen_room_details_notification_mode_custom">"Özel"</string>
<string name="screen_room_details_notification_mode_default">"Varsayılan"</string>
<string name="screen_room_details_notification_title">"Bildirimler"</string>
<string name="screen_room_details_pinned_events_row_title">"Sabitlenmiş mesajlar"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Katılma istekleri"</string>
<string name="screen_room_details_roles_and_permissions">"Roller ve izinler"</string>
<string name="screen_room_details_room_name_label">"Oda adı"</string>
<string name="screen_room_details_security_and_privacy_title">"Güvenlik ve gizlilik"</string>
<string name="screen_room_details_security_title">"Güvenlik"</string>
<string name="screen_room_details_share_room_title">"Oda paylaş"</string>
<string name="screen_room_details_title">"Oda bilgisi"</string>
<string name="screen_room_details_topic_title">"Konu"</string>
<string name="screen_room_details_updating_room">"Oda güncelleniyor…"</string>
<string name="screen_room_member_list_banned_empty">"Bu odada yasaklı kullanıcı yok."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d kişi"</item>
<item quantity="other">"%1$d kişi"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Üyeyi çıkar ve yasakla"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Yalnızca üyeyi kaldır"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Yasağı Kaldır"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Davet edildikleri takdirde bu odaya tekrar katılabileceklerdir."</string>
<string name="screen_room_member_list_mode_banned">"Yasaklandı"</string>
<string name="screen_room_member_list_mode_members">"Üyeler"</string>
<string name="screen_room_member_list_role_administrator">"Yalnızca yöneticiler"</string>
<string name="screen_room_member_list_role_moderator">"Yöneticiler ve moderatörler"</string>
<string name="screen_room_member_list_room_members_header_title">"Oda üyeleri"</string>
<string name="screen_room_member_list_unbanning_user">"Yasak kaldırılıyor %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Özel ayarlara izin ver"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Bunu açmak varsayılan ayarlarınızı geçersiz kılacaktır"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Bu sohbette bana bildir"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Bunu %1$s içinde değiştirebilirsiniz."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"genel ayarlar"</string>
<string name="screen_room_notification_settings_default_setting_title">"Varsayılan ayar"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Özel ayarı kaldır"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Bildirim ayarları yüklenirken bir hata oluştu."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Varsayılan ayarlar geri yüklenemedi, lütfen tekrar deneyin."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Ayarlanamadı, lütfen tekrar deneyin."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Ana sunucunuz şifreli odalarda bu seçeneği desteklemiyor, bu odada bildirim almayacaksınız."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Tüm mesajlar"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Yalnızca Bahsetmeler ve Anahtar Kelimeler"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Bu odada, bana bildir"</string>
<string name="screen_room_roles_and_permissions_admins">"Yöneticiler"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Rolümü değiştir"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Üyeliğe düşür"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Moderatörlüğe düşür"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Üye moderasyonu"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Mesajlar ve içerik"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatörler"</string>
<string name="screen_room_roles_and_permissions_reset">"İzinleri sıfırla"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"İzinleri sıfırladığınızda, mevcut ayarları kaybedersiniz."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"İzinleri sıfırla?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roller"</string>
<string name="screen_room_roles_and_permissions_room_details">"Oda bilgileri"</string>
<string name="screen_room_roles_and_permissions_title">"Roller ve izinler"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Oda adresi ekle"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Herkes odaya katılma isteğinde bulunabilir ancak bir yönetici veya moderatörün isteği kabul etmesi gerekir."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Katılmak için sor"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Evet, şifrelemeyi etkinleştir"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Etkinleştirildikten sonra, bir oda için şifreleme devre dışı bırakılamaz, Mesaj geçmişi yalnızca davet edildiklerinden veya odaya katıldıklarından beri oda üyeleri için görünür olacaktır.
Oda üyeleri dışında hiç kimse mesajları okuyamayacaktır. Bu, botların ve köprülerin düzgün çalışmasını engelleyebilir.
Herkesin bulabileceği ve katılabileceği odalar için şifrelemenin etkinleştirilmesini önermiyoruz."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Şifrelemeyi etkinleştir?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Açıldıktan donra şifreleme kapatılamaz."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Şifreleme"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Uçtan uca şifrelemeyi etkinleştir"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Herkes bulabilir ve katılabilir"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Herkes"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"İnsanlar yalnızca davet edildiklerinde katılabilirler"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Yalnızca davet"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Oda Erişimi"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Alan üyeleri"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Alanlar şu anda desteklenmiyor"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Dizinde görünür hale getirmek için bir oda adresine ihtiyacınız olacak."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Oda adresi"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Bu odanın %1$s genel oda dizininde arama yapılarak bulunmasına izin verin"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Genel oda dizininde görünür"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Herkes"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Geçmişi kimler okuyabilir ?"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Sadece üyeler (davet edildiklerinden beri)"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Bu seçeneği seçtiğinden beri yalnızca üyeler"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Oda adresleri, odaları bulmanın ve odalara erişmenin yoludur. Bu aynı zamanda odanızı başkalarıyla kolayca paylaşabilmenizi sağlar.
Odanızı ana sunucunuzun genel oda dizininde yayınlamayı seçebilirsiniz."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Oda yayınlama"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Oda görünürlüğü"</string>
<string name="screen_security_and_privacy_title">"Güvenlik ve gizlilik"</string>
</resources>

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі."</string>
<string name="screen_edit_room_address_title">"Адреса кімнати"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Під час оновлення налаштувань сповіщень сталася помилка."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Ваш домашній сервер не підтримує цю опцію в зашифрованих кімнатах, ви можете не отримати сповіщення в деяких кімнатах."</string>
<string name="screen_polls_history_title">"Опитування"</string>
<string name="screen_room_change_permissions_administrators">"Тільки для адміністраторів"</string>
<string name="screen_room_change_permissions_ban_people">"Заблоковувати людей"</string>
<string name="screen_room_change_permissions_delete_messages">"Вилучати повідомлення"</string>
<string name="screen_room_change_permissions_invite_people">"Запрошувати людей і приймати запити на приєднання"</string>
<string name="screen_room_change_permissions_messages_and_content">"Повідомлення та зміст"</string>
<string name="screen_room_change_permissions_moderators">"Адміністратори та модератори"</string>
<string name="screen_room_change_permissions_remove_people">"Вилучати людей і відхиляти запити на приєднання"</string>
<string name="screen_room_change_permissions_room_avatar">"Змінювати аватар кімнати"</string>
<string name="screen_room_change_permissions_room_details">"Редагувати кімнату"</string>
<string name="screen_room_change_permissions_room_name">"Змінювати назву кімнати"</string>
<string name="screen_room_change_permissions_room_topic">"Змінювати тему кімнати"</string>
<string name="screen_room_change_permissions_send_messages">"Надсилати повідомлення"</string>
<string name="screen_room_change_role_administrators_title">"Керувати адмінами"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Ви не зможете скасувати цю дію. Ви просуваєте користувача, щоб він мав такий же рівень прав, як і ви."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Додати адміністратора?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Ви не зможете скасувати цю дію. Ви передаєте право власності вибраним користувачам. Після вашого виходу це буде остаточно."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Передати право власності?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Понизити"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Ви не зможете скасувати цю зміну, оскільки ви понижуєте себе, якщо ви останній привілейований користувач у кімнаті, відновити повноваження буде неможливо."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Понизити себе?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Очікується)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Очікується)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Адміністратори автоматично мають повноваження модератора"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Власники автоматично отримують права адміністратора."</string>
<string name="screen_room_change_role_moderators_title">"Керувати модераторами"</string>
<string name="screen_room_change_role_owners_title">"Оберіть власників"</string>
<string name="screen_room_change_role_section_administrators">"Адміністратори"</string>
<string name="screen_room_change_role_section_moderators">"Модератори"</string>
<string name="screen_room_change_role_section_users">"Учасники"</string>
<string name="screen_room_change_role_unsaved_changes_description">"У вас є не збережені зміни."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Зберегти зміни?"</string>
<string name="screen_room_details_add_topic_title">"Додати тему"</string>
<string name="screen_room_details_badge_encrypted">"Зашифровано"</string>
<string name="screen_room_details_badge_not_encrypted">"Не зашифровано"</string>
<string name="screen_room_details_badge_public">"Загальнодоступна кімната"</string>
<string name="screen_room_details_edit_room_title">"Редагувати кімнату"</string>
<string name="screen_room_details_edition_error">"Сталася невідома помилка, й інформацію не вдалося змінити."</string>
<string name="screen_room_details_edition_error_title">"Не вдалося оновити кімнату"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Повідомлення захищені замками. Тільки ви та одержувачі маєте унікальні ключі для їх розблокування."</string>
<string name="screen_room_details_encryption_enabled_title">"Шифрування повідомлень увімкнено"</string>
<string name="screen_room_details_error_loading_notification_settings">"Виникла помилка при завантаженні налаштувань сповіщень."</string>
<string name="screen_room_details_error_muting">"Не вдалося вимкнути цю кімнату. Будь ласка, спробуйте ще раз."</string>
<string name="screen_room_details_error_unmuting">"Не вдалося ввімкнути звук цієї кімнати. Повторіть спробу."</string>
<string name="screen_room_details_invite_people_title">"Запросити людей"</string>
<string name="screen_room_details_leave_conversation_title">"Залишити розмову"</string>
<string name="screen_room_details_leave_room_title">"Вийти з кімнати"</string>
<string name="screen_room_details_media_gallery_title">"Медіа та файли"</string>
<string name="screen_room_details_notification_mode_custom">"Власні"</string>
<string name="screen_room_details_notification_mode_default">"Типово"</string>
<string name="screen_room_details_notification_title">"Сповіщення"</string>
<string name="screen_room_details_pinned_events_row_title">"Закріплені повідомлення"</string>
<string name="screen_room_details_profile_row_title">"Профіль"</string>
<string name="screen_room_details_requests_to_join_title">"Запити на приєднання"</string>
<string name="screen_room_details_roles_and_permissions">"Ролі та дозволи"</string>
<string name="screen_room_details_room_name_label">"Назва кімнати"</string>
<string name="screen_room_details_security_and_privacy_title">"Безпека й приватність"</string>
<string name="screen_room_details_security_title">"Безпека"</string>
<string name="screen_room_details_share_room_title">"Поділитися кімнатою"</string>
<string name="screen_room_details_title">"Інформація про кімнату"</string>
<string name="screen_room_details_topic_title">"Тема"</string>
<string name="screen_room_details_updating_room">"Оновлення кімнати…"</string>
<string name="screen_room_member_list_banned_empty">"У цій кімнаті немає заблокованих користувачів."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d особа"</item>
<item quantity="few">"%1$d особи"</item>
<item quantity="many">"%1$d осіб"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Вилучити й заблокувати учасника"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Лише вилучити учасника"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Розблокувати"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Вони зможуть знову приєднатися до цієї кімнати, якщо їх запросять."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Розблокувати в кімнаті"</string>
<string name="screen_room_member_list_mode_banned">"Заблоковані"</string>
<string name="screen_room_member_list_mode_members">"Учасники"</string>
<string name="screen_room_member_list_role_administrator">"Тільки для адміністраторів"</string>
<string name="screen_room_member_list_role_moderator">"Адміністратори та модератори"</string>
<string name="screen_room_member_list_role_owner">"Власник"</string>
<string name="screen_room_member_list_room_members_header_title">"Учасники кімнати"</string>
<string name="screen_room_member_list_unbanning_user">"Розблокування %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Дозволити користувальницькі налаштування"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Увімкнення цього параметра змінить типові налаштування"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Сповіщати мене в цій бесіді про"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Ви можете змінити це у своїх %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"глобальних налаштуваннях"</string>
<string name="screen_room_notification_settings_default_setting_title">"Типові налаштування"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Вилучити користувальницькі налаштування"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Під час завантаження налаштувань сповіщень сталася помилка."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Не вдалося відновити типовий режим, спробуйте ще раз."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Не вдалося встановити режим, спробуйте ще раз."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Ваш домашній сервер не підтримує цю опцію в зашифрованих кімнатах, ви не отримаєте сповіщення в цій кімнаті."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Всі повідомлення"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Тільки згадки та ключові слова"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"У цій кімнаті сповіщати мене про"</string>
<string name="screen_room_roles_and_permissions_admins">"Адміністратори"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Адміністратори та власники"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Змінити мою роль"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Понизити до учасника"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Понизити до модератора"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Модерація учасників"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Повідомлення та зміст"</string>
<string name="screen_room_roles_and_permissions_moderators">"Модератори"</string>
<string name="screen_room_roles_and_permissions_owners">"Власники"</string>
<string name="screen_room_roles_and_permissions_reset">"Скинути дозволи"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Після скидання дозволів ви втратите поточні налаштування."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Скинути дозволи?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Ролі"</string>
<string name="screen_room_roles_and_permissions_room_details">"Деталі кімнати"</string>
<string name="screen_room_roles_and_permissions_title">"Ролі та дозволи"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Додати адресу кімнати"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Будь-хто може надіслати запит приєднатися до кімнати, але адміністратор або модератор повинні прийняти запит."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Запросити приєднатися"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Так, увімкнути шифрування"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Після ввімкнення шифрування кімнати, його неможливо вимкнути, історію повідомлень бачитимуть лише учасники кімнати, яких було запрошено або які приєдналися до кімнати.
Ніхто, крім учасників кімнати, не зможе прочитати повідомлення. Це може перешкоджати коректній роботі ботів і мостів.
Ми не радимо вмикати шифрування для кімнат, які будь-хто може знайти та до яких може приєднатися всі."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Увімкнути шифрування?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Після ввімкнення шифрування неможливо вимкнути."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Шифрування"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Увімкнути наскрізне шифрування"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Будь-хто може знайти та приєднатися."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Кожний"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Люди можуть приєднатися, лише якщо їх запросили"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Лише запрошені"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Доступ до кімнати"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Учасники простору"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Простори наразі не підтримуються"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Адреса кімнати"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Дозвольте, щоб цю кімнату можна було знайти за допомогою пошуку в каталозі загальнодоступних кімнат %1$s "</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Видима в каталозі загальнодоступних кімнат"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Кожний"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Хто може читати історію"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Лише учасники з моменту запрошення"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Лише учасники після вибору цього параметра"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Адреси кімнат — це спосіб знайти кімнату та отримати до неї доступ. Це також гарантує, що ви можете легко поділитися своєю кімнатою з іншими.
Ви можете опублікувати свою кімнату в каталозі загальнодоступних кімнат вашого домашнього сервера."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Публікація в кімнаті"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Видимість кімнати"</string>
<string name="screen_security_and_privacy_title">"Безпека й приватність"</string>
</resources>

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_notification_settings_edit_failed_updating_default_mode">"اطلاع کی ترتیب کی تجدید کرتے ہوئے ایک نقص واقع ہوا۔"</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"آپ کا منزلی خادم مرموز کردہ کمروں میں اس اختیار کی حمایت نہیں کرت، ہوسکتا ہے کچھ کمروں میں آپ کو مطلع نہ کیا جائے۔"</string>
<string name="screen_polls_history_title">"رائے شماری ہا"</string>
<string name="screen_room_change_permissions_administrators">"صرف منتظمین"</string>
<string name="screen_room_change_permissions_ban_people">"لوگوں کو محظور کریں"</string>
<string name="screen_room_change_permissions_delete_messages">"پیغامات ہٹائیں"</string>
<string name="screen_room_change_permissions_invite_people">"لوگوں کو مدعو کریں اور شمولیت کی درخواستیں قبول کریں"</string>
<string name="screen_room_change_permissions_messages_and_content">"پیغامات اور مواد"</string>
<string name="screen_room_change_permissions_moderators">"منتظمین اور ناظمین"</string>
<string name="screen_room_change_permissions_remove_people">"لوگوں کو ہٹا دیں اور شمولیت کی درخواستیں مسترد کریں"</string>
<string name="screen_room_change_permissions_room_avatar">"کمرے کا اوتار بدلیں"</string>
<string name="screen_room_change_permissions_room_details">"کمرے میں ترمیم کریں"</string>
<string name="screen_room_change_permissions_room_name">"کمرے کا نام بدلیں"</string>
<string name="screen_room_change_permissions_room_topic">"کمرے کا موضوع بدلیں"</string>
<string name="screen_room_change_permissions_send_messages">"پیغامات بھیجیں"</string>
<string name="screen_room_change_role_administrators_title">"منتظمین میں ترمیم کریں"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"آپ اس کارروائی کو کالعدم نہیں کرسکیں گے۔ آپ صارف کو اپنی جیسی طاقت کی سطح رکھنے کے لئے فروغ دے رہے ہیں۔"</string>
<string name="screen_room_change_role_confirm_add_admin_title">"منتظم شمال کریں؟"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"تنزل کریں"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"آپ اس تبدیلی کو کالعدم نہیں کرسکیں گے کیونکہ آپ اپنے آپ کو تنزل کر رہے ہیں، اگر آپ کمرے میں آخری مراعات یافتہ صارف ہیں تو مراعات پھر حاصل کرنا ناممکن ہو جائے گا۔"</string>
<string name="screen_room_change_role_confirm_demote_self_title">"اپنے آپ کو تنزل کریں؟"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (زیر التواء)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(زیر التواء)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"منتظمین کے پاس خودکاراً ناظمین مراعات ہوتی ہیں"</string>
<string name="screen_room_change_role_moderators_title">"ناظمین میں ترمیم کریں"</string>
<string name="screen_room_change_role_section_administrators">"منتظمین"</string>
<string name="screen_room_change_role_section_moderators">"ناظمین"</string>
<string name="screen_room_change_role_section_users">"اراکین"</string>
<string name="screen_room_change_role_unsaved_changes_description">"آپکے پاس غیر محفوظ تبدیلیاں ہیں"</string>
<string name="screen_room_change_role_unsaved_changes_title">"تبدیلیاں محفوظ کریں؟"</string>
<string name="screen_room_details_add_topic_title">"موضوع شامل کریں"</string>
<string name="screen_room_details_badge_encrypted">"مرموز کردہ"</string>
<string name="screen_room_details_badge_not_encrypted">"رموز کردہ نہیں"</string>
<string name="screen_room_details_badge_public">"عوامی کمرہ"</string>
<string name="screen_room_details_edit_room_title">"کمرے میں ترمیم کریں"</string>
<string name="screen_room_details_edition_error">"ایک نامعلوم خلل تھا اور معلومات تبدیل نہیں ہوسکی۔"</string>
<string name="screen_room_details_edition_error_title">"کمرے کی تجدید کرنے سے قاصر"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"پیغامات قفلوں کے ساتھ محفوظ ہیں۔ ان کو غیر مقفل کرنے کے لیے صرف آپ اور وصول کنندگان کے پاس منفرد چابیاں ہیں۔"</string>
<string name="screen_room_details_encryption_enabled_title">"پیغام کی مرموزکاری فعال ہے۔"</string>
<string name="screen_room_details_error_loading_notification_settings">"اطلاع کی ترتیبات لادتے ہوئے ایک نقص واقع ہوا۔"</string>
<string name="screen_room_details_error_muting">"اس کمرے کو خاموش کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔"</string>
<string name="screen_room_details_error_unmuting">"اس کمرے کو غیر خاموش کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔"</string>
<string name="screen_room_details_invite_people_title">"لوگوں کو مدعو کریں"</string>
<string name="screen_room_details_leave_conversation_title">"گفتگو چھوڑیں"</string>
<string name="screen_room_details_leave_room_title">"کمرہ چھوڑ دیں"</string>
<string name="screen_room_details_notification_mode_custom">"حسب ضرورت"</string>
<string name="screen_room_details_notification_mode_default">"طے شدہ"</string>
<string name="screen_room_details_notification_title">"اطلاعات"</string>
<string name="screen_room_details_pinned_events_row_title">"مثبوتہ پیغامات"</string>
<string name="screen_room_details_profile_row_title">"نمایہ"</string>
<string name="screen_room_details_roles_and_permissions">"کردارہا اور اجازتیں"</string>
<string name="screen_room_details_room_name_label">"کمرے کا نام"</string>
<string name="screen_room_details_security_title">"حفاظت"</string>
<string name="screen_room_details_share_room_title">"کمرے کا اشتراک کریں"</string>
<string name="screen_room_details_title">"کمرے کی معلومات"</string>
<string name="screen_room_details_topic_title">"موضوع"</string>
<string name="screen_room_details_updating_room">"کمرے کی تجدید کر رہا ہے…"</string>
<string name="screen_room_member_list_banned_empty">"اس کمرے میں کوئی محظور صارفین نہیں ہیں۔"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d شخص"</item>
<item quantity="other">"%1$d اشخاص"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"کمرے سے محظور کریں"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"رکن کو صرف ہٹائیں"</string>
<string name="screen_room_member_list_manage_member_unban_action">"غیر محظور کریں"</string>
<string name="screen_room_member_list_manage_member_unban_message">"اگر وہ مدعو کیا جائیں تو وہ دوبارہ اس کمرے میں شامل ہوسکیں گے۔"</string>
<string name="screen_room_member_list_mode_banned">"محظور"</string>
<string name="screen_room_member_list_mode_members">"اراکین"</string>
<string name="screen_room_member_list_role_administrator">"صرف منتظمین"</string>
<string name="screen_room_member_list_role_moderator">"منتظمین اور ناظمین"</string>
<string name="screen_room_member_list_room_members_header_title">"کمرے کے ارکان"</string>
<string name="screen_room_member_list_unbanning_user">"%1$s کو غیر محظور کر رہا ہے"</string>
<string name="screen_room_notification_settings_allow_custom">"حسب ضرورت ترتیب کی اجازت دیں"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"اسے چالو کرنے سے آپکی متعینہ ترتیبات تجاوز گی جائیں گی"</string>
<string name="screen_room_notification_settings_custom_settings_title">"اس گفتگو میں مجھے مطلع کریں برائے"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"آپ اسے اپنے %1$s میں بدل سکتے ہیں۔"</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"عالمی ترتیبات"</string>
<string name="screen_room_notification_settings_default_setting_title">"متعین ترتیب"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"حسب ضرورت ترتیب کو ہٹائیں"</string>
<string name="screen_room_notification_settings_error_loading_settings">"اطلاع کی ترتیبات لادتے ہوئے ایک نقص واقع ہوا۔"</string>
<string name="screen_room_notification_settings_error_restoring_default">"متعین وضع کو بحال کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔"</string>
<string name="screen_room_notification_settings_error_setting_mode">"وضع ترتیب دینے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔"</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"آپ کا منزلی خادم مرموز کردہ کمروں میں اس اختیار کی حمایت نہیں کرتا ہے، آپ کو اس کمرے میں مطلع کیا جائے گا۔"</string>
<string name="screen_room_notification_settings_mode_all_messages">"تمام پیغامات"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"صرف تذکرے اور کلیدی الفاظ"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"اس کمرے میں، مجھے مطلع کریں برائے"</string>
<string name="screen_room_roles_and_permissions_admins">"منتظمین"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"میرا کردار تبدیل کریں"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"تا رکن تنزلی کریں"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"تا ناظم تنزلی کریں"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"ارکان کا اعتدال"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"پیغامات اور مواد"</string>
<string name="screen_room_roles_and_permissions_moderators">"ناظمین"</string>
<string name="screen_room_roles_and_permissions_reset">"اجازتیں بحال کریں"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"ایک بار جب آپ اجازتیں بحال کردیں گے، آپ موجودہ ترتیبات کھو دیں گے۔"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"اجازتیں بحال کریں؟"</string>
<string name="screen_room_roles_and_permissions_roles_header">"کردارہا"</string>
<string name="screen_room_roles_and_permissions_room_details">"کمرے کی تفصیلات"</string>
<string name="screen_room_roles_and_permissions_title">"کردارہا اور اجازتیں"</string>
</resources>

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Katalogda korinadigan qilish uchun xona manzili kerak boladi."</string>
<string name="screen_edit_room_address_title">"Xona manzili"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"Bildirishnoma sozlamalarini yangilashda xatolik yuz berdi."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Uy serveringiz shifrlangan xonalarda ushbu imkoniyatni qoʻllab-quvvatlamaydi, shuning uchun baʼzi xonalardagi xabarlarni olmasligingiz mumkin."</string>
<string name="screen_polls_history_title">"Soʻrovnomalar"</string>
<string name="screen_room_change_permissions_administrators">"Faqat adminlar"</string>
<string name="screen_room_change_permissions_ban_people">"Odamlarni taqiqlash"</string>
<string name="screen_room_change_permissions_delete_messages">"Xabarlarni olib tashlash"</string>
<string name="screen_room_change_permissions_invite_people">"Odamlarni taklif qiling va qoshilish sorovlarini qabul qiling"</string>
<string name="screen_room_change_permissions_messages_and_content">"Xabarlar va kontent"</string>
<string name="screen_room_change_permissions_moderators">"Adminlar va moderatorlar"</string>
<string name="screen_room_change_permissions_remove_people">"Odamlarni olib tashlash va qoʻshilish soʻrovlarini rad etish"</string>
<string name="screen_room_change_permissions_room_avatar">"Xona avatarini oʻzgartirish"</string>
<string name="screen_room_change_permissions_room_details">"Xonani tahrirlash"</string>
<string name="screen_room_change_permissions_room_name">"Xona nomini oʻzgartirish"</string>
<string name="screen_room_change_permissions_room_topic">"Xona mavzusini almashtirish"</string>
<string name="screen_room_change_permissions_send_messages">"Xabarlar yuborish"</string>
<string name="screen_room_change_role_administrators_title">"Administratorlarni tahrirlash"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"Bu amalni bekor qila olmaysiz. Siz foydalanuvchini ozingiz bilan bir xil quvvat darajasiga ega bolishga undayapsiz."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Admin qoshilsinmi?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"Bu amalni bekor qila olmaysiz. Siz egalikni tanlangan foydalanuvchilarga otkazmoqdasiz. Tark etsangiz, bu doimiy boladi."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Egalik huquqini otkazasizmi?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Pastga tushirish"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"Siz oʻzingizni imtiyozlardan mahrum qilayotganingiz sababli, bu ozgarishni bekor qila olmaysiz. Agar xonadagi songgi imtiyozli foydalanuvchi bolsangiz, imtiyozlarni qayta tiklash imkonsiz boladi."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Oz darajangizni pasaytirmoqchimisiz?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Jarayonda)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Kutilmoqda)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Administratorlar avtomatik ravishda moderator imtiyozlariga ega"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Egalar avtomatik ravishda administrator huquqlariga ega."</string>
<string name="screen_room_change_role_moderators_title">"Moderatorlarni tahrirlash"</string>
<string name="screen_room_change_role_owners_title">"Egalarni tanlang"</string>
<string name="screen_room_change_role_section_administrators">"Adminlar"</string>
<string name="screen_room_change_role_section_moderators">"Moderatorlar"</string>
<string name="screen_room_change_role_section_users">"Azolar"</string>
<string name="screen_room_change_role_unsaved_changes_description">"Sizda saqlanmagan oʻzgarishlar bor"</string>
<string name="screen_room_change_role_unsaved_changes_title">"Ozgartirishlarni saqlaysizmi?"</string>
<string name="screen_room_details_add_topic_title">"Mavzu qo\'shish"</string>
<string name="screen_room_details_badge_encrypted">"Shifrlangan"</string>
<string name="screen_room_details_badge_not_encrypted">"Shifrlanmagan"</string>
<string name="screen_room_details_badge_public">"Jamoat xonasi"</string>
<string name="screen_room_details_edit_room_title">"Xonani tahrirlash"</string>
<string name="screen_room_details_edition_error">"Nomaʼlum xatolik yuz berdi va maʼlumotni oʻzgartirib boʻlmadi."</string>
<string name="screen_room_details_edition_error_title">"Xonani yangilab bolmadi"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Xabarlar qulflar bilan himoyalangan. Faqat siz va qabul qiluvchilar ularni qulfdan chiqarish uchun noyob kalitlarga ega."</string>
<string name="screen_room_details_encryption_enabled_title">"Xabarni shifrlash yoqilgan"</string>
<string name="screen_room_details_error_loading_notification_settings">"Bildirishnoma sozlamalarini yuklashda xatolik yuz berdi."</string>
<string name="screen_room_details_error_muting">"Bu xona ovozini ochirib bolmadi, qayta urinib koring."</string>
<string name="screen_room_details_error_unmuting">"Bu xonaning ovozi yoqilmadi, qayta urinib koring."</string>
<string name="screen_room_details_invite_people_title">"Odamlarni taklif qiling"</string>
<string name="screen_room_details_leave_conversation_title">"Suhbatni tark etish"</string>
<string name="screen_room_details_leave_room_title">"Xonani tark etish"</string>
<string name="screen_room_details_media_gallery_title">"Media va fayllar"</string>
<string name="screen_room_details_notification_mode_custom">"Maxsus"</string>
<string name="screen_room_details_notification_mode_default">"Standart"</string>
<string name="screen_room_details_notification_title">"Bildirishnomalar"</string>
<string name="screen_room_details_pinned_events_row_title">"Qadalgan xabarlar"</string>
<string name="screen_room_details_profile_row_title">"Profil"</string>
<string name="screen_room_details_requests_to_join_title">"Qoshilish uchun sorovlar"</string>
<string name="screen_room_details_roles_and_permissions">"Rollar va ruxsatlar"</string>
<string name="screen_room_details_room_name_label">"Xona nomi"</string>
<string name="screen_room_details_security_and_privacy_title">"Xavfsizlik va maxfiylik"</string>
<string name="screen_room_details_security_title">"Xavfsizlik"</string>
<string name="screen_room_details_share_room_title">"Xonani baham ko\'ring"</string>
<string name="screen_room_details_title">"Xona haqida maʼlumot"</string>
<string name="screen_room_details_topic_title">"Mavzu"</string>
<string name="screen_room_details_updating_room">"Xona yangilanmoqda…"</string>
<string name="screen_room_member_list_banned_empty">"Bu xonada taqiqlangan foydalanuvchilar yoʻq."</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$dodam"</item>
<item quantity="other">"%1$dodamlar"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Xonadan chetlashtirish"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Faqat aʻzoni olib tashlash"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Taqiqni bekor qilish"</string>
<string name="screen_room_member_list_manage_member_unban_message">"Agar taklif qilinsa, ular bu xonaga qayta qoshilishlari mumkin."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Xonadan taqiqni olib tashlash"</string>
<string name="screen_room_member_list_mode_banned">"Taqiqlangan"</string>
<string name="screen_room_member_list_mode_members">"Azolar"</string>
<string name="screen_room_member_list_role_administrator">"Faqat adminlar"</string>
<string name="screen_room_member_list_role_moderator">"Adminlar va moderatorlar"</string>
<string name="screen_room_member_list_role_owner">"Egasi"</string>
<string name="screen_room_member_list_room_members_header_title">"Xona a\'zolari"</string>
<string name="screen_room_member_list_unbanning_user">"Taqiqni bekor qilish %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Moslashtirilgan sozlamalarga ruxsat bering"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Buni yoqsangiz, standart sozlamalaringiz bekor qilinadi"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Bu chatda menga xabar bering"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"Siz buni o\'zgartira olasiz o\'zingizning %1$sda."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"global sozlamalar"</string>
<string name="screen_room_notification_settings_default_setting_title">"Standart sozlama"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Maxsus sozlamani olib tashlang"</string>
<string name="screen_room_notification_settings_error_loading_settings">"Bildirishnoma sozlamalarini yuklashda xatolik yuz berdi."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Standart rejimni tiklab bolmadi, qaytadan urinib koring."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Rejimni ornatib bolmadi, qayta urinib koring."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Uy serveringiz shifrlangan xonalarda ushbu imkoniyatni qoʻllab-quvvatlamaydi, shuning uchun bu xonadan bildirishnomalar olmaysiz."</string>
<string name="screen_room_notification_settings_mode_all_messages">"Barcha xabarlar"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Faqat eslatmalar va kalit so\'zlar"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"Bu xonada menga xabar bering"</string>
<string name="screen_room_roles_and_permissions_admins">"Adminlar"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Adminlar va egalari"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Rolimni ozgartirish"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Aʼzolikka tushirish"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Moderatorga pasaytirish"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Aʻzo moderatsiyasi"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Xabarlar va kontent"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderatorlar"</string>
<string name="screen_room_roles_and_permissions_owners">"Egalari"</string>
<string name="screen_room_roles_and_permissions_reset">"Ruxsatlarni tiklash"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Ruxsatlarni asliga qaytargach, joriy sozlamalarni yoʻqotasiz."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Ruxsatlar asliga qaytarilsinmi?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Rollar"</string>
<string name="screen_room_roles_and_permissions_room_details">"Xona tafsilotlari"</string>
<string name="screen_room_roles_and_permissions_title">"Rollar va ruxsatlar"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Xona manzilini kiritish"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Xonaga qoshilishni istalgan kishi sorashi mumkin, lekin administrator yoki moderator sorovni qabul qilishi kerak"</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Qoshilishni sorang"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Ha, shifrlashni yoqish"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Yoqilgandan song, xona uchun shifrlashni ochirib bolmaydi. Xabarlar tarixi faqat xona azolari taklif qilinganidan yoki xonaga qoshilganidan keyingi davrdan boshlab korinadi. Xona azolaridan tashqari hech kim xabarlarni oqiy olmaydi. Bu botlar va kopriklarning togri ishlashiga tosqinlik qilishi mumkin.
Shu sababli, har kim topishi va qoshilishi mumkin bolgan xonalar uchun shifrlashni yoqishni tavsiya etmaymiz."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Shifrlash yoqilsinmi?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Yoqilgandan keyin shifrlashni faolsizlantirish imkonsiz."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Shifrlash"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"End-to-end shifrlashni yoqish"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Istalgan kishi topishi va qoshilishi mumkin"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Har kim"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Odamlar faqat taklif qilingan taqdirdagina qoshilishi mumkin"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Faqat taklif qilish"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Xonaga kirish huquqi"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Maydon azolari"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Hozirda maydonlar qollab-quvvatlanmaydi"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Katalogda korinadigan qilish uchun xona manzili kerak boladi."</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Bu xonani %1$s umumiy xonalar royxatidan qidirib topish imkoniyatini berish"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Umumiy xona royxatida korinadi"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Har kim"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Tarixni kim oqiy oladi"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Taklif qilinganidan buyon faqat azolar"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Azolar faqat bu parametr tanlanganidan keyin"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Xona manzillari xonalarni topish va ularga kirish usullaridir. Bu shuningdek xonangizni boshqalar bilan oson ulashish imkonini beradi.
Xonangizni oz homeserveringizning ommaviy xonalar royxatida elon qilishni tanlashingiz mumkin."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"xona nashriyoti"</string>
<string name="screen_security_and_privacy_title">"Xavfsizlik va maxfiylik"</string>
</resources>

View File

@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"您需要地址才能在公開目錄中顯示。"</string>
<string name="screen_edit_room_address_title">"編輯地址"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"更新通知設定時發生錯誤。"</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"您的家伺服器在加密聊天室中不支援此選項,可能無法收到部份聊天室的通知。"</string>
<string name="screen_polls_history_title">"所有投票"</string>
<string name="screen_room_change_permissions_administrators">"管理員"</string>
<string name="screen_room_change_permissions_ban_people">"管理黑名單"</string>
<string name="screen_room_change_permissions_delete_messages">"移除訊息"</string>
<string name="screen_room_change_permissions_everyone">"成員"</string>
<string name="screen_room_change_permissions_invite_people">"邀請夥伴"</string>
<string name="screen_room_change_permissions_member_moderation">"管理成員"</string>
<string name="screen_room_change_permissions_messages_and_content">"訊息與內容"</string>
<string name="screen_room_change_permissions_moderators">"版主"</string>
<string name="screen_room_change_permissions_remove_people">"移除夥伴"</string>
<string name="screen_room_change_permissions_room_avatar">"變更聊天室大頭照"</string>
<string name="screen_room_change_permissions_room_details">"編輯詳細資訊"</string>
<string name="screen_room_change_permissions_room_name">"變更聊天室名稱"</string>
<string name="screen_room_change_permissions_room_topic">"變更聊天室主題"</string>
<string name="screen_room_change_permissions_send_messages">"傳送訊息"</string>
<string name="screen_room_change_role_administrators_title">"編輯管理員"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"您將無法復原此動作。您正將使用者提昇至與您相同的權力等級。"</string>
<string name="screen_room_change_role_confirm_add_admin_title">"要新增管理員嗎?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"您將無法撤銷此動作。您正在將所有權轉移給選定的使用者。一旦您離開,此動作將永久有效。"</string>
<string name="screen_room_change_role_confirm_change_owners_title">"轉移所有權?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"降級"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"當您自行降級時,您將無法復原此變更,若您是聊天室中的最後一位特權使用者,則無法重新獲得權限。"</string>
<string name="screen_room_change_role_confirm_demote_self_title">"將自己降級?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s擱置中"</string>
<string name="screen_room_change_role_invited_member_name_android">"(擱置中)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"管理員自動擁有版主權限"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"擁有者自動擁有管理員權限。"</string>
<string name="screen_room_change_role_moderators_title">"編輯版主"</string>
<string name="screen_room_change_role_owners_title">"選擇擁有者"</string>
<string name="screen_room_change_role_section_administrators">"管理員"</string>
<string name="screen_room_change_role_section_moderators">"版主"</string>
<string name="screen_room_change_role_section_users">"成員"</string>
<string name="screen_room_change_role_unsaved_changes_description">"您有尚未儲存的變更"</string>
<string name="screen_room_change_role_unsaved_changes_title">"是否儲存變更?"</string>
<string name="screen_room_details_add_topic_title">"新增主題"</string>
<string name="screen_room_details_badge_encrypted">"已加密"</string>
<string name="screen_room_details_badge_not_encrypted">"未加密"</string>
<string name="screen_room_details_badge_public">"公開的聊天室"</string>
<string name="screen_room_details_edit_room_title">"編輯詳細資訊"</string>
<string name="screen_room_details_edition_error">"發生未知錯誤,無法變更資訊。"</string>
<string name="screen_room_details_edition_error_title">"無法更新聊天室"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"訊息透過鎖定保護。只有您與收件者才有解鎖它們的唯一金鑰。"</string>
<string name="screen_room_details_encryption_enabled_title">"訊息已加密"</string>
<string name="screen_room_details_error_loading_notification_settings">"載入通知設定時發生錯誤。"</string>
<string name="screen_room_details_error_muting">"無法關閉聊天室通知,請再試一次。"</string>
<string name="screen_room_details_error_unmuting">"無法開啟聊天室通知,請再試一次。"</string>
<string name="screen_room_details_invite_people_dont_close">"完成前請勿關閉應用程式。"</string>
<string name="screen_room_details_invite_people_preparing">"正在準備邀請……"</string>
<string name="screen_room_details_invite_people_title">"邀請夥伴"</string>
<string name="screen_room_details_leave_conversation_title">"離開對話"</string>
<string name="screen_room_details_leave_room_title">"離開聊天室"</string>
<string name="screen_room_details_media_gallery_title">"媒體與檔案"</string>
<string name="screen_room_details_notification_mode_custom">"自訂"</string>
<string name="screen_room_details_notification_mode_default">"預設"</string>
<string name="screen_room_details_notification_title">"通知"</string>
<string name="screen_room_details_pinned_events_row_title">"釘選訊息"</string>
<string name="screen_room_details_profile_row_title">"個人檔案"</string>
<string name="screen_room_details_requests_to_join_title">"請求加入"</string>
<string name="screen_room_details_roles_and_permissions">"角色與權限"</string>
<string name="screen_room_details_room_name_label">"聊天室名稱"</string>
<string name="screen_room_details_security_and_privacy_title">"安全與隱私"</string>
<string name="screen_room_details_security_title">"安全性"</string>
<string name="screen_room_details_share_room_title">"分享聊天室"</string>
<string name="screen_room_details_title">"聊天室資訊"</string>
<string name="screen_room_details_topic_title">"主題"</string>
<string name="screen_room_details_updating_room">"正在更新聊天室…"</string>
<string name="screen_room_member_list_banned_empty">"沒有被封鎖的使用者。"</string>
<string name="screen_room_member_list_empty_search_subtitle">"檢查拼字或嘗試新搜尋"</string>
<string name="screen_room_member_list_empty_search_title">"找不到「%1$s」"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="other">"%1$d 個人"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"踢出並加入黑名單"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"僅移除成員"</string>
<string name="screen_room_member_list_manage_member_unban_action">"解除黑名單"</string>
<string name="screen_room_member_list_manage_member_unban_message">"如果收到邀請,他們能再次加入聊天室。"</string>
<string name="screen_room_member_list_manage_member_unban_title">"從聊天室解除封鎖"</string>
<string name="screen_room_member_list_mode_banned">"黑名單"</string>
<string name="screen_room_member_list_mode_members">"成員"</string>
<string name="screen_room_member_list_pending_status">"擱置中"</string>
<string name="screen_room_member_list_role_administrator">"管理員"</string>
<string name="screen_room_member_list_role_moderator">"版主"</string>
<string name="screen_room_member_list_role_owner">"擁有者"</string>
<string name="screen_room_member_list_room_members_header_title">"聊天室成員"</string>
<string name="screen_room_member_list_unbanning_user">"正在解除黑名單 %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"允許自訂設定"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"啟用此功能將會覆寫您的預設設定"</string>
<string name="screen_room_notification_settings_custom_settings_title">"在此聊天中通知我"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"您可以在您的 %1$s 中變更它。"</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"全域設定"</string>
<string name="screen_room_notification_settings_default_setting_title">"預設"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"移除自訂設定"</string>
<string name="screen_room_notification_settings_error_loading_settings">"載入通知設定時發生錯誤。"</string>
<string name="screen_room_notification_settings_error_restoring_default">"無法重設為預設模式,請再試一次。"</string>
<string name="screen_room_notification_settings_error_setting_mode">"無法設定模式,請再試一次。"</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"您的家伺服器在加密聊天室中不支援此選項,您將不會收到此聊天室的通知。"</string>
<string name="screen_room_notification_settings_mode_all_messages">"所有訊息"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"僅限提及與關鍵字"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"在此聊天適中,通知我"</string>
<string name="screen_room_roles_and_permissions_admins">"管理員"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"管理員與擁有者"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"變更我的身份"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"降級為普通成員"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"降級為版主"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"成員管理"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"訊息與內容"</string>
<string name="screen_room_roles_and_permissions_moderators">"版主"</string>
<string name="screen_room_roles_and_permissions_owners">"擁有者"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"權限"</string>
<string name="screen_room_roles_and_permissions_reset">"重設權限"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"重設之後,您會遺失當前的設定。"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"確定要重設權限嗎?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"身份"</string>
<string name="screen_room_roles_and_permissions_room_details">"聊天室資訊"</string>
<string name="screen_room_roles_and_permissions_title">"角色與權限"</string>
<string name="screen_security_and_privacy_add_room_address_action">"新增地址"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"所有人都必須申請存取權。"</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"要求加入"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"是的,啟用加密"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"啟用後就無法停用聊天室的加密,只有受邀的聊天室成員或加入聊天室後才能看到訊息歷史紀錄。
除了聊天室成員以外,任何人都不能讀取訊息。這可能會讓機器人與橋接無法正常運作。
我們不建議對任何人都可以找到並加入的聊天室啟用加密。"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"啟用加密?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"一旦啟用就無法停用加密。"</string>
<string name="screen_security_and_privacy_encryption_section_header">"加密"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"啟用端到端加密"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"任何人都可以加入。"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"任何人"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"僅受邀者才能加入。"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"僅限邀請"</string>
<string name="screen_security_and_privacy_room_access_section_header">"存取權"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"空間成員"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"目前不支援空間"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"您需要地址才能在公開目錄中顯示。"</string>
<string name="screen_security_and_privacy_room_address_section_header">"地址"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"允許透過搜尋 %1$s 公開聊天室目錄找到此聊天室"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"允許其他人透過公開目錄找到。"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"在公開目錄中可見"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"任何人"</string>
<string name="screen_security_and_privacy_room_history_section_header">"誰可以讀取歷史紀錄"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"僅在成員被邀請後"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"選取此選項後僅限成員"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"聊天室地址是尋找與存取聊天室的方法。也確保您可以輕鬆與其他人分享聊天室。
您可以選擇在家伺服器公開聊天室目錄中發佈您的聊天室。"</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"聊天室發佈"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"能見度"</string>
<string name="screen_security_and_privacy_title">"安全與隱私"</string>
</resources>

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"你需要房间地址才能使其在目录中可见。"</string>
<string name="screen_edit_room_address_title">"房间地址"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"更新通知设置时出错。"</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"服务器在加密聊天室中不支持此选项,因此在某些聊天室可能无法收到通知。"</string>
<string name="screen_polls_history_title">"投票"</string>
<string name="screen_room_change_permissions_administrators">"仅限管理员"</string>
<string name="screen_room_change_permissions_ban_people">"封禁成员"</string>
<string name="screen_room_change_permissions_delete_messages">"移除消息"</string>
<string name="screen_room_change_permissions_invite_people">"邀请他人及接受加入请求"</string>
<string name="screen_room_change_permissions_messages_and_content">"消息和内容"</string>
<string name="screen_room_change_permissions_moderators">"管理员和协管员"</string>
<string name="screen_room_change_permissions_remove_people">"移除成员及拒绝加入请求"</string>
<string name="screen_room_change_permissions_room_avatar">"更改聊天室头像"</string>
<string name="screen_room_change_permissions_room_details">"编辑聊天室"</string>
<string name="screen_room_change_permissions_room_name">"更改聊天室名称"</string>
<string name="screen_room_change_permissions_room_topic">"更改聊天室主题"</string>
<string name="screen_room_change_permissions_send_messages">"发送消息"</string>
<string name="screen_room_change_role_administrators_title">"编辑管理员"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"您将无法撤消此操作。您正在提升用户的权限,使其拥有与您平权。"</string>
<string name="screen_room_change_role_confirm_add_admin_title">"添加管理员?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"此操作无法撤销。您正在将所有权转移给所选用户。一旦离开此界面,该操作将永久生效。"</string>
<string name="screen_room_change_role_confirm_change_owners_title">"转让所有权"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"降级"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"您正在降级,此更改将无法撤消。如果您是聊天室中的最后一个特权用户,则无法重新获得权限。"</string>
<string name="screen_room_change_role_confirm_demote_self_title">"降级自己?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s待处理"</string>
<string name="screen_room_change_role_invited_member_name_android">"(已邀请)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"管理员自动拥有协管员权限"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"所有者自动拥有管理员权限。"</string>
<string name="screen_room_change_role_moderators_title">"编辑协管员"</string>
<string name="screen_room_change_role_owners_title">"选择所有者"</string>
<string name="screen_room_change_role_section_administrators">"管理员"</string>
<string name="screen_room_change_role_section_moderators">"协管员"</string>
<string name="screen_room_change_role_section_users">"成员"</string>
<string name="screen_room_change_role_unsaved_changes_description">"您有未保存的更改。"</string>
<string name="screen_room_change_role_unsaved_changes_title">"保存更改?"</string>
<string name="screen_room_details_add_topic_title">"添加主题"</string>
<string name="screen_room_details_badge_encrypted">"加密的"</string>
<string name="screen_room_details_badge_not_encrypted">"未加密的"</string>
<string name="screen_room_details_badge_public">"公共聊天室"</string>
<string name="screen_room_details_edit_room_title">"编辑聊天室"</string>
<string name="screen_room_details_edition_error">"出现未知错误,无法更改信息。"</string>
<string name="screen_room_details_edition_error_title">"无法更新聊天室"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"消息已加密,只有你和消息接收者拥有唯一解密密钥。"</string>
<string name="screen_room_details_encryption_enabled_title">"消息加密已启用"</string>
<string name="screen_room_details_error_loading_notification_settings">"加载通知设置时出错。"</string>
<string name="screen_room_details_error_muting">"无法将此聊天室静音,请重试。"</string>
<string name="screen_room_details_error_unmuting">"无法取消此聊天室的静音,请重试。"</string>
<string name="screen_room_details_invite_people_dont_close">"完成之前请勿关闭应用程序。"</string>
<string name="screen_room_details_invite_people_preparing">"准备邀请…"</string>
<string name="screen_room_details_invite_people_title">"邀请朋友"</string>
<string name="screen_room_details_leave_conversation_title">"离开聊天"</string>
<string name="screen_room_details_leave_room_title">"离开聊天室"</string>
<string name="screen_room_details_media_gallery_title">"媒体和文件"</string>
<string name="screen_room_details_notification_mode_custom">"自定义"</string>
<string name="screen_room_details_notification_mode_default">"默认"</string>
<string name="screen_room_details_notification_title">"通知"</string>
<string name="screen_room_details_pinned_events_row_title">"置顶消息"</string>
<string name="screen_room_details_profile_row_title">"个人资料"</string>
<string name="screen_room_details_requests_to_join_title">"申请加入"</string>
<string name="screen_room_details_roles_and_permissions">"角色与权限"</string>
<string name="screen_room_details_room_name_label">"聊天室名称"</string>
<string name="screen_room_details_security_and_privacy_title">"安全与隐私"</string>
<string name="screen_room_details_security_title">"安全"</string>
<string name="screen_room_details_share_room_title">"分享聊天室"</string>
<string name="screen_room_details_title">"聊天室信息"</string>
<string name="screen_room_details_topic_title">"主题"</string>
<string name="screen_room_details_updating_room">"正在更新聊天室……"</string>
<string name="screen_room_member_list_banned_empty">"没有被封禁的用户。"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="other">"%1$d 人"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"移除并封禁成员"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"仅移除成员"</string>
<string name="screen_room_member_list_manage_member_unban_action">"取消封禁"</string>
<string name="screen_room_member_list_manage_member_unban_message">"如果受到邀请,他们可以重新加入聊天室。"</string>
<string name="screen_room_member_list_manage_member_unban_title">"从房间取消解封"</string>
<string name="screen_room_member_list_mode_banned">"已封禁用户"</string>
<string name="screen_room_member_list_mode_members">"成员"</string>
<string name="screen_room_member_list_role_administrator">"仅限管理员"</string>
<string name="screen_room_member_list_role_moderator">"管理员和协管员"</string>
<string name="screen_room_member_list_role_owner">"所有者"</string>
<string name="screen_room_member_list_room_members_header_title">"聊天室成员"</string>
<string name="screen_room_member_list_unbanning_user">"解除封禁 %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"允许自定义设置"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"开启此功能将覆盖您的默认设置"</string>
<string name="screen_room_notification_settings_custom_settings_title">"在此聊天中通知我以下内容"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"你可以在你的 %1$s 中更改这一项。"</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"全局设置"</string>
<string name="screen_room_notification_settings_default_setting_title">"默认设置"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"撤销独立设置"</string>
<string name="screen_room_notification_settings_error_loading_settings">"加载通知设置时出错。"</string>
<string name="screen_room_notification_settings_error_restoring_default">"恢复默认模式失败,请重试。"</string>
<string name="screen_room_notification_settings_error_setting_mode">"设置模式失败,请重试。"</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"服务器在加密聊天室中不支持此选项,无法在此聊天室收到通知。"</string>
<string name="screen_room_notification_settings_mode_all_messages">"全部消息"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"仅限提及和关键词"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"在这个聊天室,通知我:"</string>
<string name="screen_room_roles_and_permissions_admins">"管理员"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"管理员和所有者"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"更改我的角色"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"降级为成员"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"降级为协管员"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"成员权限"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"消息和内容"</string>
<string name="screen_room_roles_and_permissions_moderators">"协管员"</string>
<string name="screen_room_roles_and_permissions_owners">"所有者"</string>
<string name="screen_room_roles_and_permissions_reset">"重置权限"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"重置权限后,您将丢失当前设置。"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"重置权限?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"角色"</string>
<string name="screen_room_roles_and_permissions_room_details">"聊天室详情"</string>
<string name="screen_room_roles_and_permissions_title">"角色与权限"</string>
<string name="screen_security_and_privacy_add_room_address_action">"添加房间地址"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"任何人都可以请求加入房间,但必须由管理员或版主接受请求。"</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"请求加入"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"是的,启用加密"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"一旦启用,就不能再禁用房间的加密功能。消息历史记录只能在房间成员被邀请或加入房间后才可见。
除房间成员外,任何人都无法阅读信息。这可能会妨碍机器人和网桥正常工作。
我们不建议对任何人都能找到并加入的房间启用加密。"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"启用加密?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"加密一旦启用,就无法禁用。"</string>
<string name="screen_security_and_privacy_encryption_section_header">"加密"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"启用端到端加密"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"任何人都可以找到并加入"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"任何人"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"只有受邀者才能加入"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"仅限邀请"</string>
<string name="screen_security_and_privacy_room_access_section_header">"房间访问权限"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"空间成员"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"目前不支持空间"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"你需要房间地址才能使其在目录中可见。"</string>
<string name="screen_security_and_privacy_room_address_section_header">"房间地址"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"允许通过搜索 %1$s 的公共房间目录来发现此房间"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"在公共房间目录中可见"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"任何人"</string>
<string name="screen_security_and_privacy_room_history_section_header">"谁可以读取历史记录"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"仅限被邀请的成员"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"仅自选择此选项以来的成员"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"房间地址是查找和访问房间的方式。这也确保你可以轻松地向他人分享房间。
你可以选择在你服务器的公共房间目录中发布你的房间。"</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"房间发布"</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"房间可见性"</string>
<string name="screen_security_and_privacy_title">"安全与隐私"</string>
</resources>

View File

@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_edit_room_address_room_address_section_footer">"Youll need an address in order to make it visible in the public directory."</string>
<string name="screen_edit_room_address_title">"Edit address"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"An error occurred while updating the notification setting."</string>
<string name="screen_notification_settings_mentions_only_disclaimer">"Your homeserver does not support this option in encrypted rooms, you may not get notified in some rooms."</string>
<string name="screen_polls_history_title">"Polls"</string>
<string name="screen_room_change_permissions_administrators">"Admin"</string>
<string name="screen_room_change_permissions_ban_people">"Ban people"</string>
<string name="screen_room_change_permissions_delete_messages">"Remove messages"</string>
<string name="screen_room_change_permissions_everyone">"Member"</string>
<string name="screen_room_change_permissions_invite_people">"Invite people"</string>
<string name="screen_room_change_permissions_member_moderation">"Manage members"</string>
<string name="screen_room_change_permissions_messages_and_content">"Messages and content"</string>
<string name="screen_room_change_permissions_moderators">"Moderator"</string>
<string name="screen_room_change_permissions_remove_people">"Remove people"</string>
<string name="screen_room_change_permissions_room_avatar">"Change avatar"</string>
<string name="screen_room_change_permissions_room_details">"Edit details"</string>
<string name="screen_room_change_permissions_room_name">"Change name"</string>
<string name="screen_room_change_permissions_room_topic">"Change topic"</string>
<string name="screen_room_change_permissions_send_messages">"Send messages"</string>
<string name="screen_room_change_role_administrators_title">"Edit Admins"</string>
<string name="screen_room_change_role_confirm_add_admin_description">"You will not be able to undo this action. You are promoting the user to have the same power level as you."</string>
<string name="screen_room_change_role_confirm_add_admin_title">"Add Admin?"</string>
<string name="screen_room_change_role_confirm_change_owners_description">"You will not be able to undo this action. You are transferring the ownership to the selected users. Once you leave this will be permanent."</string>
<string name="screen_room_change_role_confirm_change_owners_title">"Transfer ownership?"</string>
<string name="screen_room_change_role_confirm_demote_self_action">"Demote"</string>
<string name="screen_room_change_role_confirm_demote_self_description">"You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges."</string>
<string name="screen_room_change_role_confirm_demote_self_title">"Demote yourself?"</string>
<string name="screen_room_change_role_invited_member_name">"%1$s (Pending)"</string>
<string name="screen_room_change_role_invited_member_name_android">"(Pending)"</string>
<string name="screen_room_change_role_moderators_admin_section_footer">"Admins automatically have moderator privileges"</string>
<string name="screen_room_change_role_moderators_owner_section_footer">"Owners automatically have admin privileges."</string>
<string name="screen_room_change_role_moderators_title">"Edit Moderators"</string>
<string name="screen_room_change_role_owners_title">"Choose Owners"</string>
<string name="screen_room_change_role_section_administrators">"Admins"</string>
<string name="screen_room_change_role_section_moderators">"Moderators"</string>
<string name="screen_room_change_role_section_users">"Members"</string>
<string name="screen_room_change_role_unsaved_changes_description">"You have unsaved changes."</string>
<string name="screen_room_change_role_unsaved_changes_title">"Save changes?"</string>
<string name="screen_room_details_add_topic_title">"Add topic"</string>
<string name="screen_room_details_badge_encrypted">"Encrypted"</string>
<string name="screen_room_details_badge_not_encrypted">"Not encrypted"</string>
<string name="screen_room_details_badge_public">"Public room"</string>
<string name="screen_room_details_edit_room_title">"Edit details"</string>
<string name="screen_room_details_edition_error">"There was an unknown error and the information couldn\'t be changed."</string>
<string name="screen_room_details_edition_error_title">"Unable to update room"</string>
<string name="screen_room_details_encryption_enabled_subtitle">"Messages are secured with locks. Only you and the recipients have the unique keys to unlock them."</string>
<string name="screen_room_details_encryption_enabled_title">"Message encryption enabled"</string>
<string name="screen_room_details_error_loading_notification_settings">"An error occurred when loading notification settings."</string>
<string name="screen_room_details_error_muting">"Failed muting this room, please try again."</string>
<string name="screen_room_details_error_unmuting">"Failed unmuting this room, please try again."</string>
<string name="screen_room_details_invite_people_dont_close">"Don\'t close the app until finished."</string>
<string name="screen_room_details_invite_people_preparing">"Preparing invitations…"</string>
<string name="screen_room_details_invite_people_title">"Invite people"</string>
<string name="screen_room_details_leave_conversation_title">"Leave conversation"</string>
<string name="screen_room_details_leave_room_title">"Leave room"</string>
<string name="screen_room_details_media_gallery_title">"Media and files"</string>
<string name="screen_room_details_notification_mode_custom">"Custom"</string>
<string name="screen_room_details_notification_mode_default">"Default"</string>
<string name="screen_room_details_notification_title">"Notifications"</string>
<string name="screen_room_details_pinned_events_row_title">"Pinned messages"</string>
<string name="screen_room_details_profile_row_title">"Profile"</string>
<string name="screen_room_details_requests_to_join_title">"Requests to join"</string>
<string name="screen_room_details_roles_and_permissions">"Roles &amp; permissions"</string>
<string name="screen_room_details_room_name_label">"Room name"</string>
<string name="screen_room_details_security_and_privacy_title">"Security &amp; privacy"</string>
<string name="screen_room_details_security_title">"Security"</string>
<string name="screen_room_details_share_room_title">"Share room"</string>
<string name="screen_room_details_title">"Room info"</string>
<string name="screen_room_details_topic_title">"Topic"</string>
<string name="screen_room_details_updating_room">"Updating room…"</string>
<string name="screen_room_member_list_banned_empty">"There are no banned users."</string>
<plurals name="screen_room_member_list_banned_header_title">
<item quantity="one">"%1$d Banned"</item>
<item quantity="other">"%1$d Banned"</item>
</plurals>
<string name="screen_room_member_list_empty_search_subtitle">"Check the spelling or try a new search"</string>
<string name="screen_room_member_list_empty_search_title">"No results for “%1$s”"</string>
<plurals name="screen_room_member_list_header_title">
<item quantity="one">"%1$d Person"</item>
<item quantity="other">"%1$d People"</item>
</plurals>
<string name="screen_room_member_list_manage_member_remove_confirmation_ban">"Ban user"</string>
<string name="screen_room_member_list_manage_member_remove_confirmation_kick">"Only remove member"</string>
<string name="screen_room_member_list_manage_member_unban_action">"Unban"</string>
<string name="screen_room_member_list_manage_member_unban_message">"They will be able to join this room again if invited."</string>
<string name="screen_room_member_list_manage_member_unban_title">"Unban user"</string>
<string name="screen_room_member_list_mode_banned">"Banned"</string>
<string name="screen_room_member_list_mode_members">"Members"</string>
<plurals name="screen_room_member_list_pending_header_title">
<item quantity="one">"%1$d Invited"</item>
<item quantity="other">"%1$d Invited"</item>
</plurals>
<string name="screen_room_member_list_pending_status">"Pending"</string>
<string name="screen_room_member_list_role_administrator">"Admin"</string>
<string name="screen_room_member_list_role_moderator">"Moderator"</string>
<string name="screen_room_member_list_role_owner">"Owner"</string>
<string name="screen_room_member_list_room_members_header_title">"Room members"</string>
<string name="screen_room_member_list_unbanning_user">"Unbanning %1$s"</string>
<string name="screen_room_notification_settings_allow_custom">"Allow custom setting"</string>
<string name="screen_room_notification_settings_allow_custom_footnote">"Turning this on will override your default setting"</string>
<string name="screen_room_notification_settings_custom_settings_title">"Notify me in this chat for"</string>
<string name="screen_room_notification_settings_default_setting_footnote">"You can change it in your %1$s."</string>
<string name="screen_room_notification_settings_default_setting_footnote_content_link">"global settings"</string>
<string name="screen_room_notification_settings_default_setting_title">"Default setting"</string>
<string name="screen_room_notification_settings_edit_remove_setting">"Remove custom setting"</string>
<string name="screen_room_notification_settings_error_loading_settings">"An error occurred while loading notification settings."</string>
<string name="screen_room_notification_settings_error_restoring_default">"Failed restoring the default mode, please try again."</string>
<string name="screen_room_notification_settings_error_setting_mode">"Failed setting the mode, please try again."</string>
<string name="screen_room_notification_settings_mentions_only_disclaimer">"Your homeserver does not support this option in encrypted rooms, you won\'t get notified in this room."</string>
<string name="screen_room_notification_settings_mode_all_messages">"All messages"</string>
<string name="screen_room_notification_settings_mode_mentions_and_keywords">"Mentions and Keywords only"</string>
<string name="screen_room_notification_settings_room_custom_settings_title">"In this room, notify me for"</string>
<string name="screen_room_roles_and_permissions_admins">"Admins"</string>
<string name="screen_room_roles_and_permissions_admins_and_owners">"Admins and owners"</string>
<string name="screen_room_roles_and_permissions_change_my_role">"Change my role"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_member">"Demote to member"</string>
<string name="screen_room_roles_and_permissions_change_role_demote_to_moderator">"Demote to moderator"</string>
<string name="screen_room_roles_and_permissions_member_moderation">"Member moderation"</string>
<string name="screen_room_roles_and_permissions_messages_and_content">"Messages and content"</string>
<string name="screen_room_roles_and_permissions_moderators">"Moderators"</string>
<string name="screen_room_roles_and_permissions_owners">"Owners"</string>
<string name="screen_room_roles_and_permissions_permissions_header">"Permissions"</string>
<string name="screen_room_roles_and_permissions_reset">"Reset permissions"</string>
<string name="screen_room_roles_and_permissions_reset_confirm_description">"Once you reset permissions, you will lose the current settings."</string>
<string name="screen_room_roles_and_permissions_reset_confirm_title">"Reset permissions?"</string>
<string name="screen_room_roles_and_permissions_roles_header">"Roles"</string>
<string name="screen_room_roles_and_permissions_room_details">"Room details"</string>
<string name="screen_room_roles_and_permissions_title">"Roles &amp; permissions"</string>
<string name="screen_security_and_privacy_add_room_address_action">"Add address"</string>
<string name="screen_security_and_privacy_ask_to_join_option_description">"Everyone must request access."</string>
<string name="screen_security_and_privacy_ask_to_join_option_title">"Ask to join"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_confirm_button_title">"Yes, enable encryption"</string>
<string name="screen_security_and_privacy_enable_encryption_alert_description">"Once enabled, encryption for a room cannot be disabled, Message history will only be visible for room members since they were invited or since they joined the room.
No one besides the room members will be able to read messages. This may prevent bots and bridges to work correctly.
We do not recommend enabling encryption for rooms that anyone can find and join."</string>
<string name="screen_security_and_privacy_enable_encryption_alert_title">"Enable encryption?"</string>
<string name="screen_security_and_privacy_encryption_section_footer">"Once enabled, encryption cannot be disabled."</string>
<string name="screen_security_and_privacy_encryption_section_header">"Encryption"</string>
<string name="screen_security_and_privacy_encryption_toggle_title">"Enable end-to-end encryption"</string>
<string name="screen_security_and_privacy_room_access_anyone_option_description">"Anyone can join."</string>
<string name="screen_security_and_privacy_room_access_anyone_option_title">"Anyone"</string>
<string name="screen_security_and_privacy_room_access_footer">"Choose which spaces members can join this room without an invitation. %1$s"</string>
<string name="screen_security_and_privacy_room_access_footer_manage_spaces_action">"Manage spaces"</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_description">"Only invited people can join."</string>
<string name="screen_security_and_privacy_room_access_invite_only_option_title">"Invite only"</string>
<string name="screen_security_and_privacy_room_access_section_header">"Access"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_multiple_parents_description">"Anyone in authorized spaces can join."</string>
<string name="screen_security_and_privacy_room_access_space_members_option_single_parent_description">"Anyone in %1$s can join."</string>
<string name="screen_security_and_privacy_room_access_space_members_option_title">"Space members"</string>
<string name="screen_security_and_privacy_room_access_space_members_option_unavailable_description">"Spaces are not currently supported"</string>
<string name="screen_security_and_privacy_room_address_section_footer">"Youll need an address in order to make it visible in the public directory."</string>
<string name="screen_security_and_privacy_room_address_section_header">"Address"</string>
<string name="screen_security_and_privacy_room_directory_visibility_section_footer">"Allow for this room to be found by searching %1$s public room directory"</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_description">"Allow to be found by searching the public directory."</string>
<string name="screen_security_and_privacy_room_directory_visibility_toggle_title">"Visible in public directory"</string>
<string name="screen_security_and_privacy_room_history_anyone_option_title">"Anyone"</string>
<string name="screen_security_and_privacy_room_history_section_header">"Who can read history"</string>
<string name="screen_security_and_privacy_room_history_since_invite_option_title">"Members only since they were invited"</string>
<string name="screen_security_and_privacy_room_history_since_selecting_option_title">"Members only since selecting this option"</string>
<string name="screen_security_and_privacy_room_publishing_section_footer">"Room addresses are ways to find and access rooms. This also ensures you can easily share your room with others.
You can choose to publish your room in your homeserver public room directory."</string>
<string name="screen_security_and_privacy_room_publishing_section_header">"Room publishing"</string>
<string name="screen_security_and_privacy_room_visibility_section_footer">"Addresses are a way to find and access rooms and spaces. This also ensures you can easily share them with others."</string>
<string name="screen_security_and_privacy_room_visibility_section_header">"Visibility"</string>
<string name="screen_security_and_privacy_title">"Security &amp; privacy"</string>
</resources>

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* 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.roomdetails.impl
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.testing.junit4.util.MainDispatcherRule
import com.google.common.truth.Truth.assertThat
import io.element.android.features.call.test.FakeElementCallEntryPoint
import io.element.android.features.changeroommemberroles.test.FakeChangeRoomMemberRolesEntryPoint
import io.element.android.features.changeroommemberroles.test.FakeRolesAndPermissionsEntryPoint
import io.element.android.features.knockrequests.test.FakeKnockRequestsListEntryPoint
import io.element.android.features.messages.test.FakeMessagesEntryPoint
import io.element.android.features.poll.test.history.FakePollHistoryEntryPoint
import io.element.android.features.reportroom.test.FakeReportRoomEntryPoint
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
import io.element.android.features.securityandprivacy.test.FakeSecurityAndPrivacyEntryPoint
import io.element.android.features.verifysession.test.FakeOutgoingVerificationEntryPoint
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.mediaviewer.test.FakeMediaGalleryEntryPoint
import io.element.android.libraries.mediaviewer.test.FakeMediaViewerEntryPoint
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.node.TestParentNode
import org.junit.Rule
import org.junit.Test
class DefaultRoomDetailsEntryPointTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
@Test
fun `test node builder`() {
val entryPoint = DefaultRoomDetailsEntryPoint()
val parentNode = TestParentNode.create { buildContext, plugins ->
RoomDetailsFlowNode(
buildContext = buildContext,
plugins = plugins,
pollHistoryEntryPoint = FakePollHistoryEntryPoint(),
elementCallEntryPoint = FakeElementCallEntryPoint(),
room = FakeJoinedRoom(),
analyticsService = FakeAnalyticsService(),
messagesEntryPoint = FakeMessagesEntryPoint(),
knockRequestsListEntryPoint = FakeKnockRequestsListEntryPoint(),
mediaViewerEntryPoint = FakeMediaViewerEntryPoint(),
mediaGalleryEntryPoint = FakeMediaGalleryEntryPoint(),
outgoingVerificationEntryPoint = FakeOutgoingVerificationEntryPoint(),
reportRoomEntryPoint = FakeReportRoomEntryPoint(),
changeRoomMemberRolesEntryPoint = FakeChangeRoomMemberRolesEntryPoint(),
rolesAndPermissionsEntryPoint = FakeRolesAndPermissionsEntryPoint(),
securityAndPrivacyEntryPoint = FakeSecurityAndPrivacyEntryPoint(),
)
}
val callback = object : RoomDetailsEntryPoint.Callback {
override fun navigateToGlobalNotificationSettings() = lambdaError()
override fun navigateToRoom(roomId: RoomId, serverNames: List<String>) = lambdaError()
override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError()
override fun startForwardEventFlow(eventId: EventId, fromPinnedEvents: Boolean) = lambdaError()
}
val params = RoomDetailsEntryPoint.Params(
initialElement = RoomDetailsEntryPoint.InitialTarget.RoomDetails,
)
val result = entryPoint.createNode(
parentNode = parentNode,
buildContext = BuildContext.root(null),
params = params,
callback = callback,
)
assertThat(result).isInstanceOf(RoomDetailsFlowNode::class.java)
assertThat(result.plugins).contains(params)
assertThat(result.plugins).contains(callback)
}
@Test
fun `test initial target to nav target mapping`() {
assertThat(RoomDetailsEntryPoint.InitialTarget.RoomDetails.toNavTarget())
.isEqualTo(RoomDetailsFlowNode.NavTarget.RoomDetails)
assertThat(RoomDetailsEntryPoint.InitialTarget.RoomMemberDetails(A_USER_ID).toNavTarget())
.isEqualTo(RoomDetailsFlowNode.NavTarget.RoomMemberDetails(A_USER_ID))
assertThat(RoomDetailsEntryPoint.InitialTarget.RoomNotificationSettings.toNavTarget())
.isEqualTo(RoomDetailsFlowNode.NavTarget.RoomNotificationSettings(showUserDefinedSettingStyle = true))
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 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.roomdetails.impl
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
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.StateEventType
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_ROOM_TOPIC
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.lambda.lambdaError
fun aRoom(
sessionId: SessionId = A_SESSION_ID,
roomId: RoomId = A_ROOM_ID,
displayName: String = A_ROOM_NAME,
rawName: String? = displayName,
topic: String? = A_ROOM_TOPIC,
avatarUrl: String? = AN_AVATAR_URL,
canonicalAlias: RoomAlias? = A_ROOM_ALIAS,
isEncrypted: Boolean = true,
isPublic: Boolean = true,
isDirect: Boolean = false,
joinRule: JoinRule? = null,
activeMemberCount: Long = 1,
joinedMemberCount: Long = 1,
invitedMemberCount: Long = 0,
canInviteResult: (UserId) -> Result<Boolean> = { lambdaError() },
canBanResult: (UserId) -> Result<Boolean> = { lambdaError() },
canKickResult: (UserId) -> Result<Boolean> = { lambdaError() },
canSendStateResult: (UserId, StateEventType) -> Result<Boolean> = { _, _ -> lambdaError() },
userDisplayNameResult: (UserId) -> Result<String?> = { lambdaError() },
userAvatarUrlResult: () -> Result<String?> = { lambdaError() },
canUserJoinCallResult: (UserId) -> Result<Boolean> = { lambdaError() },
getUpdatedMemberResult: (UserId) -> Result<RoomMember> = { lambdaError() },
userRoleResult: () -> Result<RoomMember.Role> = { lambdaError() },
setIsFavoriteResult: (Boolean) -> Result<Unit> = { lambdaError() },
) = FakeBaseRoom(
sessionId = sessionId,
roomId = roomId,
canInviteResult = canInviteResult,
canBanResult = canBanResult,
canKickResult = canKickResult,
canSendStateResult = canSendStateResult,
userDisplayNameResult = userDisplayNameResult,
userAvatarUrlResult = userAvatarUrlResult,
canUserJoinCallResult = canUserJoinCallResult,
getUpdatedMemberResult = getUpdatedMemberResult,
userRoleResult = userRoleResult,
setIsFavoriteResult = setIsFavoriteResult,
initialRoomInfo = aRoomInfo(
name = displayName,
rawName = rawName,
topic = topic,
avatarUrl = avatarUrl,
canonicalAlias = canonicalAlias,
isDirect = isDirect,
isPublic = isPublic,
isEncrypted = isEncrypted,
joinRule = joinRule,
joinedMembersCount = joinedMemberCount,
activeMembersCount = activeMemberCount,
invitedMembersCount = invitedMemberCount,
)
)
fun aJoinedRoom(
sessionId: SessionId = A_SESSION_ID,
roomId: RoomId = A_ROOM_ID,
displayName: String = A_ROOM_NAME,
rawName: String? = displayName,
topic: String? = A_ROOM_TOPIC,
avatarUrl: String? = AN_AVATAR_URL,
canonicalAlias: RoomAlias? = A_ROOM_ALIAS,
isEncrypted: Boolean = true,
isPublic: Boolean = true,
isDirect: Boolean = false,
joinRule: JoinRule? = null,
activeMemberCount: Long = 1,
joinedMemberCount: Long = 1,
invitedMemberCount: Long = 0,
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
canInviteResult: (UserId) -> Result<Boolean> = { lambdaError() },
canBanResult: (UserId) -> Result<Boolean> = { lambdaError() },
canKickResult: (UserId) -> Result<Boolean> = { lambdaError() },
canSendStateResult: (UserId, StateEventType) -> Result<Boolean> = { _, _ -> lambdaError() },
userDisplayNameResult: (UserId) -> Result<String?> = { lambdaError() },
userAvatarUrlResult: () -> Result<String?> = { lambdaError() },
setNameResult: (String) -> Result<Unit> = { lambdaError() },
setTopicResult: (String) -> Result<Unit> = { lambdaError() },
updateAvatarResult: (String, ByteArray) -> Result<Unit> = { _, _ -> lambdaError() },
removeAvatarResult: () -> Result<Unit> = { lambdaError() },
canUserJoinCallResult: (UserId) -> Result<Boolean> = { lambdaError() },
getUpdatedMemberResult: (UserId) -> Result<RoomMember> = { lambdaError() },
userRoleResult: () -> Result<RoomMember.Role> = { lambdaError() },
kickUserResult: (UserId, String?) -> Result<Unit> = { _, _ -> lambdaError() },
banUserResult: (UserId, String?) -> Result<Unit> = { _, _ -> lambdaError() },
unBanUserResult: (UserId, String?) -> Result<Unit> = { _, _ -> lambdaError() },
updateCanonicalAliasResult: (RoomAlias?, List<RoomAlias>) -> Result<Unit> = { _, _ -> lambdaError() },
publishRoomAliasInRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
removeRoomAliasFromRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
setIsFavoriteResult: (Boolean) -> Result<Unit> = { lambdaError() },
) = FakeJoinedRoom(
roomNotificationSettingsService = notificationSettingsService,
setNameResult = setNameResult,
setTopicResult = setTopicResult,
updateAvatarResult = updateAvatarResult,
removeAvatarResult = removeAvatarResult,
kickUserResult = kickUserResult,
banUserResult = banUserResult,
unBanUserResult = unBanUserResult,
updateCanonicalAliasResult = updateCanonicalAliasResult,
publishRoomAliasInRoomDirectoryResult = publishRoomAliasInRoomDirectoryResult,
removeRoomAliasFromRoomDirectoryResult = removeRoomAliasFromRoomDirectoryResult,
baseRoom = aRoom(
sessionId = sessionId,
roomId = roomId,
canInviteResult = canInviteResult,
canBanResult = canBanResult,
canKickResult = canKickResult,
canSendStateResult = canSendStateResult,
userDisplayNameResult = userDisplayNameResult,
userAvatarUrlResult = userAvatarUrlResult,
canUserJoinCallResult = canUserJoinCallResult,
getUpdatedMemberResult = getUpdatedMemberResult,
userRoleResult = userRoleResult,
setIsFavoriteResult = setIsFavoriteResult,
displayName = displayName,
rawName = rawName,
topic = topic,
avatarUrl = avatarUrl,
canonicalAlias = canonicalAlias,
isDirect = isDirect,
isPublic = isPublic,
isEncrypted = isEncrypted,
joinRule = joinRule,
joinedMemberCount = joinedMemberCount,
activeMemberCount = activeMemberCount,
invitedMemberCount = invitedMemberCount,
)
)

View File

@@ -0,0 +1,747 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl
import androidx.lifecycle.Lifecycle
import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.roomcall.api.aStandByCallState
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.features.userprofile.shared.aUserProfileState
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
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.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_ROOM_TOPIC
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.FakeLifecycleOwner
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.testCoroutineDispatchers
import io.element.android.tests.testutils.testWithLifecycleOwner
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import kotlin.time.Duration.Companion.milliseconds
@Suppress("LargeClass")
@ExperimentalCoroutinesApi
class RoomDetailsPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
private val fakeLifecycleOwner = FakeLifecycleOwner().apply {
givenState(Lifecycle.State.RESUMED)
}
private fun TestScope.createRoomDetailsPresenter(
room: JoinedRoom = aJoinedRoom(),
leaveRoomState: LeaveRoomState = aLeaveRoomState(),
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
analyticsService: AnalyticsService = FakeAnalyticsService(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(
mapOf(
FeatureFlags.Knock.key to false,
)
),
encryptionService: FakeEncryptionService = FakeEncryptionService(),
clipboardHelper: ClipboardHelper = FakeClipboardHelper(),
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore()
): RoomDetailsPresenter {
val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService)
val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory {
override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter {
return RoomMemberDetailsPresenter(
roomMemberId = roomMemberId,
room = room,
userProfilePresenterFactory = {
Presenter { aUserProfileState() }
},
encryptionService = encryptionService,
clipboardHelper = clipboardHelper,
)
}
}
return RoomDetailsPresenter(
client = matrixClient,
room = room,
featureFlagService = featureFlagService,
notificationSettingsService = matrixClient.notificationSettingsService,
roomMembersDetailsPresenterFactory = roomMemberDetailsPresenterFactory,
leaveRoomPresenter = { leaveRoomState },
roomCallStatePresenter = { aStandByCallState() },
dispatchers = dispatchers,
analyticsService = analyticsService,
clipboardHelper = clipboardHelper,
appPreferencesStore = appPreferencesStore,
)
}
@Test
fun `present - initial state is created from initial room info`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
val initialState = awaitItem()
assertThat(initialState.roomId).isEqualTo(room.roomId)
assertThat(initialState.roomName).isEqualTo(room.info().name)
assertThat(initialState.roomAvatarUrl).isEqualTo(room.info().avatarUrl)
assertThat(initialState.roomTopic).isEqualTo(RoomTopicState.ExistingTopic(room.info().topic!!))
assertThat(initialState.memberCount).isEqualTo(room.info().joinedMembersCount)
assertThat(initialState.pinnedMessagesCount).isEqualTo(0)
assertThat(initialState.canShowSecurityAndPrivacy).isFalse()
assertThat(initialState.showDebugInfo).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state is updated with a new roomInfo`() = runTest {
val roomInfo = aRoomInfo(
name = A_ROOM_NAME,
topic = A_ROOM_TOPIC,
avatarUrl = AN_AVATAR_URL,
pinnedEventIds = listOf(AN_EVENT_ID),
)
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
).apply {
givenRoomInfo(roomInfo)
}
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
skipItems(1)
val updatedState = awaitItem()
assertThat(updatedState.roomName).isEqualTo(roomInfo.name)
assertThat(updatedState.roomAvatarUrl).isEqualTo(roomInfo.avatarUrl)
assertThat(updatedState.roomTopic).isEqualTo(RoomTopicState.ExistingTopic(roomInfo.topic!!))
assertThat(updatedState.pinnedMessagesCount).isEqualTo(roomInfo.pinnedEventIds.size)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state with no room name`() = runTest {
val room = aJoinedRoom(
displayName = "",
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
val initialState = awaitItem()
assertThat(initialState.roomName).isEqualTo(room.info().name)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state with DM member sets custom DM roomType`() = runTest {
val myRoomMember = aRoomMember(A_SESSION_ID)
val otherRoomMember = aRoomMember(A_USER_ID_2)
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
getUpdatedMemberResult = { userId ->
when (userId) {
A_SESSION_ID -> Result.success(myRoomMember)
A_USER_ID_2 -> Result.success(otherRoomMember)
else -> lambdaError()
}
},
).apply {
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(RoomMembersState.Ready(roomMembers))
givenRoomInfo(
aRoomInfo(
isEncrypted = true,
isDirect = true,
)
)
}
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
val initialState = awaitItem()
assertThat(initialState.roomType).isEqualTo(
RoomDetailsType.Dm(
me = myRoomMember,
otherMember = otherRoomMember,
)
)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when user can invite others to room`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
// Initially false
assertThat(awaitItem().canInvite).isFalse()
// Then the asynchronous check completes and it becomes true
assertThat(awaitItem().canInvite).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when user can not invite others to room`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.success(false) },
canKickResult = { Result.success(false) },
canBanResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
assertThat(awaitItem().canInvite).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when canInvite errors`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.failure(RuntimeException("Whoops")) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
assertThat(awaitItem().canInvite).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when user can edit one attribute`() = runTest {
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC -> Result.success(true)
StateEventType.ROOM_NAME -> Result.success(false)
else -> Result.failure(RuntimeException("Whelp"))
}
},
canBanResult = { Result.success(false) },
canKickResult = { Result.success(false) },
canInviteResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
// Initially false
assertThat(awaitItem().canEdit).isFalse()
// Then the asynchronous check completes and it becomes true
assertThat(awaitItem().canEdit).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when user can edit attributes in a DM`() = runTest {
val myRoomMember = aRoomMember(A_SESSION_ID)
val otherRoomMember = aRoomMember(A_USER_ID_2)
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC,
StateEventType.ROOM_NAME,
StateEventType.ROOM_AVATAR -> Result.success(true)
else -> Result.failure(RuntimeException("Whelp"))
}
},
canKickResult = { Result.success(false) },
canBanResult = { Result.success(false) },
canInviteResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
getUpdatedMemberResult = { userId ->
when (userId) {
A_SESSION_ID -> Result.success(myRoomMember)
A_USER_ID_2 -> Result.success(otherRoomMember)
else -> lambdaError()
}
},
).apply {
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(RoomMembersState.Ready(roomMembers))
givenRoomInfo(
aRoomInfo(
isEncrypted = true,
isDirect = true,
)
)
}
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
// Initially false
assertThat(awaitItem().canEdit).isFalse()
// Then the asynchronous check completes, but editing is still disallowed because it's a DM
val settledState = awaitItem()
assertThat(settledState.canEdit).isFalse()
// If there is a topic, it's visible
assertThat(settledState.roomTopic).isEqualTo(RoomTopicState.ExistingTopic(room.info().topic!!))
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when in a DM with no topic`() = runTest {
val myRoomMember = aRoomMember(A_SESSION_ID)
val otherRoomMember = aRoomMember(A_USER_ID_2)
val room = aJoinedRoom(
isDirect = true,
topic = null,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_AVATAR,
StateEventType.ROOM_TOPIC,
StateEventType.ROOM_NAME -> Result.success(true)
else -> Result.failure(RuntimeException("Whelp"))
}
},
userDisplayNameResult = { Result.success(A_USER_NAME) },
userAvatarUrlResult = { Result.success(AN_AVATAR_URL) },
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
getUpdatedMemberResult = { userId ->
when (userId) {
A_SESSION_ID -> Result.success(myRoomMember)
A_USER_ID_2 -> Result.success(otherRoomMember)
else -> lambdaError()
}
},
).apply {
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(RoomMembersState.Ready(roomMembers))
givenRoomInfo(
aRoomInfo(
isDirect = true,
activeMembersCount = 2,
topic = null,
)
)
}
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
skipItems(2)
// There's no topic, so we hide the entire UI for DMs
assertThat(awaitItem().roomTopic).isEqualTo(RoomTopicState.Hidden)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when user can edit all attributes`() = runTest {
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC,
StateEventType.ROOM_NAME,
StateEventType.ROOM_AVATAR -> Result.success(true)
else -> Result.failure(RuntimeException("Whelp"))
}
},
canKickResult = {
Result.success(false)
},
canBanResult = {
Result.success(false)
},
canInviteResult = {
Result.success(false)
},
canUserJoinCallResult = { Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
// Initially false
assertThat(awaitItem().canEdit).isFalse()
// Then the asynchronous check completes and it becomes true
assertThat(awaitItem().canEdit).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state when user can edit no attributes`() = runTest {
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC,
StateEventType.ROOM_NAME,
StateEventType.ROOM_AVATAR -> Result.success(false)
else -> Result.failure(RuntimeException("Whelp"))
}
},
canBanResult = {
Result.success(false)
},
canKickResult = {
Result.success(false)
},
canInviteResult = {
Result.success(false)
},
canUserJoinCallResult = { Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
// Initially false, and no further events
assertThat(awaitItem().canEdit).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - topic state is hidden when no topic and user has no permission`() = runTest {
val room = aJoinedRoom(
topic = null,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_AVATAR,
StateEventType.ROOM_NAME -> Result.success(true)
StateEventType.ROOM_TOPIC -> Result.success(false)
else -> Result.failure(RuntimeException("Whelp"))
}
},
canKickResult = {
Result.success(false)
},
canBanResult = {
Result.success(false)
},
canInviteResult = {
Result.success(false)
},
canUserJoinCallResult = { Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
// The initial state is "hidden" and no further state changes happen
assertThat(awaitItem().roomTopic).isEqualTo(RoomTopicState.Hidden)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - topic state is 'can add topic' when no topic and user has permission`() = runTest {
val room = aJoinedRoom(
topic = null,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_AVATAR,
StateEventType.ROOM_TOPIC,
StateEventType.ROOM_NAME -> Result.success(true)
else -> Result.failure(RuntimeException("Whelp"))
}
},
canKickResult = {
Result.success(false)
},
canBanResult = {
Result.success(false)
},
canInviteResult = {
Result.success(false)
},
canUserJoinCallResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(topic = null))
}
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
// Ignore the initial state
skipItems(1)
// When the async permission check finishes, the topic state will be updated
assertThat(awaitItem().roomTopic).isEqualTo(RoomTopicState.CanAddTopic)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - leave room event is passed on to leave room presenter`() = runTest {
val leaveRoomEventRecorder = EventsRecorder<LeaveRoomEvent>()
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(
room = room,
leaveRoomState = aLeaveRoomState(eventSink = leaveRoomEventRecorder),
dispatchers = testCoroutineDispatchers()
)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
awaitItem().eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
leaveRoomEventRecorder.assertSingle(LeaveRoomEvent.LeaveRoom(room.roomId, needsConfirmation = true))
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - notification mode changes`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
val room = aJoinedRoom(
notificationSettingsService = notificationSettingsService,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(
room = room,
notificationSettingsService = notificationSettingsService,
)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
notificationSettingsService.setRoomNotificationMode(
room.roomId,
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
)
val updatedState = consumeItemsUntilPredicate {
it.roomNotificationSettings?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - mute room notifications`() = runTest {
val notificationSettingsService =
FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
val room = aJoinedRoom(
notificationSettingsService = notificationSettingsService,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(
room = room,
notificationSettingsService = notificationSettingsService
)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
awaitItem().eventSink(RoomDetailsEvent.MuteNotification)
val updatedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) {
it.roomNotificationSettings?.mode == RoomNotificationMode.MUTE
}.last()
assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(
RoomNotificationMode.MUTE
)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - unmute room notifications`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService(
initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES
)
val room = aJoinedRoom(
notificationSettingsService = notificationSettingsService,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(
room = room,
notificationSettingsService = notificationSettingsService
)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
awaitItem().eventSink(RoomDetailsEvent.UnmuteNotification)
val updatedState = consumeItemsUntilPredicate {
it.roomNotificationSettings?.mode == RoomNotificationMode.ALL_MESSAGES
}.last()
assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(
RoomNotificationMode.ALL_MESSAGES
)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - when set is favorite event is emitted, then the action is called`() = runTest {
val setIsFavoriteResult = lambdaRecorder<Boolean, Result<Unit>> { _ -> Result.success(Unit) }
val room = aJoinedRoom(
setIsFavoriteResult = setIsFavoriteResult,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val analyticsService = FakeAnalyticsService()
val presenter =
createRoomDetailsPresenter(room = room, analyticsService = analyticsService)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
val initialState = awaitItem()
initialState.eventSink(RoomDetailsEvent.SetFavorite(true))
setIsFavoriteResult.assertions().isCalledOnce().with(value(true))
initialState.eventSink(RoomDetailsEvent.SetFavorite(false))
setIsFavoriteResult.assertions().isCalledExactly(2)
.withSequence(
listOf(value(true)),
listOf(value(false)),
)
assertThat(analyticsService.capturedEvents).containsExactly(
Interaction(name = Interaction.Name.MobileRoomFavouriteToggle),
Interaction(name = Interaction.Name.MobileRoomFavouriteToggle)
)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - changes in room info updates the is favorite flag`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val presenter = createRoomDetailsPresenter(room = room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
room.givenRoomInfo(aRoomInfo(isFavorite = true))
consumeItemsUntilPredicate { it.isFavorite }.last().let { state ->
assertThat(state.isFavorite).isTrue()
}
room.givenRoomInfo(aRoomInfo(isFavorite = false))
consumeItemsUntilPredicate { !it.isFavorite }.last().let { state ->
assertThat(state.isFavorite).isFalse()
}
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - show knock requests`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
joinRule = JoinRule.Knock,
)
val featureFlagService = FakeFeatureFlagService(
mapOf(FeatureFlags.Knock.key to false)
)
val presenter = createRoomDetailsPresenter(
room = room,
featureFlagService = featureFlagService,
)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
skipItems(1)
assertThat(awaitItem().canShowKnockRequests).isFalse()
featureFlagService.setFeatureEnabled(FeatureFlags.Knock, true)
assertThat(awaitItem().canShowKnockRequests).isTrue()
room.givenRoomInfo(aRoomInfo(joinRule = JoinRule.Private))
assertThat(awaitItem().canShowKnockRequests).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - show security and privacy`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val featureFlagService = FakeFeatureFlagService()
val presenter = createRoomDetailsPresenter(room = room, featureFlagService = featureFlagService)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
skipItems(1)
with(awaitItem()) {
assertThat(canShowSecurityAndPrivacy).isTrue()
}
}
}
@Test
fun `present - show debug info`() = runTest {
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
)
val inMemoryAppPreferencesStore = InMemoryAppPreferencesStore(
isDeveloperModeEnabled = true,
)
val presenter = createRoomDetailsPresenter(room = room, appPreferencesStore = inMemoryAppPreferencesStore)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
skipItems(1)
with(awaitItem()) {
assertThat(showDebugInfo).isTrue()
}
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 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.roomdetails.impl
import com.google.common.truth.Truth.assertThat
import kotlinx.collections.immutable.persistentListOf
import org.junit.Test
class RoomDetailsStateTest {
@Test
fun `room not public not encrypted should have not encrypted badge`() {
val sut = aRoomDetailsState(
isPublic = false,
isEncrypted = false,
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.NOT_ENCRYPTED)
)
}
@Test
fun `room public not encrypted should have not encrypted and public badges`() {
val sut = aRoomDetailsState(
isPublic = true,
isEncrypted = false,
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.NOT_ENCRYPTED, RoomBadge.PUBLIC)
)
}
@Test
fun `room public encrypted should have encrypted and public badges`() {
val sut = aRoomDetailsState(
isPublic = true,
isEncrypted = true,
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC)
)
}
@Test
fun `room not public encrypted should have encrypted badges`() {
val sut = aRoomDetailsState(
isPublic = false,
isEncrypted = true,
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.ENCRYPTED)
)
}
}

View File

@@ -0,0 +1,375 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 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.roomdetails.impl
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.userprofile.shared.aUserProfileState
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureCalledOnceWithTwoParams
import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EnsureNeverCalledWithParam
import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParams
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce
import io.element.android.tests.testutils.ensureCalledOnceWithParam
import io.element.android.tests.testutils.pressBack
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@RunWith(AndroidJUnit4::class)
class RoomDetailsViewTest {
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `click on back invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
goBack = callback,
)
rule.pressBack()
}
}
@Test
fun `click on share invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
onShareRoom = callback,
)
rule.clickOn(CommonStrings.action_share)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on room members invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
openRoomMemberList = callback,
)
rule.clickOn(CommonStrings.common_people)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on polls invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
openPollHistory = callback,
)
rule.clickOn(R.string.screen_polls_history_title)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on media gallery invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
openMediaGallery = callback,
)
rule.clickOn(R.string.screen_room_details_media_gallery_title)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on notification invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
openRoomNotificationSettings = callback,
)
rule.clickOn(R.string.screen_room_details_notification_title)
}
}
@Test
fun `click on invite invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
canInvite = true,
),
invitePeople = callback,
)
rule.clickOn(CommonStrings.action_invite)
}
}
@Test
fun `click on call invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
canInvite = true,
),
onJoinCallClick = callback,
)
rule.clickOn(CommonStrings.action_call)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on pinned messages invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
canInvite = true,
),
onPinnedMessagesClick = callback,
)
rule.clickOn(R.string.screen_room_details_pinned_events_row_title)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on security and privacy invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
canShowSecurityAndPrivacy = true,
),
onSecurityAndPrivacyClick = callback,
)
rule.clickOn(R.string.screen_room_details_security_and_privacy_title)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on add topic emit expected event`() {
ensureCalledOnceWithParam<RoomDetailsAction>(RoomDetailsAction.AddTopic) { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
roomTopic = RoomTopicState.CanAddTopic,
),
onActionClick = callback,
)
rule.clickOn(R.string.screen_room_details_add_topic_title)
}
}
@Test
fun `click on menu edit emit expected event`() {
ensureCalledOnceWithParam<RoomDetailsAction>(RoomDetailsAction.Edit) { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
canEdit = true,
),
onActionClick = callback,
)
val menuContentDescription = rule.activity.getString(CommonStrings.a11y_user_menu)
rule.onNodeWithContentDescription(menuContentDescription).performClick()
rule.clickOn(CommonStrings.action_edit)
}
}
@Test
fun `click on avatar test`() {
val eventsRecorder = EventsRecorder<RoomDetailsEvent>(expectEvents = false)
val state = aRoomDetailsState(
eventSink = eventsRecorder,
roomAvatarUrl = "an_avatar_url",
)
val callback = EnsureCalledOnceWithTwoParams(state.roomName, "an_avatar_url")
rule.setRoomDetailView(
state = state,
openAvatarPreview = callback,
)
rule.onNodeWithTag(TestTags.roomDetailAvatar.value).performClick()
callback.assertSuccess()
}
@Test
fun `click on avatar test on DM`() {
val eventsRecorder = EventsRecorder<RoomDetailsEvent>(expectEvents = false)
val state = aRoomDetailsState(
roomType = RoomDetailsType.Dm(
aRoomMember(),
aDmRoomMember(avatarUrl = "an_avatar_url"),
),
roomName = "Daniel",
eventSink = eventsRecorder,
)
val callback = EnsureCalledOnceWithTwoParams("Daniel", "an_avatar_url")
rule.setRoomDetailView(
state = state,
openAvatarPreview = callback,
)
rule.onNodeWithTag(TestTags.memberDetailAvatar.value).performClick()
callback.assertSuccess()
}
@Test
fun `click on mute emit expected event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEvent>()
val state = aRoomDetailsState(
eventSink = eventsRecorder,
roomNotificationSettings = aRoomNotificationSettings(mode = RoomNotificationMode.ALL_MESSAGES),
)
rule.setRoomDetailView(
state = state,
)
rule.clickOn(CommonStrings.common_mute)
eventsRecorder.assertSingle(RoomDetailsEvent.MuteNotification)
}
@Test
fun `click on unmute emit expected event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEvent>()
val state = aRoomDetailsState(
eventSink = eventsRecorder,
roomNotificationSettings = aRoomNotificationSettings(mode = RoomNotificationMode.MUTE),
)
rule.setRoomDetailView(
state = state,
)
rule.clickOn(CommonStrings.common_unmute)
eventsRecorder.assertSingle(RoomDetailsEvent.UnmuteNotification)
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on favorite emit expected Event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEvent>()
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = eventsRecorder,
),
)
rule.clickOn(CommonStrings.common_favourite)
eventsRecorder.assertSingle(RoomDetailsEvent.SetFavorite(true))
}
@Config(qualifiers = "h1500dp")
@Test
fun `click on leave emit expected Event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEvent>()
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = eventsRecorder,
),
)
rule.clickOn(R.string.screen_room_details_leave_room_title)
eventsRecorder.assertSingle(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
}
@Config(qualifiers = "h1500dp")
@Test
fun `click on report room invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
),
onReportRoomClick = callback,
)
rule.clickOn(CommonStrings.action_report_room)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on knock requests invokes expected callback`() {
ensureCalledOnce { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
canShowKnockRequests = true,
),
onKnockRequestsClick = callback,
)
rule.clickOn(R.string.screen_room_details_requests_to_join_title)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `click on profile invokes the expected callback`() {
ensureCalledOnceWithParam(A_USER_ID) { callback ->
rule.setRoomDetailView(
state = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
roomMemberDetailsState = aUserProfileState(userId = A_USER_ID),
),
onProfileClick = callback,
)
rule.clickOn(R.string.screen_room_details_profile_row_title)
}
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomDetailView(
state: RoomDetailsState = aRoomDetailsState(
eventSink = EventsRecorder(expectEvents = false),
),
goBack: () -> Unit = EnsureNeverCalled(),
onActionClick: (RoomDetailsAction) -> Unit = EnsureNeverCalledWithParam(),
onShareRoom: () -> Unit = EnsureNeverCalled(),
openRoomMemberList: () -> Unit = EnsureNeverCalled(),
openRoomNotificationSettings: () -> Unit = EnsureNeverCalled(),
invitePeople: () -> Unit = EnsureNeverCalled(),
openAvatarPreview: (name: String, url: String) -> Unit = EnsureNeverCalledWithTwoParams(),
openPollHistory: () -> Unit = EnsureNeverCalled(),
openMediaGallery: () -> Unit = EnsureNeverCalled(),
openAdminSettings: () -> Unit = EnsureNeverCalled(),
onJoinCallClick: () -> Unit = EnsureNeverCalled(),
onPinnedMessagesClick: () -> Unit = EnsureNeverCalled(),
onKnockRequestsClick: () -> Unit = EnsureNeverCalled(),
onSecurityAndPrivacyClick: () -> Unit = EnsureNeverCalled(),
onProfileClick: (UserId) -> Unit = EnsureNeverCalledWithParam(),
onReportRoomClick: () -> Unit = EnsureNeverCalled(),
) {
setContent {
RoomDetailsView(
state = state,
goBack = goBack,
onActionClick = onActionClick,
onShareRoom = onShareRoom,
openRoomMemberList = openRoomMemberList,
openRoomNotificationSettings = openRoomNotificationSettings,
invitePeople = invitePeople,
openAvatarPreview = openAvatarPreview,
openPollHistory = openPollHistory,
openMediaGallery = openMediaGallery,
openAdminSettings = openAdminSettings,
onJoinCallClick = onJoinCallClick,
onPinnedMessagesClick = onPinnedMessagesClick,
onKnockRequestsClick = onKnockRequestsClick,
onSecurityAndPrivacyClick = onSecurityAndPrivacyClick,
onProfileClick = onProfileClick,
onReportRoomClick = onReportRoomClick,
leaveRoomView = {},
)
}
}

View File

@@ -0,0 +1,780 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.edit
import android.net.Uri
import app.cash.turbine.ReceiveTurbine
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.aJoinedRoom
import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_ROOM_RAW_NAME
import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.mediapickers.test.FakePickerProvider
import io.element.android.libraries.mediaupload.api.MediaUploadInfo
import io.element.android.libraries.mediaupload.test.FakeMediaOptimizationConfigProvider
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
import io.element.android.libraries.permissions.api.PermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.fake.FakeTemporaryUriDeleter
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.io.File
@Suppress("LargeClass")
@ExperimentalCoroutinesApi
class RoomDetailsEditPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
private lateinit var fakePickerProvider: FakePickerProvider
private lateinit var fakeMediaPreProcessor: FakeMediaPreProcessor
private val roomAvatarUri: Uri = mockk()
private val anotherAvatarUri: Uri = mockk()
private val fakeFileContents = ByteArray(2)
@Before
fun setup() {
fakePickerProvider = FakePickerProvider()
fakeMediaPreProcessor = FakeMediaPreProcessor()
mockkStatic(Uri::class)
every { Uri.parse(AN_AVATAR_URL) } returns roomAvatarUri
every { roomAvatarUri.toString() } returns AN_AVATAR_URL
every { Uri.parse(ANOTHER_AVATAR_URL) } returns anotherAvatarUri
every { anotherAvatarUri.toString() } returns ANOTHER_AVATAR_URL
}
@After
fun tearDown() {
unmockkAll()
}
private fun createRoomDetailsEditPresenter(
room: JoinedRoom,
permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(),
temporaryUriDeleter: TemporaryUriDeleter = FakeTemporaryUriDeleter(),
mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(),
): RoomDetailsEditPresenter {
return RoomDetailsEditPresenter(
room = room,
mediaPickerProvider = fakePickerProvider,
mediaPreProcessor = fakeMediaPreProcessor,
permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionsPresenter),
temporaryUriDeleter = temporaryUriDeleter,
mediaOptimizationConfigProvider = mediaOptimizationConfigProvider,
)
}
@Test
fun `present - initial state is created from room info`() = runTest {
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
displayName = A_ROOM_NAME,
rawName = A_ROOM_RAW_NAME,
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.roomId).isEqualTo(room.roomId)
assertThat(initialState.roomRawName).isEqualTo(A_ROOM_RAW_NAME)
assertThat(initialState.roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
assertThat(initialState.roomTopic).isEqualTo(room.info().topic.orEmpty())
assertThat(initialState.avatarActions).containsExactly(
AvatarAction.ChoosePhoto,
AvatarAction.TakePhoto,
AvatarAction.Remove
)
assertThat(initialState.saveButtonEnabled).isFalse()
assertThat(initialState.saveAction).isInstanceOf(AsyncAction.Uninitialized::class.java)
}
}
@Test
fun `present - sets canChangeName if user has permission`() = runTest {
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_NAME -> Result.success(true)
StateEventType.ROOM_AVATAR -> Result.success(false)
StateEventType.ROOM_TOPIC -> Result.failure(RuntimeException("Oops"))
else -> lambdaError()
}
},
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
// Initially false
val initialState = awaitItem()
assertThat(initialState.canChangeName).isFalse()
assertThat(initialState.canChangeAvatar).isFalse()
assertThat(initialState.canChangeTopic).isFalse()
// When the asynchronous check completes, the single field we can edit is true
val settledState = awaitItem()
assertThat(settledState.canChangeName).isTrue()
assertThat(settledState.canChangeAvatar).isFalse()
assertThat(settledState.canChangeTopic).isFalse()
deleteCallback.assertions().isCalledOnce().with(value(null))
}
}
@Test
fun `present - sets canChangeAvatar if user has permission`() = runTest {
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_NAME -> Result.success(false)
StateEventType.ROOM_AVATAR -> Result.success(true)
StateEventType.ROOM_TOPIC -> Result.failure(RuntimeException("Oops"))
else -> lambdaError()
}
}
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
// Initially false
val initialState = awaitItem()
assertThat(initialState.canChangeName).isFalse()
assertThat(initialState.canChangeAvatar).isFalse()
assertThat(initialState.canChangeTopic).isFalse()
// When the asynchronous check completes, the single field we can edit is true
val settledState = awaitItem()
assertThat(settledState.canChangeName).isFalse()
assertThat(settledState.canChangeAvatar).isTrue()
assertThat(settledState.canChangeTopic).isFalse()
}
}
@Test
fun `present - sets canChangeTopic if user has permission`() = runTest {
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_NAME -> Result.success(false)
StateEventType.ROOM_AVATAR -> Result.failure(RuntimeException("Oops"))
StateEventType.ROOM_TOPIC -> Result.success(true)
else -> lambdaError()
}
}
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
// Initially false
val initialState = awaitItem()
assertThat(initialState.canChangeName).isFalse()
assertThat(initialState.canChangeAvatar).isFalse()
assertThat(initialState.canChangeTopic).isFalse()
// When the asynchronous check completes, the single field we can edit is true
val settledState = awaitItem()
assertThat(settledState.canChangeName).isFalse()
assertThat(settledState.canChangeAvatar).isFalse()
assertThat(settledState.canChangeTopic).isTrue()
}
}
@Test
fun `present - updates state in response to changes`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.roomTopic).isEqualTo("My topic")
assertThat(initialState.roomRawName).isEqualTo("Name")
assertThat(initialState.roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name II"))
awaitItem().apply {
assertThat(roomTopic).isEqualTo("My topic")
assertThat(roomRawName).isEqualTo("Name II")
assertThat(roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
}
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name III"))
awaitItem().apply {
assertThat(roomTopic).isEqualTo("My topic")
assertThat(roomRawName).isEqualTo("Name III")
assertThat(roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
}
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("Another topic"))
awaitItem().apply {
assertThat(roomTopic).isEqualTo("Another topic")
assertThat(roomRawName).isEqualTo("Name III")
assertThat(roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
}
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove))
awaitItem().apply {
assertThat(roomTopic).isEqualTo("Another topic")
assertThat(roomRawName).isEqualTo("Name III")
assertThat(roomAvatarUrl).isNull()
}
}
}
@Test
fun `present - obtains avatar uris from gallery`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
fakePickerProvider.givenResult(anotherAvatarUri)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
awaitItem().apply {
assertThat(roomAvatarUrl).isEqualTo(anotherAvatarUri.toString())
}
}
}
@Test
fun `present - obtains avatar uris from camera`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
fakePickerProvider.givenResult(anotherAvatarUri)
val fakePermissionsPresenter = FakePermissionsPresenter()
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
permissionsPresenter = fakePermissionsPresenter,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
assertThat(initialState.cameraPermissionState.permissionGranted).isFalse()
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.TakePhoto))
val stateWithAskingPermission = awaitItem()
assertThat(stateWithAskingPermission.cameraPermissionState.showDialog).isTrue()
fakePermissionsPresenter.setPermissionGranted()
val stateWithPermission = awaitItem()
assertThat(stateWithPermission.cameraPermissionState.permissionGranted).isTrue()
val stateWithNewAvatar = awaitItem()
assertThat(stateWithNewAvatar.roomAvatarUrl).isEqualTo(anotherAvatarUri.toString())
// Do it again, no permission is requested
fakePickerProvider.givenResult(roomAvatarUri)
stateWithNewAvatar.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.TakePhoto))
val stateWithNewAvatar2 = awaitItem()
assertThat(stateWithNewAvatar2.roomAvatarUrl).isEqualTo(AN_AVATAR_URL)
deleteCallback.assertions().isCalledExactly(3).withSequence(
listOf(value(null)),
listOf(value(roomAvatarUri)),
listOf(value(anotherAvatarUri)),
)
}
}
@Test
fun `present - updates save button state`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
fakePickerProvider.givenResult(roomAvatarUri)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.saveButtonEnabled).isFalse()
// Once a change is made, the save button is enabled
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name II"))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
}
// If it's reverted then the save disables again
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name"))
awaitItem().apply {
assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("Another topic"))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("My topic"))
awaitItem().apply {
assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
awaitItem().apply {
assertThat(saveButtonEnabled).isFalse()
}
}
}
@Test
fun `present - updates save button state when initial values are null`() = runTest {
val room = aJoinedRoom(
topic = null,
displayName = "fallback",
avatarUrl = null,
canSendStateResult = { _, _ -> Result.success(true) }
)
fakePickerProvider.givenResult(roomAvatarUri)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.saveButtonEnabled).isFalse()
// Once a change is made, the save button is enabled
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name II"))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
}
// If it's reverted then the save disables again
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("fallback"))
awaitItem().apply {
assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("Another topic"))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(""))
awaitItem().apply {
assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove))
awaitItem().apply {
assertThat(saveButtonEnabled).isFalse()
}
}
}
@Test
fun `present - save changes room details if different`() = runTest {
val setNameResult = lambdaRecorder { _: String -> Result.success(Unit) }
val setTopicResult = lambdaRecorder { _: String -> Result.success(Unit) }
val removeAvatarResult = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
setNameResult = setNameResult,
setTopicResult = setTopicResult,
removeAvatarResult = removeAvatarResult,
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("New name"))
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("New topic"))
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(5)
setNameResult.assertions().isCalledOnce().with(value("New name"))
setTopicResult.assertions().isCalledOnce().with(value("New topic"))
removeAvatarResult.assertions().isCalledOnce()
}
}
@Test
fun `present - save doesn't change room details if they're the same trimmed`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName(" Name "))
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(" My topic "))
initialState.eventSink(RoomDetailsEditEvents.Save)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - save doesn't change topic if it was unset and is now blank`() = runTest {
val room = aJoinedRoom(
topic = null,
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(""))
initialState.eventSink(RoomDetailsEditEvents.Save)
cancelAndIgnoreRemainingEvents()
deleteCallback.assertions().isCalledOnce().with(value(null))
}
}
@Test
fun `present - save doesn't change name if it's now empty`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName(""))
initialState.eventSink(RoomDetailsEditEvents.Save)
cancelAndIgnoreRemainingEvents()
deleteCallback.assertions().isCalledOnce().with(value(null))
}
}
@Test
fun `present - save processes and sets avatar when processor returns successfully`() = runTest {
val updateAvatarResult = lambdaRecorder { _: String, _: ByteArray -> Result.success(Unit) }
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
updateAvatarResult = updateAvatarResult,
canSendStateResult = { _, _ -> Result.success(true) }
)
givenPickerReturnsFile()
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(4)
updateAvatarResult.assertions().isCalledOnce().with(value(MimeTypes.Jpeg), value(fakeFileContents))
deleteCallback.assertions().isCalledExactly(2).withSequence(
listOf(value(null)),
listOf(value(roomAvatarUri)),
)
}
}
@Test
fun `present - save does not set avatar data if processor fails`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, _ -> Result.success(true) }
)
fakePickerProvider.givenResult(anotherAvatarUri)
fakeMediaPreProcessor.givenResult(Result.failure(RuntimeException("Oh no")))
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(3)
assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Failure::class.java)
}
}
@Test
fun `present - sets save action to failure if name update fails`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
setNameResult = { Result.failure(RuntimeException("!")) },
canSendStateResult = { _, _ -> Result.success(true) }
)
saveAndAssertFailure(room, RoomDetailsEditEvents.UpdateRoomName("New name"), deleteCallbackNumberOfInvocation = 1)
}
@Test
fun `present - sets save action to failure if topic update fails`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
setTopicResult = { Result.failure(RuntimeException("!")) },
canSendStateResult = { _, _ -> Result.success(true) }
)
saveAndAssertFailure(room, RoomDetailsEditEvents.UpdateRoomTopic("New topic"), deleteCallbackNumberOfInvocation = 1)
}
@Test
fun `present - sets save action to failure if removing avatar fails`() = runTest {
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
removeAvatarResult = { Result.failure(RuntimeException("!")) },
canSendStateResult = { _, _ -> Result.success(true) }
)
saveAndAssertFailure(room, RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove), deleteCallbackNumberOfInvocation = 2)
}
@Test
fun `present - sets save action to failure if setting avatar fails`() = runTest {
givenPickerReturnsFile()
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
updateAvatarResult = { _, _ -> Result.failure(RuntimeException("!")) },
canSendStateResult = { _, _ -> Result.success(true) }
)
saveAndAssertFailure(room, RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto), deleteCallbackNumberOfInvocation = 2)
}
@Test
fun `present - CancelSaveChanges resets save action state`() = runTest {
givenPickerReturnsFile()
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
setTopicResult = { Result.failure(RuntimeException("!")) },
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("foo"))
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(3)
assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Failure::class.java)
initialState.eventSink(RoomDetailsEditEvents.CloseDialog)
assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Uninitialized::class.java)
}
}
@Test
fun `present - leave without saving - cancel`() = runTest {
val room = aJoinedRoom(
displayName = "Name",
canSendStateResult = { _, _ -> Result.success(true) }
)
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.saveButtonEnabled).isFalse()
// Once a change is made, the save button is enabled
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name edited"))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
eventSink(RoomDetailsEditEvents.OnBackPress)
}
awaitItem().apply {
assertThat(saveAction).isEqualTo(AsyncAction.ConfirmingCancellation)
eventSink(RoomDetailsEditEvents.CloseDialog)
}
awaitItem().apply {
assertThat(saveAction).isEqualTo(AsyncAction.Uninitialized)
}
}
}
@Test
fun `present - leave no changes, no confirmation`() = runTest {
val room = aJoinedRoom(
displayName = "Name",
canSendStateResult = { _, _ -> Result.success(true) }
)
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter {},
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.saveButtonEnabled).isFalse()
initialState.eventSink(RoomDetailsEditEvents.OnBackPress)
assertThat(awaitItem().saveAction).isEqualTo(AsyncAction.Success(Unit))
}
}
@Test
fun `present - leave without saving - confirm`() = runTest {
val room = aJoinedRoom(
displayName = "Name",
canSendStateResult = { _, _ -> Result.success(true) }
)
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter({}),
)
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.saveButtonEnabled).isFalse()
// Once a change is made, the save button is enabled
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name edited"))
awaitItem().apply {
assertThat(saveButtonEnabled).isTrue()
eventSink(RoomDetailsEditEvents.OnBackPress)
}
awaitItem().apply {
assertThat(saveAction).isEqualTo(AsyncAction.ConfirmingCancellation)
eventSink(RoomDetailsEditEvents.OnBackPress)
}
awaitItem().apply {
assertThat(saveAction).isEqualTo(AsyncAction.Success(Unit))
}
}
}
private suspend fun saveAndAssertFailure(
room: JoinedRoom,
event: RoomDetailsEditEvents,
deleteCallbackNumberOfInvocation: Int = 2,
) {
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
val presenter = createRoomDetailsEditPresenter(
room = room,
temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback),
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(event)
initialState.eventSink(RoomDetailsEditEvents.Save)
skipItems(1)
assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Loading::class.java)
assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Failure::class.java)
deleteCallback.assertions().isCalledExactly(deleteCallbackNumberOfInvocation)
}
}
private fun givenPickerReturnsFile() {
mockkStatic(File::readBytes)
val processedFile: File = mockk {
every { readBytes() } returns fakeFileContents
}
fakePickerProvider.givenResult(anotherAvatarUri)
fakeMediaPreProcessor.givenResult(
Result.success(
MediaUploadInfo.AnyFile(
file = processedFile,
fileInfo = mockk(),
)
)
)
}
companion object {
private const val ANOTHER_AVATAR_URL = "example://camera/foo.jpg"
}
}
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
skipItems(1)
return awaitItem()
}

View File

@@ -0,0 +1,251 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2024, 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.roomdetails.impl.edit
import androidx.activity.ComponentActivity
import androidx.annotation.StringRes
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.isEditable
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce
import io.element.android.tests.testutils.pressBack
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class RoomDetailsEditViewTest {
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `clicking on back emits the expected Event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder
),
)
rule.pressBack()
eventsRecorder.assertSingle(RoomDetailsEditEvents.OnBackPress)
}
@Test
fun `clicking on OK when confirming exit emits the expected Event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
saveAction = AsyncAction.ConfirmingCancellation,
eventSink = eventsRecorder,
),
)
rule.clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(RoomDetailsEditEvents.OnBackPress)
}
@Test
fun `clicking on cancel when confirming exit emits the expected Event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
saveAction = AsyncAction.ConfirmingCancellation,
eventSink = eventsRecorder,
),
)
rule.clickOn(CommonStrings.action_cancel)
eventsRecorder.assertSingle(RoomDetailsEditEvents.CloseDialog)
}
@Test
fun `when edition is successful, the expected callback is invoked`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>(expectEvents = false)
ensureCalledOnce { callback ->
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
saveAction = AsyncAction.Success(Unit)
),
onDone = callback,
)
}
}
@Test
fun `when name is changed, the expected Event is emitted`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
roomRawName = "Marketing",
),
)
rule.onNodeWithText("Marketing").performTextInput("A")
eventsRecorder.assertSingle(RoomDetailsEditEvents.UpdateRoomName("AMarketing"))
}
@Test
fun `when user cannot change name, nothing happen`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>(expectEvents = false)
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
roomRawName = "Marketing",
canChangeName = false,
),
)
rule.onNodeWithText("Marketing").assert(!isEditable())
}
@Test
fun `when topic is changed, the expected Event is emitted`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
roomTopic = "My Topic",
),
)
rule.onNodeWithText("My Topic").performTextInput("A")
eventsRecorder.assertSingle(RoomDetailsEditEvents.UpdateRoomTopic("AMy Topic"))
}
@Test
fun `when user cannot change topic, nothing happen`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>(expectEvents = false)
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
roomTopic = "My Topic",
canChangeTopic = false,
),
)
rule.onNodeWithText("My Topic").assert(!isEditable())
}
@Ignore("This test is failing because the bottom sheet does not open")
@Test
fun `when avatar is changed with action to take photo, the expected Event is emitted`() {
testAvatarChange(
stringActionRes = CommonStrings.action_take_photo,
expectedEvent = RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.TakePhoto),
)
}
@Ignore("This test is failing because the bottom sheet does not open")
@Test
fun `when avatar is changed with action to choose photo, the expected Event is emitted`() {
testAvatarChange(
stringActionRes = CommonStrings.action_choose_photo,
expectedEvent = RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto),
)
}
@Ignore("This test is failing because the bottom sheet does not open")
@Test
fun `when avatar is changed with action to remove photo, the expected Event is emitted`() {
testAvatarChange(
stringActionRes = CommonStrings.action_remove,
expectedEvent = RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove),
)
}
private fun testAvatarChange(
@StringRes stringActionRes: Int,
expectedEvent: RoomDetailsEditEvents.HandleAvatarAction,
) {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
),
)
// Open the bottom sheet
rule.onNode(hasTestTag(TestTags.editAvatar.value)).performClick()
rule.onNodeWithText(rule.activity.getString(stringActionRes)).assertExists()
rule.clickOn(stringActionRes)
eventsRecorder.assertSingle(expectedEvent)
}
@Test
fun `when user cannot change avatar, nothing happen`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>(expectEvents = false)
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
canChangeAvatar = false,
),
)
rule.onNode(hasTestTag(TestTags.editAvatar.value)).performClick()
rule.onNodeWithText(rule.activity.getString(CommonStrings.action_take_photo)).assertDoesNotExist()
}
@Test
fun `when save is clicked, the expected Event is emitted`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
saveButtonEnabled = true,
),
)
rule.clickOn(CommonStrings.action_save)
eventsRecorder.assertSingle(RoomDetailsEditEvents.Save)
}
@Test
fun `when save is clicked, but nothing need to be saved, nothing happens`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>(expectEvents = false)
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
saveButtonEnabled = false,
),
)
rule.clickOn(CommonStrings.action_save)
}
@Test
fun `when error is shown, closing the dialog emit the expected Event`() {
val eventsRecorder = EventsRecorder<RoomDetailsEditEvents>()
rule.setRoomDetailsEditView(
aRoomDetailsEditState(
eventSink = eventsRecorder,
saveAction = AsyncAction.Failure(RuntimeException("Whelp")),
),
)
rule.clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(RoomDetailsEditEvents.CloseDialog)
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomDetailsEditView(
state: RoomDetailsEditState,
onDone: () -> Unit = EnsureNeverCalled(),
) {
setContent {
RoomDetailsEditView(
state = state,
onDone = onDone,
)
}
}

View File

@@ -0,0 +1,236 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roommembermoderation.api.RoomMemberModerationState
import io.element.android.libraries.architecture.Presenter
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.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.test
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ExperimentalCoroutinesApi
class RoomMemberListPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
@Test
fun `initial state is loading`() = runTest {
val presenter = createPresenter()
presenter.test {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.filteredRoomMembers.isLoading()).isTrue()
assertThat(initialState.searchQuery).isEmpty()
assertThat(initialState.selectedSection).isEqualTo(SelectedSection.MEMBERS)
}
}
@Test
fun `hide banned section when there is no banned users`() = runTest {
val allRoomMembers = aRoomMemberList()
val noBannedMembers = allRoomMembers
.filterNot { it.membership == RoomMembershipState.BAN }
.toImmutableList()
val room = createFakeJoinedRoom()
.apply {
givenRoomMembersState(RoomMembersState.Ready(allRoomMembers))
}
val presenter = createPresenter(
joinedRoom = room,
roomMemberModerationState = aRoomMemberModerationState(canBan = true),
)
presenter.test {
skipItems(1)
val loadedState = awaitItem()
assertThat(loadedState.showBannedSection).isTrue()
loadedState.eventSink(RoomMemberListEvents.ChangeSelectedSection(SelectedSection.BANNED))
val bannedSectionState = awaitItem()
assertThat(bannedSectionState.selectedSection).isEqualTo(SelectedSection.BANNED)
// Now update the room members to have no banned users
room.givenRoomMembersState(RoomMembersState.Ready(noBannedMembers))
skipItems(1)
val noBannedMembersState = awaitItem()
assertThat(noBannedMembersState.showBannedSection).isFalse()
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.selectedSection).isEqualTo(SelectedSection.MEMBERS)
}
}
@Test
fun `member loading is done automatically on start, but is async`() = runTest {
val room = createFakeJoinedRoom()
val presenter = createPresenter(joinedRoom = room)
presenter.test {
skipItems(1)
val initialState = awaitItem()
assertThat(initialState.filteredRoomMembers.isLoading()).isTrue()
assertThat(initialState.searchQuery).isEmpty()
room.givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
// Skip items while the new members state is processed
skipItems(2)
val loadedState = awaitItem()
val loadedRoomMembers = loadedState.filteredRoomMembers.dataOrNull()!!
assertThat(loadedRoomMembers.joined).isNotEmpty()
assertThat(loadedRoomMembers.banned).isNotEmpty()
assertThat(loadedRoomMembers.invited).isNotEmpty()
assertThat(loadedRoomMembers.isEmpty(SelectedSection.MEMBERS)).isFalse()
assertThat(loadedRoomMembers.isEmpty(SelectedSection.BANNED)).isFalse()
}
}
@Test
fun `search for something which is not found`() = runTest {
val room = createFakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
}
val presenter = createPresenter(joinedRoom = room)
presenter.test {
skipItems(1)
val loadedState = awaitItem()
val loadedRoomMembers = loadedState.filteredRoomMembers.dataOrNull()!!
assertThat(loadedRoomMembers.joined).isNotEmpty()
assertThat(loadedRoomMembers.banned).isNotEmpty()
assertThat(loadedRoomMembers.invited).isNotEmpty()
assertThat(loadedRoomMembers.isEmpty(SelectedSection.MEMBERS)).isFalse()
assertThat(loadedRoomMembers.isEmpty(SelectedSection.BANNED)).isFalse()
loadedState.eventSink(RoomMemberListEvents.UpdateSearchQuery("something"))
val searchQueryUpdatedState = awaitItem()
assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("something")
val searchSearchResultDelivered = awaitItem()
val emptyRoomMembers = searchSearchResultDelivered.filteredRoomMembers.dataOrNull()!!
assertThat(emptyRoomMembers.joined).isEmpty()
assertThat(emptyRoomMembers.banned).isEmpty()
assertThat(emptyRoomMembers.invited).isEmpty()
assertThat(emptyRoomMembers.isEmpty(SelectedSection.MEMBERS)).isTrue()
assertThat(emptyRoomMembers.isEmpty(SelectedSection.BANNED)).isTrue()
}
}
@Test
fun `search for something which is found`() = runTest {
val room = createFakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
}
val presenter = createPresenter(joinedRoom = room)
presenter.test {
skipItems(1)
val loadedState = awaitItem()
val loadedRoomMembers = loadedState.filteredRoomMembers.dataOrNull()!!
assertThat(loadedRoomMembers.joined).isNotEmpty()
assertThat(loadedRoomMembers.banned).isNotEmpty()
assertThat(loadedRoomMembers.invited).isNotEmpty()
assertThat(loadedRoomMembers.isEmpty(SelectedSection.MEMBERS)).isFalse()
assertThat(loadedRoomMembers.isEmpty(SelectedSection.BANNED)).isFalse()
loadedState.eventSink(RoomMemberListEvents.UpdateSearchQuery("alice"))
val searchQueryUpdatedState = awaitItem()
assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("alice")
val searchSearchResultDelivered = awaitItem()
val emptyRoomMembers = searchSearchResultDelivered.filteredRoomMembers.dataOrNull()!!
assertThat(emptyRoomMembers.joined).isNotEmpty()
assertThat(emptyRoomMembers.banned).isEmpty()
assertThat(emptyRoomMembers.invited).isEmpty()
assertThat(emptyRoomMembers.isEmpty(SelectedSection.MEMBERS)).isFalse()
assertThat(emptyRoomMembers.isEmpty(SelectedSection.BANNED)).isTrue()
}
}
@Test
fun `present - asynchronously sets canInvite when user has correct power level`() = runTest {
val presenter = createPresenter()
presenter.test {
skipItems(1)
val loadedState = awaitItem()
assertThat(loadedState.canInvite).isTrue()
}
}
@Test
fun `present - asynchronously sets canInvite when user does not have correct power level`() = runTest {
val presenter = createPresenter(
joinedRoom = createFakeJoinedRoom(
canInviteResult = { Result.success(false) },
)
)
presenter.test {
val loadedState = awaitItem()
assertThat(loadedState.canInvite).isFalse()
}
}
@Test
fun `present - asynchronously sets canInvite when power level check fails`() = runTest {
val presenter = createPresenter(
joinedRoom = createFakeJoinedRoom(
canInviteResult = { Result.failure(RuntimeException("Eek")) },
)
)
presenter.test {
val loadedState = awaitItem()
assertThat(loadedState.canInvite).isFalse()
}
}
@Test
fun `present - RoomMemberSelected will open the moderation options`() = runTest {
val presenter = createPresenter(
roomMemberModerationState = aRoomMemberModerationState(canBan = true, canKick = true)
)
presenter.test {
skipItems(1)
awaitItem().eventSink(RoomMemberListEvents.RoomMemberSelected(anInvitedVictor()))
}
}
}
private fun createFakeJoinedRoom(
updateMembersResult: () -> Unit = { },
canInviteResult: (UserId) -> Result<Boolean> = { Result.success(true) },
): FakeJoinedRoom {
return FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = updateMembersResult,
canInviteResult = canInviteResult,
).apply {
// Needed to avoid discarding the loaded members as a partial and invalid result
givenRoomInfo(aRoomInfo(joinedMembersCount = 2))
}
)
}
@ExperimentalCoroutinesApi
private fun TestScope.createPresenter(
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
joinedRoom: JoinedRoom = createFakeJoinedRoom(),
encryptedService: FakeEncryptionService = FakeEncryptionService(),
roomMemberModerationState: RoomMemberModerationState = aRoomMemberModerationState(),
) = RoomMemberListPresenter(
room = joinedRoom,
coroutineDispatchers = coroutineDispatchers,
roomMembersModerationPresenter = Presenter {
roomMemberModerationState
},
encryptionService = encryptedService,
)

View File

@@ -0,0 +1,388 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.members.details
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.aJoinedRoom
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.userprofile.api.UserProfileEvents
import io.element.android.features.userprofile.api.UserProfilePresenterFactory
import io.element.android.features.userprofile.api.UserProfileVerificationState
import io.element.android.features.userprofile.shared.aUserProfileState
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.test
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ExperimentalCoroutinesApi
class RoomMemberDetailsPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
@Test
fun `present - returns the room member's data, then updates it if needed`() = runTest {
val roomMember = aRoomMember(displayName = "Alice")
val room = aJoinedRoom(
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
getUpdatedMemberResult = { Result.success(roomMember) },
).apply {
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,
)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.userName).isEqualTo("Alice")
assertThat(initialState.avatarUrl).isEqualTo("Profile avatar url")
skipItems(1)
val nextState = awaitItem()
assertThat(nextState.userName).isEqualTo("A custom name")
assertThat(nextState.avatarUrl).isEqualTo("A custom avatar")
}
}
@Test
fun `present - will recover when retrieving room member details fails`() = runTest {
val roomMember = aRoomMember(
displayName = "Alice",
avatarUrl = "Alice Avatar url",
)
val room = aJoinedRoom(
userDisplayNameResult = { Result.failure(RuntimeException()) },
userAvatarUrlResult = { Result.failure(RuntimeException()) },
getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) },
).apply {
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.userName).isEqualTo("Alice")
assertThat(initialState.avatarUrl).isEqualTo("Alice Avatar url")
}
}
@Test
fun `present - will fallback to original data if the updated data is null`() = runTest {
val roomMember = aRoomMember(displayName = "Alice")
val room = aJoinedRoom(
userDisplayNameResult = { Result.success(null) },
userAvatarUrlResult = { Result.success(null) },
getUpdatedMemberResult = { Result.success(roomMember) }
).apply {
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.userName).isEqualTo("Alice")
assertThat(initialState.avatarUrl).isEqualTo("Profile avatar url")
}
}
@Test
fun `present - will fallback to user profile if user is not a member of the room`() = runTest {
val room = aJoinedRoom(
userDisplayNameResult = { Result.failure(Exception("Not a member!")) },
userAvatarUrlResult = { Result.failure(Exception("Not a member!")) },
getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) },
)
val presenter = createRoomMemberDetailsPresenter(
room = room,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.userName).isEqualTo("Profile user name")
assertThat(initialState.avatarUrl).isEqualTo("Profile avatar url")
}
}
@Test
fun `present - null cases`() = runTest {
val roomMember = aRoomMember(
displayName = null,
avatarUrl = null,
)
val room = aJoinedRoom(
userDisplayNameResult = { Result.success(null) },
userAvatarUrlResult = { Result.success(null) },
getUpdatedMemberResult = { Result.success(roomMember) },
)
val presenter = createRoomMemberDetailsPresenter(
room = room,
userProfilePresenterFactory = {
Presenter {
aUserProfileState(
userName = null,
avatarUrl = null,
)
}
},
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.userName).isNull()
assertThat(initialState.avatarUrl).isNull()
}
}
@Test
fun `present - when user's identity is verified, the value in the state is VERIFIED`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.Verified) },
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.VERIFIED }
}
}
@Test
fun `present - when user's identity is unknown, the value in the state is UNKNOWN`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(null) },
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
ensureAllEventsConsumed()
}
}
@Test
fun `present - when user's identity is pinned, the value in the state is UNVERIFIED`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.Pinned) },
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.UNVERIFIED }
}
}
@Test
fun `present - when user's identity is pin violation, the value in the state is UNVERIFIED`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.PinViolation) },
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.UNVERIFIED }
}
}
@Test
fun `present - when user's identity has a verification violation, the value in the state is VERIFICATION_VIOLATION`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.VerificationViolation) },
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.VERIFICATION_VIOLATION }
}
}
@Test
fun `present - user identity updates in real time if the room is encrypted`() = runTest {
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
),
identityStateChangesFlow = identityStateChanges,
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(null) },
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
room.emitSyncUpdate()
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.Pinned)))
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.UNVERIFIED }
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.Verified)))
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.VERIFIED }
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.VerificationViolation)))
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.VERIFICATION_VIOLATION }
}
}
@Test
fun `present - user identity can't update in real time if the room is not encrypted`() = runTest {
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = false),
),
identityStateChangesFlow = identityStateChanges,
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(null) },
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
room.emitSyncUpdate()
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.Pinned)))
// No new events emitted
ensureAllEventsConsumed()
}
}
@Test
fun `present - handles WithdrawVerification action`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val withdrawVerificationResult = lambdaRecorder<UserId, Result<Unit>> { Result.success(Unit) }
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.VerificationViolation) },
withdrawVerificationResult = withdrawVerificationResult,
)
val presenter = createRoomMemberDetailsPresenter(room = room, encryptionService = encryptionService)
presenter.test {
// Initial state, then the verification state is updated
val initialState = awaitItem()
assertThat(initialState.verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.VERIFICATION_VIOLATION }
initialState.eventSink(UserProfileEvents.WithdrawVerification)
withdrawVerificationResult.assertions().isCalledOnce()
}
}
private fun createRoomMemberDetailsPresenter(
room: JoinedRoom,
userProfilePresenterFactory: UserProfilePresenterFactory = UserProfilePresenterFactory {
Presenter {
aUserProfileState(
userName = "Profile user name",
avatarUrl = "Profile avatar url",
)
}
},
encryptionService: FakeEncryptionService = FakeEncryptionService(getUserIdentityResult = { Result.success(null) }),
clipboardHelper: ClipboardHelper = FakeClipboardHelper(),
): RoomMemberDetailsPresenter {
return RoomMemberDetailsPresenter(
roomMemberId = UserId("@alice:server.org"),
room = room,
userProfilePresenterFactory = userProfilePresenterFactory,
encryptionService = encryptionService,
clipboardHelper = clipboardHelper,
)
}
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.roomdetails.impl.notificationsettings
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.aJoinedRoom
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.tests.testutils.awaitLastSequentialItem
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import kotlinx.coroutines.test.runTest
import org.junit.Test
class RoomNotificationSettingsPresenterTest {
@Test
fun `present - initial state is created from room info`() = runTest {
val presenter = createRoomNotificationSettingsPresenter()
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.roomNotificationSettings.dataOrNull()).isNull()
assertThat(initialState.defaultRoomNotificationMode).isNull()
val loadedState = awaitItem()
assertThat(loadedState.displayMentionsOnlyDisclaimer).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - notification mode changed`() = runTest {
val presenter = createRoomNotificationSettingsPresenter()
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
awaitItem().eventSink(RoomNotificationSettingsEvents.ChangeRoomNotificationMode(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY))
val updatedState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
assertThat(updatedState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - observe notification mode changed`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
val presenter = createRoomNotificationSettingsPresenter(notificationSettingsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
notificationSettingsService.setRoomNotificationMode(A_ROOM_ID, RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
val updatedState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
assertThat(updatedState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
}
}
@Test
fun `present - notification settings set custom failed`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
notificationSettingsService.givenSetNotificationModeError(AN_EXCEPTION)
val presenter = createRoomNotificationSettingsPresenter(notificationSettingsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(false))
val failedState = consumeItemsUntilPredicate {
it.setNotificationSettingAction.isFailure()
}.last()
assertThat(failedState.roomNotificationSettings.dataOrNull()?.isDefault).isTrue()
assertThat(failedState.pendingSetDefault).isNull()
assertThat(failedState.setNotificationSettingAction.isFailure()).isTrue()
failedState.eventSink(RoomNotificationSettingsEvents.ClearSetNotificationError)
val errorClearedState = consumeItemsUntilPredicate {
it.setNotificationSettingAction.isUninitialized()
}.last()
assertThat(errorClearedState.setNotificationSettingAction.isUninitialized()).isTrue()
}
}
@Test
fun `present - notification settings set custom`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
val presenter = createRoomNotificationSettingsPresenter(notificationSettingsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(false))
skipItems(3)
val defaultState = awaitItem()
assertThat(defaultState.roomNotificationSettings.dataOrNull()?.isDefault).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - notification settings restore default`() = runTest {
val presenter = createRoomNotificationSettingsPresenter()
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomNotificationSettingsEvents.ChangeRoomNotificationMode(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY))
initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(true))
val defaultState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
assertThat(defaultState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - notification settings restore default failed`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
notificationSettingsService.givenRestoreDefaultNotificationModeError(AN_EXCEPTION)
val presenter = createRoomNotificationSettingsPresenter(notificationSettingsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomNotificationSettingsEvents.ChangeRoomNotificationMode(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY))
initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(true))
val failedState = consumeItemsUntilPredicate {
it.restoreDefaultAction.isFailure()
}.last()
assertThat(failedState.restoreDefaultAction.isFailure()).isTrue()
failedState.eventSink(RoomNotificationSettingsEvents.ClearRestoreDefaultError)
val errorClearedState = consumeItemsUntilPredicate {
it.restoreDefaultAction.isUninitialized()
}.last()
assertThat(errorClearedState.restoreDefaultAction.isUninitialized()).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - display mentions only warning for a room if homeserver does not support it and it's encrypted`() = runTest {
val notificationService = FakeNotificationSettingsService().apply {
givenCanHomeServerPushEncryptedEventsToDeviceResult(Result.success(false))
}
val room = aJoinedRoom(notificationSettingsService = notificationService, isEncrypted = true)
val presenter = createRoomNotificationSettingsPresenter(notificationService, room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
assertThat(awaitLastSequentialItem().displayMentionsOnlyDisclaimer).isTrue()
}
}
@Test
fun `present - do not display mentions only warning for a room it's not encrypted`() = runTest {
val notificationService = FakeNotificationSettingsService().apply {
givenCanHomeServerPushEncryptedEventsToDeviceResult(Result.success(false))
}
val room = aJoinedRoom(notificationSettingsService = notificationService, isEncrypted = false)
val presenter = createRoomNotificationSettingsPresenter(notificationService, room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
assertThat(awaitLastSequentialItem().displayMentionsOnlyDisclaimer).isFalse()
}
}
private fun createRoomNotificationSettingsPresenter(
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
room: FakeJoinedRoom = aJoinedRoom(notificationSettingsService = notificationSettingsService),
): RoomNotificationSettingsPresenter {
return RoomNotificationSettingsPresenter(
room = room,
notificationSettingsService = notificationSettingsService,
showUserDefinedSettingStyle = false,
)
}
}