Merge branch 'develop' into renovate/kotlin
This commit is contained in:
commit
56df011930
450 changed files with 4051 additions and 1909 deletions
2
.github/workflows/danger.yml
vendored
2
.github/workflows/danger.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
- run: |
|
||||
npm install --save-dev @babel/plugin-transform-flow-strip-types
|
||||
- name: Danger
|
||||
uses: danger/danger-js@12.3.3
|
||||
uses: danger/danger-js@12.3.4
|
||||
with:
|
||||
args: "--dangerfile ./tools/danger/dangerfile.js"
|
||||
env:
|
||||
|
|
|
|||
2
.github/workflows/quality.yml
vendored
2
.github/workflows/quality.yml
vendored
|
|
@ -294,7 +294,7 @@ jobs:
|
|||
yarn add danger-plugin-lint-report --dev
|
||||
- name: Danger lint
|
||||
if: always()
|
||||
uses: danger/danger-js@12.3.3
|
||||
uses: danger/danger-js@12.3.4
|
||||
with:
|
||||
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
|
||||
env:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
<locale android:name="ru"/>
|
||||
<locale android:name="sk"/>
|
||||
<locale android:name="sv"/>
|
||||
<locale android:name="tr"/>
|
||||
<locale android:name="uk"/>
|
||||
<locale android:name="uz"/>
|
||||
<locale android:name="zh-CN"/>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<network-security-config xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Ref: https://developer.android.com/training/articles/security-config.html -->
|
||||
<!-- By default, do not allow clearText traffic -->
|
||||
<base-config cleartextTrafficPermitted="false" />
|
||||
<base-config cleartextTrafficPermitted="false">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates
|
||||
src="user"
|
||||
tools:ignore="AcceptsUserCertificates" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
|
||||
<!-- Allow clearText traffic on some specified host -->
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
|
|
@ -24,12 +31,4 @@
|
|||
<domain includeSubdomains="true">lan</domain>
|
||||
<domain includeSubdomains="true">localdomain</domain>
|
||||
</domain-config>
|
||||
|
||||
<debug-overrides>
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
</trust-anchors>
|
||||
</debug-overrides>
|
||||
|
||||
</network-security-config>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ 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.verification.SessionVerificationRequestDetails
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationServiceListener
|
||||
import io.element.android.libraries.preferences.api.store.EnableNativeSlidingSyncUseCase
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
|
@ -105,7 +104,6 @@ class LoggedInFlowNode @AssistedInject constructor(
|
|||
private val sendingQueue: SendQueues,
|
||||
private val logoutEntryPoint: LogoutEntryPoint,
|
||||
private val incomingVerificationEntryPoint: IncomingVerificationEntryPoint,
|
||||
private val enableNativeSlidingSyncUseCase: EnableNativeSlidingSyncUseCase,
|
||||
snackbarDispatcher: SnackbarDispatcher,
|
||||
) : BaseFlowNode<LoggedInFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
|
|
@ -420,9 +418,6 @@ class LoggedInFlowNode @AssistedInject constructor(
|
|||
}
|
||||
|
||||
logoutEntryPoint.nodeBuilder(this, buildContext)
|
||||
.onSuccessfulLogoutPendingAction {
|
||||
enableNativeSlidingSyncUseCase()
|
||||
}
|
||||
.callback(callback)
|
||||
.build()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.appnav.di
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -21,9 +22,9 @@ import kotlinx.coroutines.FlowPreview
|
|||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
|
@ -53,13 +54,28 @@ class SyncOrchestrator @AssistedInject constructor(
|
|||
*
|
||||
* Before observing the state, a first attempt at starting the sync service will happen if it's not already running.
|
||||
*/
|
||||
@OptIn(FlowPreview::class)
|
||||
fun start() {
|
||||
if (!started.compareAndSet(false, true)) {
|
||||
Timber.tag(tag).d("already started, exiting early")
|
||||
return
|
||||
}
|
||||
|
||||
coroutineScope.launch {
|
||||
// Perform an initial sync if the sync service is not running, to check whether the homeserver is accessible
|
||||
// Otherwise, if the device is offline the sync service will never start and the SyncState will be Idle, not Offline
|
||||
Timber.tag(tag).d("performing initial sync attempt")
|
||||
syncService.startSync()
|
||||
|
||||
// Wait until the sync service is not idle, either it will be running or in error/offline state
|
||||
syncService.syncState.first { it != SyncState.Idle }
|
||||
|
||||
observeStates()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
internal fun observeStates() = coroutineScope.launch {
|
||||
Timber.tag(tag).d("start observing the app and network state")
|
||||
|
||||
combine(
|
||||
|
|
@ -76,7 +92,7 @@ class SyncOrchestrator @AssistedInject constructor(
|
|||
Timber.tag(tag).d("isAppActive=$isAppActive, isNetworkAvailable=$isNetworkAvailable")
|
||||
if (syncState == SyncState.Running && !isAppActive) {
|
||||
SyncStateAction.StopSync
|
||||
} else if (syncState != SyncState.Running && isAppActive && isNetworkAvailable) {
|
||||
} else if (syncState == SyncState.Idle && isAppActive && isNetworkAvailable) {
|
||||
SyncStateAction.StartSync
|
||||
} else {
|
||||
SyncStateAction.NoOp
|
||||
|
|
@ -87,7 +103,10 @@ class SyncOrchestrator @AssistedInject constructor(
|
|||
// Don't stop the sync immediately, wait a bit to avoid starting/stopping the sync too often
|
||||
if (action == SyncStateAction.StopSync) 3.seconds else 0.seconds
|
||||
}
|
||||
.onEach { action ->
|
||||
.onCompletion {
|
||||
Timber.tag(tag).d("has been stopped")
|
||||
}
|
||||
.collect { action ->
|
||||
when (action) {
|
||||
SyncStateAction.StartSync -> {
|
||||
syncService.startSync()
|
||||
|
|
@ -98,10 +117,6 @@ class SyncOrchestrator @AssistedInject constructor(
|
|||
SyncStateAction.NoOp -> Unit
|
||||
}
|
||||
}
|
||||
.onCompletion {
|
||||
Timber.tag(tag).d("has been stopped")
|
||||
}
|
||||
.launchIn(coroutineScope)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import im.vector.app.features.analytics.plan.UserProperties
|
|||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
|
|
@ -31,7 +32,6 @@ import io.element.android.libraries.matrix.api.sync.SyncService
|
|||
import io.element.android.libraries.matrix.api.sync.isOnline
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.preferences.api.store.EnableNativeSlidingSyncUseCase
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.pushproviders.api.RegistrationFailure
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
|
|
@ -51,7 +51,7 @@ class LoggedInPresenter @Inject constructor(
|
|||
private val sessionVerificationService: SessionVerificationService,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val encryptionService: EncryptionService,
|
||||
private val enableNativeSlidingSyncUseCase: EnableNativeSlidingSyncUseCase,
|
||||
private val buildMeta: BuildMeta,
|
||||
) : Presenter<LoggedInState> {
|
||||
@Composable
|
||||
override fun present(): LoggedInState {
|
||||
|
|
@ -103,12 +103,10 @@ class LoggedInPresenter @Inject constructor(
|
|||
}
|
||||
}
|
||||
LoggedInEvents.CheckSlidingSyncProxyAvailability -> coroutineScope.launch {
|
||||
forceNativeSlidingSyncMigration = matrixClient.forceNativeSlidingSyncMigration().getOrDefault(false)
|
||||
forceNativeSlidingSyncMigration = matrixClient.needsForcedNativeSlidingSyncMigration().getOrDefault(false)
|
||||
}
|
||||
LoggedInEvents.LogoutAndMigrateToNativeSlidingSync -> coroutineScope.launch {
|
||||
// Enable native sliding sync if it wasn't already the case
|
||||
enableNativeSlidingSyncUseCase()
|
||||
// Then force the logout
|
||||
// Force the logout since Native Sliding Sync is already enforced by the SDK
|
||||
matrixClient.logout(userInitiated = true, ignoreSdkError = true)
|
||||
}
|
||||
}
|
||||
|
|
@ -119,20 +117,15 @@ class LoggedInPresenter @Inject constructor(
|
|||
pusherRegistrationState = pusherRegistrationState.value,
|
||||
ignoreRegistrationError = ignoreRegistrationError,
|
||||
forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration,
|
||||
appName = buildMeta.applicationName,
|
||||
eventSink = ::handleEvent
|
||||
)
|
||||
}
|
||||
|
||||
// Force the user to log out if they were using the proxy sliding sync and it's no longer available, but native sliding sync is.
|
||||
private suspend fun MatrixClient.forceNativeSlidingSyncMigration(): Result<Boolean> = runCatching {
|
||||
// Force the user to log out if they were using the proxy sliding sync as it's no longer supported by the SDK
|
||||
private suspend fun MatrixClient.needsForcedNativeSlidingSyncMigration(): Result<Boolean> = runCatching {
|
||||
val currentSlidingSyncVersion = currentSlidingSyncVersion().getOrThrow()
|
||||
if (currentSlidingSyncVersion == SlidingSyncVersion.Proxy) {
|
||||
val availableSlidingSyncVersions = availableSlidingSyncVersions().getOrThrow()
|
||||
availableSlidingSyncVersions.contains(SlidingSyncVersion.Native) &&
|
||||
!availableSlidingSyncVersions.contains(SlidingSyncVersion.Proxy)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
currentSlidingSyncVersion == SlidingSyncVersion.Proxy
|
||||
}
|
||||
|
||||
private suspend fun ensurePusherIsRegistered(pusherRegistrationState: MutableState<AsyncData<Unit>>) {
|
||||
|
|
|
|||
|
|
@ -14,5 +14,6 @@ data class LoggedInState(
|
|||
val pusherRegistrationState: AsyncData<Unit>,
|
||||
val ignoreRegistrationError: Boolean,
|
||||
val forceNativeSlidingSyncMigration: Boolean,
|
||||
val appName: String,
|
||||
val eventSink: (LoggedInEvents) -> Unit,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,10 +24,12 @@ fun aLoggedInState(
|
|||
showSyncSpinner: Boolean = false,
|
||||
pusherRegistrationState: AsyncData<Unit> = AsyncData.Uninitialized,
|
||||
forceNativeSlidingSyncMigration: Boolean = false,
|
||||
appName: String = "Element X",
|
||||
) = LoggedInState(
|
||||
showSyncSpinner = showSyncSpinner,
|
||||
pusherRegistrationState = pusherRegistrationState,
|
||||
ignoreRegistrationError = false,
|
||||
forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration,
|
||||
appName = appName,
|
||||
eventSink = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -73,9 +73,12 @@ fun LoggedInView(
|
|||
|
||||
// Set the force migration dialog here so it's always displayed over every screen
|
||||
if (state.forceNativeSlidingSyncMigration) {
|
||||
ForceNativeSlidingSyncMigrationDialog(onSubmit = {
|
||||
state.eventSink(LoggedInEvents.LogoutAndMigrateToNativeSlidingSync)
|
||||
})
|
||||
ForceNativeSlidingSyncMigrationDialog(
|
||||
appName = state.appName,
|
||||
onSubmit = {
|
||||
state.eventSink(LoggedInEvents.LogoutAndMigrateToNativeSlidingSync)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,11 +101,12 @@ private fun Throwable.getReason(): String? {
|
|||
|
||||
@Composable
|
||||
private fun ForceNativeSlidingSyncMigrationDialog(
|
||||
appName: String,
|
||||
onSubmit: () -> Unit,
|
||||
) {
|
||||
ErrorDialog(
|
||||
title = null,
|
||||
content = stringResource(R.string.banner_migrate_to_native_sliding_sync_force_logout_title),
|
||||
content = stringResource(R.string.banner_migrate_to_native_sliding_sync_app_force_logout_title, appName),
|
||||
submitText = stringResource(R.string.banner_migrate_to_native_sliding_sync_action),
|
||||
onSubmit = onSubmit,
|
||||
canDismiss = false,
|
||||
|
|
|
|||
5
appnav/src/main/res/values-tr/translations.xml
Normal file
5
appnav/src/main/res/values-tr/translations.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="banner_migrate_to_native_sliding_sync_action">"Çıkış Yap ve Yükselt"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_force_logout_title">"Ana sunucunuz artık eski protokolü desteklemiyor. Lütfen oturumu kapatın ve uygulamayı kullanmaya devam etmek için tekrar oturum açın."</string>
|
||||
</resources>
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="banner_migrate_to_native_sliding_sync_action">"Log Out & Upgrade"</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_app_force_logout_title">"%1$s no longer supports the old protocol. Please log out and log back in to continue using the app."</string>
|
||||
<string name="banner_migrate_to_native_sliding_sync_force_logout_title">"Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,50 @@ class SyncOrchestratorTest {
|
|||
@get:Rule
|
||||
val warmUpRule = WarmUpRule()
|
||||
|
||||
@Test
|
||||
fun `when the sync wasn't running before, an initial sync will take place, even with no network`() = runTest {
|
||||
val startSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
val syncService = FakeSyncService(initialSyncState = SyncState.Idle).apply {
|
||||
startSyncLambda = startSyncRecorder
|
||||
}
|
||||
val networkMonitor = FakeNetworkMonitor(initialStatus = NetworkStatus.Disconnected)
|
||||
val syncOrchestrator = createSyncOrchestrator(
|
||||
syncService = syncService,
|
||||
networkMonitor = networkMonitor,
|
||||
)
|
||||
|
||||
// We start observing with an initial sync
|
||||
syncOrchestrator.start()
|
||||
|
||||
// Advance the time just enough to make sure the initial sync has run
|
||||
advanceTimeBy(1.milliseconds)
|
||||
startSyncRecorder.assertions().isCalledOnce()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when the sync wasn't running before, an initial sync will take place`() = runTest {
|
||||
val startSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
val syncService = FakeSyncService(initialSyncState = SyncState.Idle).apply {
|
||||
startSyncLambda = startSyncRecorder
|
||||
}
|
||||
val networkMonitor = FakeNetworkMonitor(initialStatus = NetworkStatus.Connected)
|
||||
val syncOrchestrator = createSyncOrchestrator(
|
||||
syncService = syncService,
|
||||
networkMonitor = networkMonitor,
|
||||
)
|
||||
|
||||
// We start observing with an initial sync
|
||||
syncOrchestrator.start()
|
||||
|
||||
// Advance the time just enough to make sure the initial sync has run
|
||||
advanceTimeBy(1.milliseconds)
|
||||
startSyncRecorder.assertions().isCalledOnce()
|
||||
|
||||
// If we wait for a while, the sync will not be started again by the observer since it's already running
|
||||
advanceTimeBy(10.seconds)
|
||||
startSyncRecorder.assertions().isCalledOnce()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when the app goes to background and the sync was running, it will be stopped after a delay`() = runTest {
|
||||
val stopSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
|
|
@ -46,7 +90,7 @@ class SyncOrchestratorTest {
|
|||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.start()
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
// Advance the time to make sure the orchestrator has had time to start processing the inputs
|
||||
advanceTimeBy(100.milliseconds)
|
||||
|
|
@ -78,7 +122,7 @@ class SyncOrchestratorTest {
|
|||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.start()
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
// Advance the time to make sure the orchestrator has had time to start processing the inputs
|
||||
advanceTimeBy(100.milliseconds)
|
||||
|
|
@ -126,7 +170,7 @@ class SyncOrchestratorTest {
|
|||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.start()
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
// Advance the time to make sure the orchestrator has had time to start processing the inputs
|
||||
advanceTimeBy(100.milliseconds)
|
||||
|
|
@ -169,7 +213,7 @@ class SyncOrchestratorTest {
|
|||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.start()
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
// Advance the time to make sure the orchestrator has had time to start processing the inputs
|
||||
advanceTimeBy(100.milliseconds)
|
||||
|
|
@ -213,7 +257,7 @@ class SyncOrchestratorTest {
|
|||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.start()
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
// Advance the time to make sure the orchestrator has had time to start processing the inputs
|
||||
advanceTimeBy(100.milliseconds)
|
||||
|
|
@ -256,7 +300,7 @@ class SyncOrchestratorTest {
|
|||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.start()
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
// Advance the time to make sure the orchestrator has had time to start processing the inputs
|
||||
advanceTimeBy(100.milliseconds)
|
||||
|
|
@ -285,7 +329,7 @@ class SyncOrchestratorTest {
|
|||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.start()
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
// This should still not trigger a sync, since there is no network
|
||||
advanceTimeBy(10.seconds)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import app.cash.turbine.test
|
|||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.CryptoSessionStateChange
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
|
|
@ -26,12 +27,11 @@ import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatu
|
|||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||
import io.element.android.libraries.matrix.test.sync.FakeSyncService
|
||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||
import io.element.android.libraries.preferences.api.store.EnableNativeSlidingSyncUseCase
|
||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.push.test.FakePushService
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
|
|
@ -46,7 +46,6 @@ 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 kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.runTest
|
||||
|
|
@ -92,6 +91,7 @@ class LoggedInPresenterTest {
|
|||
val roomListService = FakeRoomListService()
|
||||
val verificationService = FakeSessionVerificationService()
|
||||
val encryptionService = FakeEncryptionService()
|
||||
val buildMeta = aBuildMeta()
|
||||
val presenter = LoggedInPresenter(
|
||||
matrixClient = FakeMatrixClient(roomListService = roomListService, encryptionService = encryptionService),
|
||||
syncService = FakeSyncService(initialSyncState = SyncState.Running),
|
||||
|
|
@ -99,7 +99,7 @@ class LoggedInPresenterTest {
|
|||
sessionVerificationService = verificationService,
|
||||
analyticsService = analyticsService,
|
||||
encryptionService = encryptionService,
|
||||
enableNativeSlidingSyncUseCase = EnableNativeSlidingSyncUseCase(InMemoryAppPreferencesStore(), this),
|
||||
buildMeta = buildMeta,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -518,28 +518,9 @@ class LoggedInPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - CheckSlidingSyncProxyAvailability will not force the migration if native sliding sync is not supported too`() = runTest {
|
||||
val matrixClient = FakeMatrixClient(
|
||||
currentSlidingSyncVersionLambda = { Result.success(SlidingSyncVersion.Proxy) },
|
||||
availableSlidingSyncVersionsLambda = { Result.success(emptyList()) },
|
||||
)
|
||||
val presenter = createLoggedInPresenter(matrixClient = matrixClient)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.forceNativeSlidingSyncMigration).isFalse()
|
||||
|
||||
initialState.eventSink(LoggedInEvents.CheckSlidingSyncProxyAvailability)
|
||||
|
||||
expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Test
|
||||
fun `present - LogoutAndMigrateToNativeSlidingSync enables native sliding sync and logs out the user`() = runTest {
|
||||
fun `present - LogoutAndMigrateToNativeSlidingSync logs out the user`() = runTest {
|
||||
val logoutLambda = lambdaRecorder<Boolean, Boolean, String?> { userInitiated, ignoreSdkError ->
|
||||
assertThat(userInitiated).isTrue()
|
||||
assertThat(ignoreSdkError).isTrue()
|
||||
|
|
@ -548,21 +529,16 @@ class LoggedInPresenterTest {
|
|||
val matrixClient = FakeMatrixClient().apply {
|
||||
this.logoutLambda = logoutLambda
|
||||
}
|
||||
val appPreferencesStore = InMemoryAppPreferencesStore()
|
||||
val enableNativeSlidingSyncUseCase = EnableNativeSlidingSyncUseCase(appPreferencesStore, this)
|
||||
val presenter = createLoggedInPresenter(matrixClient = matrixClient, enableNativeSlidingSyncUseCase = enableNativeSlidingSyncUseCase)
|
||||
val presenter = createLoggedInPresenter(matrixClient = matrixClient)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
|
||||
assertThat(appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()).isFalse()
|
||||
|
||||
initialState.eventSink(LoggedInEvents.LogoutAndMigrateToNativeSlidingSync)
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
assertThat(appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()).isTrue()
|
||||
assertThat(logoutLambda.assertions().isCalledOnce())
|
||||
}
|
||||
}
|
||||
|
|
@ -579,8 +555,8 @@ class LoggedInPresenterTest {
|
|||
sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(),
|
||||
encryptionService: EncryptionService = FakeEncryptionService(),
|
||||
pushService: PushService = FakePushService(),
|
||||
enableNativeSlidingSyncUseCase: EnableNativeSlidingSyncUseCase = EnableNativeSlidingSyncUseCase(InMemoryAppPreferencesStore(), this),
|
||||
matrixClient: MatrixClient = FakeMatrixClient(roomListService = roomListService),
|
||||
buildMeta: BuildMeta = aBuildMeta(),
|
||||
): LoggedInPresenter {
|
||||
return LoggedInPresenter(
|
||||
matrixClient = matrixClient,
|
||||
|
|
@ -589,7 +565,7 @@ class LoggedInPresenterTest {
|
|||
sessionVerificationService = sessionVerificationService,
|
||||
analyticsService = analyticsService,
|
||||
encryptionService = encryptionService,
|
||||
enableNativeSlidingSyncUseCase = enableNativeSlidingSyncUseCase,
|
||||
buildMeta = buildMeta,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_analytics_settings_help_us_improve">"Sorunları tanımlamamıza yardımcı olmak için anonim kullanım verilerini paylaşın."</string>
|
||||
<string name="screen_analytics_settings_read_terms">"Tüm şartlarımızı okuyabilirsiniz %1$s."</string>
|
||||
<string name="screen_analytics_settings_read_terms_content_link">"burada"</string>
|
||||
<string name="screen_analytics_settings_share_data">"Analitik verileri paylaşın"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_analytics_prompt_data_usage">"Hiçbir kişisel veriyi kaydetmeyeceğiz veya profillemeyeceğiz"</string>
|
||||
<string name="screen_analytics_prompt_help_us_improve">"Sorunları tanımlamamıza yardımcı olmak için anonim kullanım verilerini paylaşın."</string>
|
||||
<string name="screen_analytics_prompt_read_terms">"Tüm şartlarımızı okuyabilirsiniz %1$s."</string>
|
||||
<string name="screen_analytics_prompt_read_terms_content_link">"burada"</string>
|
||||
<string name="screen_analytics_prompt_settings">"Bu özelliği istediğiniz zaman kapatabilirsiniz"</string>
|
||||
<string name="screen_analytics_prompt_third_party_sharing">"Verilerinizi üçüncü taraflarla paylaşmayacağız"</string>
|
||||
<string name="screen_analytics_prompt_title">"%1$s geliştirilmesine yardımcı olun"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="call_foreground_service_channel_title_android">"Devam eden çağrı"</string>
|
||||
<string name="call_foreground_service_message_android">"Aramaya geri dönmek için dokunun"</string>
|
||||
<string name="call_foreground_service_title_android">"☎️ Çağrı devam ediyor"</string>
|
||||
<string name="screen_incoming_call_subtitle_android">"Gelen Element Call"</string>
|
||||
</resources>
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
<string name="screen_create_room_private_option_description">"Паведамленні ў гэтым пакоі зашыфраваны. Гэта шыфраванне нельга адключыць."</string>
|
||||
<string name="screen_create_room_private_option_title">"Прыватны пакой (толькі па запрашэнні)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Паведамленні не зашыфраваны, і кожны можа іх прачытаць. Вы можаце ўключыць шыфраванне пазней."</string>
|
||||
<string name="screen_create_room_public_option_title">"Публічны пакой (для ўсіх)"</string>
|
||||
<string name="screen_create_room_public_option_title">"Публічны пакой"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_title">"Хто заўгодна"</string>
|
||||
<string name="screen_create_room_room_access_section_header">"Доступ у пакой"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Папрасіце далучыцца"</string>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<string name="screen_create_room_private_option_description">"Съобщенията в тази стая са шифровани. Шифроването не може да бъде изключено впоследствие."</string>
|
||||
<string name="screen_create_room_private_option_title">"Частна стая (само с покана)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Съобщенията не са шифровани и всеки може да ги прочете. Можете да активирате шифроването на по-късна дата."</string>
|
||||
<string name="screen_create_room_public_option_title">"Публична стая (всеки)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Име на стаята"</string>
|
||||
<string name="screen_create_room_title">"Създаване на стая"</string>
|
||||
<string name="screen_create_room_topic_label">"Тема за разговор (незадължително)"</string>
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
<string name="screen_create_room_private_option_title">"Privater Chatroom"</string>
|
||||
<string name="screen_create_room_public_option_description">"Jeder kann diesen Chatroom finden.
|
||||
Sie können dies aber jederzeit in den Chatroomeinstellungen ändern."</string>
|
||||
<string name="screen_create_room_public_option_title">"Öffentlicher Chatroom"</string>
|
||||
<string name="screen_create_room_public_option_title">"Öffentlicher Raum"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_description">"Jeder kann diesem Chatroom beitreten"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_title">"Jemand"</string>
|
||||
<string name="screen_create_room_room_access_section_header">"Chatroom Zugang"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_description">"Jeder kann darum bitten, dem Chatroom beizutreten, aber ein Administrator oder ein Moderator muss die Anfrage akzeptieren."</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Beitritt beantragen"</string>
|
||||
<string name="screen_create_room_room_address_section_footer">"Damit dieser Chatroom im öffentlichen Chatroomverzeichnis sichtbar ist, benötigen Sie eine Chatroomadresse."</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Chatroom Adresse"</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Chatroomadresse"</string>
|
||||
<string name="screen_create_room_room_name_label">"Raumname"</string>
|
||||
<string name="screen_create_room_room_visibility_section_title">" Sichtbarkeit des Chatrooms"</string>
|
||||
<string name="screen_create_room_title">"Raum erstellen"</string>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
<string name="screen_create_room_room_access_section_knocking_option_description">"Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Αίτημα συμμετοχής"</string>
|
||||
<string name="screen_create_room_room_address_section_footer">"Για να είναι ορατό αυτό το δωμάτιο στον κατάλογο των δημόσιων δωματίων, θα χρειαστείς μια διεύθυνση δωματίου."</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Διεύθυνση δωματίου"</string>
|
||||
<string name="screen_create_room_room_name_label">"Όνομα δωματίου"</string>
|
||||
<string name="screen_create_room_room_visibility_section_title">"Ορατότητα δωματίου"</string>
|
||||
<string name="screen_create_room_title">"Δημιούργησε ένα δωμάτιο"</string>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<string name="screen_create_room_private_option_description">"Los mensajes de esta sala están cifrados. La encriptación no se puede desactivar después."</string>
|
||||
<string name="screen_create_room_private_option_title">"Sala privada (sólo con invitación)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Los mensajes no están cifrados y cualquiera puede leerlos. Puedes activar la encriptación más adelante."</string>
|
||||
<string name="screen_create_room_public_option_title">"Sala pública (cualquiera)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Nombre de la sala"</string>
|
||||
<string name="screen_create_room_title">"Crear una sala"</string>
|
||||
<string name="screen_create_room_topic_label">"Tema (opcional)"</string>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<string name="screen_create_room_private_option_description">"پیامهای این اتاق رمز شدهاند. رمزنگاری نمیتواند از این پس تغییر کند."</string>
|
||||
<string name="screen_create_room_private_option_title">"اتاق خصوصی (فقط دعوت)"</string>
|
||||
<string name="screen_create_room_public_option_description">"پیامها رمزنگاری نشده و هرکسی میتواند بخواندشان. میتوانید بعداً رمزنگاری را به کار بیندازید."</string>
|
||||
<string name="screen_create_room_public_option_title">"اتاق عمومی (هرکسی)"</string>
|
||||
<string name="screen_create_room_public_option_title">"اتاق عمومی"</string>
|
||||
<string name="screen_create_room_room_name_label">"نام اتاق"</string>
|
||||
<string name="screen_create_room_title">"ایجاد اتاق"</string>
|
||||
<string name="screen_create_room_topic_label">"موضوع (اختیاری)"</string>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Ezt bármikor módosíthatja a szobabeállításokban."</string>
|
|||
<string name="screen_create_room_room_access_section_knocking_option_description">"Bárki kérheti, hogy csatlakozzon a szobához, de egy adminisztrátornak vagy moderátornak el kell fogadnia a kérést"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Csatlakozás kérése"</string>
|
||||
<string name="screen_create_room_room_address_section_footer">"Ahhoz, hogy ez a szoba látható legyen a nyilvános szobák címtárában, meg kell adnia a szoba címét."</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Szoba címe"</string>
|
||||
<string name="screen_create_room_room_address_section_title">"A szoba címe"</string>
|
||||
<string name="screen_create_room_room_name_label">"Szoba neve"</string>
|
||||
<string name="screen_create_room_room_visibility_section_title">"Szoba láthatósága"</string>
|
||||
<string name="screen_create_room_title">"Szoba létrehozása"</string>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ Anda dapat mengubah ini kapan pun dalam pengaturan ruangan."</string>
|
|||
<string name="screen_create_room_room_access_section_knocking_option_description">"Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Minta untuk bergabung"</string>
|
||||
<string name="screen_create_room_room_address_section_footer">"Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan."</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Alamat ruangan"</string>
|
||||
<string name="screen_create_room_room_name_label">"Nama ruangan"</string>
|
||||
<string name="screen_create_room_room_visibility_section_title">"Keterlihatan ruangan"</string>
|
||||
<string name="screen_create_room_title">"Buat ruangan"</string>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
<string name="screen_create_room_private_option_title">"კერძო ოთახი"</string>
|
||||
<string name="screen_create_room_public_option_description">"ყველას ამ ოთახის მოძებნა შეუძლია.
|
||||
თქვენ ნებისმიერ დროს შეგიძლიათ ამის შეცვლა ოთახის პარამეტრებში."</string>
|
||||
<string name="screen_create_room_public_option_title">"საჯარო ოთახი"</string>
|
||||
<string name="screen_create_room_room_name_label">"ოთახის სახელი"</string>
|
||||
<string name="screen_create_room_title">"ოთახის შექმნა"</string>
|
||||
<string name="screen_create_room_topic_label">"თემა (სურვილისამებრ)"</string>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
<string name="screen_create_room_private_option_title">"Sala privativa (somente por convite)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Qualquer um pode encontrar esta sala.
|
||||
Você pode mudar isso a qualquer momento nas configurações da sala."</string>
|
||||
<string name="screen_create_room_public_option_title">"Sala pública (qualquer pessoa)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Nome da sala"</string>
|
||||
<string name="screen_create_room_title">"Criar uma sala"</string>
|
||||
<string name="screen_create_room_topic_label">"Tópico (opcional)"</string>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<string name="screen_create_room_action_create_room">"Nova sala"</string>
|
||||
<string name="screen_create_room_add_people_title">"Convidar pessoas"</string>
|
||||
<string name="screen_create_room_error_creating_room">"Ocorreu um erro ao criar a sala"</string>
|
||||
<string name="screen_create_room_private_option_description">"Apenas as pessoas convidadas podem aceder a esta sala. Todas as mensagens são encriptadas ponta a ponta."</string>
|
||||
<string name="screen_create_room_private_option_description">"Apenas as pessoas convidadas podem aceder a esta sala. Todas as mensagens são cifradas ponta-a-ponta."</string>
|
||||
<string name="screen_create_room_private_option_title">"Sala privada"</string>
|
||||
<string name="screen_create_room_public_option_description">"Qualquer um pode encontrar esta sala.
|
||||
Pode alterar esta opção nas definições da sala."</string>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ Puteți modifica acest lucru oricând în setări."</string>
|
|||
<string name="screen_create_room_room_access_section_knocking_option_description">"Oricine poate cere să se alăture camerei, dar un administrator sau un moderator va trebui să accepte solicitarea"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Cereți să vă alăturați"</string>
|
||||
<string name="screen_create_room_room_address_section_footer">"Pentru ca această cameră să fie vizibilă în directorul de camere publice, veți avea nevoie de o adresă de cameră."</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Adresa camerei"</string>
|
||||
<string name="screen_create_room_room_name_label">"Numele camerei"</string>
|
||||
<string name="screen_create_room_title">"Creați o cameră"</string>
|
||||
<string name="screen_create_room_topic_label">"Subiect (opțional)"</string>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ Du kan ändra detta när som helst i rumsinställningarna."</string>
|
|||
<string name="screen_create_room_room_access_section_header">"Rumsåtkomst"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_description">"Vem som helst kan be om att gå med i rummet men en administratör eller en moderator måste acceptera begäran"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Be om att gå med"</string>
|
||||
<string name="screen_create_room_room_address_section_footer">"För att detta rum ska vara synligt i den allmänna rumskatalogen behöver du en rumsadress."</string>
|
||||
<string name="screen_create_room_room_name_label">"Rumsnamn"</string>
|
||||
<string name="screen_create_room_room_visibility_section_title">"Rumssynlighet"</string>
|
||||
<string name="screen_create_room_title">"Skapa ett rum"</string>
|
||||
<string name="screen_create_room_topic_label">"Ämne (valfritt)"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Ett fel uppstod när du försökte starta en chatt"</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_create_room_action_create_room">"Yeni oda"</string>
|
||||
<string name="screen_create_room_add_people_title">"İnsanları davet et"</string>
|
||||
<string name="screen_create_room_error_creating_room">"Oda oluşturulurken bir hata oluştu"</string>
|
||||
<string name="screen_create_room_private_option_description">"Bu odaya yalnızca davet edilen kişiler erişebilir. Tüm mesajlar uçtan uca şifrelenir."</string>
|
||||
<string name="screen_create_room_private_option_title">"Özel oda"</string>
|
||||
<string name="screen_create_room_public_option_description">"Bu odayı herkes bulabilir.
|
||||
Bunu istediğiniz zaman oda ayarlarından değiştirebilirsiniz."</string>
|
||||
<string name="screen_create_room_public_option_title">"Herkese açık oda"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_description">"Bu odaya herkes katılabilir"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_title">"Herkes"</string>
|
||||
<string name="screen_create_room_room_access_section_header">"Oda Erişimi"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_description">"Herkes odaya katılmayı isteyebilir ancak bir yönetici veya moderatörün isteği kabul etmesi gerekecektir"</string>
|
||||
<string name="screen_create_room_room_access_section_knocking_option_title">"Katılmak için sor"</string>
|
||||
<string name="screen_create_room_room_address_section_footer">"Bu odanın genel oda dizininde görünür olması için bir oda adresine ihtiyacınız olacaktır."</string>
|
||||
<string name="screen_create_room_room_address_section_title">"Oda adresi"</string>
|
||||
<string name="screen_create_room_room_name_label">"Oda adı"</string>
|
||||
<string name="screen_create_room_room_visibility_section_title">"Oda görünürlüğü"</string>
|
||||
<string name="screen_create_room_title">"Bir oda oluştur"</string>
|
||||
<string name="screen_create_room_topic_label">"Konu (isteğe bağlı)"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Sohbet başlatmaya çalışırken bir hata oluştu"</string>
|
||||
</resources>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<string name="screen_create_room_private_option_title">"Приватна кімната (тільки за запрошенням)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Будь-хто може знайти цю кімнату.
|
||||
Ви можете змінити це в будь-який час у налаштуваннях кімнати."</string>
|
||||
<string name="screen_create_room_public_option_title">"Публічна кімната"</string>
|
||||
<string name="screen_create_room_public_option_title">"Загальнодоступна кімната"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_description">"Будь-хто може приєднатися до цієї кімнати"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_title">"Кожний"</string>
|
||||
<string name="screen_create_room_room_access_section_header">"Доступ до кімнати"</string>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<string name="screen_create_room_private_option_description">"Bu xonadagi xabarlar shifrlangan. Keyinchalik shifrlashni o‘chirib bo‘lmaydi."</string>
|
||||
<string name="screen_create_room_private_option_title">"Shaxsiy xona (faqat taklif)"</string>
|
||||
<string name="screen_create_room_public_option_description">"Xabarlar shifrlanmagan va har kim ularni o\'qiy oladi. Keyinchalik shifrlashni yoqishingiz mumkin."</string>
|
||||
<string name="screen_create_room_public_option_title">"Jamoat xonasi (har kim)"</string>
|
||||
<string name="screen_create_room_room_name_label">"Xona nomi"</string>
|
||||
<string name="screen_create_room_title">"Xonani yaratish"</string>
|
||||
<string name="screen_create_room_topic_label">"Mavzu (ixtiyoriy)"</string>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<string name="screen_create_room_private_option_title">"私密聊天室"</string>
|
||||
<string name="screen_create_room_public_option_description">"任何人都可以找到此聊天室。
|
||||
您隨時都可以在聊天室設定中變更此設定。"</string>
|
||||
<string name="screen_create_room_public_option_title">"公開聊天室"</string>
|
||||
<string name="screen_create_room_public_option_title">"公開的聊天室"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_description">"任何人都可以加入此聊天室"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_title">"任何人"</string>
|
||||
<string name="screen_create_room_room_access_section_header">"聊天室存取權"</string>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<string name="screen_create_room_private_option_title">"私有聊天室"</string>
|
||||
<string name="screen_create_room_public_option_description">"任何人都能找到此聊天室。
|
||||
你可以随时在聊天室设置中更改。"</string>
|
||||
<string name="screen_create_room_public_option_title">"公开聊天室"</string>
|
||||
<string name="screen_create_room_public_option_title">"公共聊天室"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_description">"任何人都可以加入此房间"</string>
|
||||
<string name="screen_create_room_room_access_section_anyone_option_title">"任何人"</string>
|
||||
<string name="screen_create_room_room_access_section_header">"房间访问权限"</string>
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@
|
|||
<string name="screen_deactivate_account_list_item_2">"Vous retirer de tous les salons et toutes les discussions."</string>
|
||||
<string name="screen_deactivate_account_list_item_3">"Supprimer les informations de votre compte du serveur d’identité."</string>
|
||||
<string name="screen_deactivate_account_list_item_4">"Rendre vos messages invisibles aux futurs membres des salons si vous choisissez de les supprimer. Vos messages seront toujours visibles pour les utilisateurs qui les ont déjà récupérés."</string>
|
||||
<string name="screen_deactivate_account_title">"Désactiver votre compte"</string>
|
||||
<string name="screen_deactivate_account_title">"Désactiver le compte"</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@
|
|||
<string name="screen_deactivate_account_list_item_2">"Ti rimuove da tutte le stanze di chat."</string>
|
||||
<string name="screen_deactivate_account_list_item_3">"Elimina le informazioni del tuo account dal nostro server di identità."</string>
|
||||
<string name="screen_deactivate_account_list_item_4">"I tuoi messaggi saranno ancora visibili agli utenti registrati, ma non saranno disponibili per gli utenti nuovi o non registrati se decidi di eliminarli."</string>
|
||||
<string name="screen_deactivate_account_title">"Disattivazione dell\'account"</string>
|
||||
<string name="screen_deactivate_account_title">"Disattiva account"</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_deactivate_account_confirmation_dialog_content">"Lütfen hesabınızı devre dışı bırakmak istediğinizi onaylayın. Bu işlem geri alınamaz."</string>
|
||||
<string name="screen_deactivate_account_delete_all_messages">"Tüm mesajlarımı sil"</string>
|
||||
<string name="screen_deactivate_account_delete_all_messages_notice">"Uyarı: Gelecekteki kullanıcılar eksik konuşmalar görebilir."</string>
|
||||
<string name="screen_deactivate_account_description">"Hesabınızı devre dışı bırakmak %1$s, şunları yapacaktır:"</string>
|
||||
<string name="screen_deactivate_account_description_bold_part">"geri alınamaz"</string>
|
||||
<string name="screen_deactivate_account_list_item_1">"%1$s (tekrar giriş yapamazsınız ve kimliğiniz yeniden kullanılamaz)."</string>
|
||||
<string name="screen_deactivate_account_list_item_1_bold_part">"Kalıcı olarak devre dışı bırak"</string>
|
||||
<string name="screen_deactivate_account_list_item_2">"Sizi tüm sohbet odalarından çıkarmak."</string>
|
||||
<string name="screen_deactivate_account_list_item_3">"Hesap bilgileriniz kimlik sunucumuzdan silinecek."</string>
|
||||
<string name="screen_deactivate_account_list_item_4">"Mesajlarınız kayıtlı kullanıcılar tarafından görülmeye devam eder, ancak silmeyi seçerseniz yeni veya kayıtlı olmayan kullanıcılar tarafından görüntülenemeyecek."</string>
|
||||
<string name="screen_deactivate_account_title">"Hesabı devre dışı bırak"</string>
|
||||
</resources>
|
||||
|
|
@ -10,5 +10,5 @@
|
|||
<string name="screen_deactivate_account_list_item_2">"Видалити вас з усіх чатів."</string>
|
||||
<string name="screen_deactivate_account_list_item_3">"Видаліть інформацію свого облікового запису з нашого сервера ідентифікації."</string>
|
||||
<string name="screen_deactivate_account_list_item_4">"Ваші повідомлення залишатимуться видимими для зареєстрованих користувачів, але недоступними для нових або незареєстрованих користувачів, якщо ви вирішите їх видалити."</string>
|
||||
<string name="screen_deactivate_account_title">"Відключити обліковий запис"</string>
|
||||
<string name="screen_deactivate_account_title">"Деактивувати обліковий запис"</string>
|
||||
</resources>
|
||||
|
|
|
|||
11
features/ftue/impl/src/main/res/values-tr/translations.xml
Normal file
11
features/ftue/impl/src/main/res/values-tr/translations.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_notification_optin_subtitle">"Ayarlarınızı daha sonra değiştirebilirsiniz."</string>
|
||||
<string name="screen_notification_optin_title">"Bildirimlere izin verin ve hiçbir mesajı kaçırmayın"</string>
|
||||
<string name="screen_welcome_bullet_1">"Çağrılar, anketler, arama ve daha fazlası bu yıl içinde eklenecek."</string>
|
||||
<string name="screen_welcome_bullet_2">"Şifrelenmiş odalar için mesaj geçmişi henüz mevcut değil."</string>
|
||||
<string name="screen_welcome_bullet_3">"Düşüncelerinizi bizimle paylaşmanızı çok isteriz. Ayarlar sayfasından düşüncelerinizi bize iletin."</string>
|
||||
<string name="screen_welcome_button">"Hadi başlayalım!"</string>
|
||||
<string name="screen_welcome_subtitle">"İşte bilmeniz gerekenler:"</string>
|
||||
<string name="screen_welcome_title">"%1$s hoş geldiniz!"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_invites_decline_chat_message">"%1$s katılma davetini reddetmek istediğinizden emin misiniz?"</string>
|
||||
<string name="screen_invites_decline_chat_title">"Daveti reddet"</string>
|
||||
<string name="screen_invites_decline_direct_chat_message">"%1$s ile bu özel sohbeti reddetmek istediğinizden emin misiniz?"</string>
|
||||
<string name="screen_invites_decline_direct_chat_title">"Sohbeti reddet"</string>
|
||||
<string name="screen_invites_empty_list">"Davet Yok"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) sizi davet etti"</string>
|
||||
</resources>
|
||||
|
|
@ -7,6 +7,10 @@
|
|||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Ano, zrušit"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Opravdu chcete zrušit svou žádost o vstup do této místnosti?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Zrušit žádost o vstup"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Ano, odmítnout a zablokovat"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Opravdu chcete odmítnout pozvánku do této místnosti? Tím také zabráníte tomu, aby vás %1$s kontaktoval(a) nebo pozval(a) do místností."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Odmítnout pozvání a zablokovat"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Odmítnout a zablokovat"</string>
|
||||
<string name="screen_join_room_fail_message">"Vstup do místnosti se nezdařil."</string>
|
||||
<string name="screen_join_room_fail_reason">"Tato místnost je buď určena pouze pro zvané, nebo do ní může být omezen přístup na úrovni prostoru."</string>
|
||||
<string name="screen_join_room_forget_action">"Zapomenout na tuto místnost"</string>
|
||||
|
|
@ -17,6 +21,8 @@
|
|||
<string name="screen_join_room_knock_message_description">"Zpráva (nepovinné)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Pokud bude váš požadavek přijat, obdržíte pozvánku na vstup do místnosti."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Žádost o vstup odeslána"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Náhled místnosti se nám nepodařilo zobrazit. To může být způsobeno problémy se sítí nebo serverem."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Náhled této místnosti jsme nemohli zobrazit"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s zatím nepodporuje prostory. Prostory můžete používat na webu."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Prostory zatím nejsou podporovány"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Klikněte na tlačítko níže a správce místnosti bude informován. Po schválení se budete moci připojit ke konverzaci."</string>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Ja, abbrechen"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Möchten Sie Ihre Beitrittsanfrage für diesen Chatroom wirklich stornieren?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Beitrittsanfrage stornieren"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Ja, ablehnen und blockieren"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Sind Sie sicher, dass Sie die Einladung zu diesem Raum ablehnen möchten? Dadurch wird auch verhindert, dass %1$s Sie kontaktiert oder in Räume einlädt."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Einladung ablehnen und blockieren"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Ablehnen und blockieren"</string>
|
||||
<string name="screen_join_room_fail_message">"Der Beitritt zum Chatroom schlug fehl."</string>
|
||||
<string name="screen_join_room_fail_reason">"Dieser Chatroom ist entweder nur auf Einladung zugänglich oder es kann zu Zugangsbeschränkungen auf Spaceebene kommen."</string>
|
||||
<string name="screen_join_room_forget_action">"Vergessen Sie diesen Raum"</string>
|
||||
|
|
@ -17,6 +21,8 @@
|
|||
<string name="screen_join_room_knock_message_description">"Nachricht (optional)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Falls Ihre Anfrage, dem Raum beizutreten, akzeptiert wird, werden Sie eine Einladung erhalten."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Beitrittsanfrage geschickt"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Wir konnten die Chatroomvorschau nicht anzeigen. Dies kann an Netzwerk- oder Serverproblemen liegen."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Wir konnten diese Chatroomvorschau nicht anzeigen"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s unterstützt noch keine Spaces. Du kannst auf Spaces im Web zugreifen."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Spaces werden noch nicht unterstützt"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Klopfe an um einen Administrator zu benachrichtigen. Nach der Freigabe kannst du dich an der Unterhaltung beteiligen."</string>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Jah, tühista"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Kas sa oled kindel, et soovid tühistada oma palve jututoaga liitumiseks?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Tühista liitumispalve"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Jah, keeldu ja blokeeri"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Kas sa oled kindel, et soovid keelduda kutsest sellesse jututuppa? Samaga kaob kasutajal %1$s võimalus sinuga suhelda ja saata sulle jututubade kutseid."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Keeldu kutsest ja blokeeri"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Keeldu ja blokeeri"</string>
|
||||
<string name="screen_join_room_fail_message">"Jututoaga liitumine ei õnnestunud."</string>
|
||||
<string name="screen_join_room_fail_reason">"Ligipääs siia jututuppa on võimalik vaid kutse alusel või kehtivad siin kogukonnakohased piirangud."</string>
|
||||
<string name="screen_join_room_forget_action">"Unusta see jututuba"</string>
|
||||
|
|
@ -17,6 +21,8 @@
|
|||
<string name="screen_join_room_knock_message_description">"Selgitus (kui soovid lisada)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Kui sinu liitumispalvega ollakse nõus, siis saad kutse jututoaga liitumiseks."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Liitumispalve on saadetud"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Me ei saanud jututoa eelvaadet näidata. See võib olla põhjustatud võrguühenduse või serveri vigadest."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Meil ei õnnestunud selle jututoa eelvaadet kuvada"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s veel ei toeta kogukondadega liitumise ja kasutamise võimalust. Vajadusel saad seda teha veebiliidese vahendusel."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Kogukonnad pole veel toetatud"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Klõpsi allolevat nuppu ja jututoa haldaja saab asjakohase teate. Sa saad liituda, kui haldaja sinu soovi heaks kiidab."</string>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Oui, annuler"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Êtes-vous sûr de vouloir annuler votre demande d’accès à ce salon ?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Annuler la demande d’adhésion"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Oui, refuser et bloquer"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Êtes-vous sûr de vouloir refuser l’invitation à rejoindre ce salon ? Cela empêchera également %1$s de vous contacter ou de vous inviter dans les salons."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Refuser l’invitation et bloquer"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Refuser et bloquer"</string>
|
||||
<string name="screen_join_room_fail_message">"Rejoindre le salon a échoué."</string>
|
||||
<string name="screen_join_room_fail_reason">"Ce salon est accessible uniquement sur invitation ou il peut y avoir des restrictions d’accès au niveau du Space."</string>
|
||||
<string name="screen_join_room_forget_action">"Oublier ce salon"</string>
|
||||
|
|
@ -17,6 +21,8 @@
|
|||
<string name="screen_join_room_knock_message_description">"Message (facultatif)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Vous recevrez une invitation à rejoindre le salon si votre demande est acceptée."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Demande de rejoindre le salon envoyée"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Impossible d’afficher l’aperçu du salon. Cela peut être dû à des problèmes de réseau ou de serveur."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Impossible d’afficher l’aperçu de ce salon"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"Les Spaces ne sont pas encore pris en charge par %1$s . Vous pouvez voir les Spaces sur le Web."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Les Spaces ne sont pas encore pris en charge"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Cliquez ci-dessous et un administrateur sera prévenu. Une fois votre demande approuvée, pour pourrez rejoindre la discussion."</string>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Igen, visszavonás"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Biztos, hogy visszavonja a szobához való csatlakozási kérését?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Csatlakozási kérés visszavonása"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Igen, elutasítás és blokkolás"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Biztos, hogy elutasítja a meghívást, hogy csatlakozzon ehhez a szobához? Ez azt is megakadályozza, hogy %1$s kapcsolatba lépjen Önnel, vagy szobákba hívja."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Meghívó elutasítása és blokkolás"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Elutasítás és blokkolás"</string>
|
||||
<string name="screen_join_room_fail_message">"A szobához való csatlakozás sikertelen."</string>
|
||||
<string name="screen_join_room_fail_reason">"Ebbe a szobába csak meghívóval vagy tértagsággal lehet belépni."</string>
|
||||
<string name="screen_join_room_forget_action">"Szoba elfelejtése"</string>
|
||||
|
|
@ -17,6 +21,8 @@
|
|||
<string name="screen_join_room_knock_message_description">"Üzenet (nem kötelező)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Ha a kérését elfogadják, meghívót kap a szobához való csatlakozáshoz."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Csatlakozási kérés elküldve"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Nem tudtuk megjeleníteni a szoba előnézetét. Ennek az oka hálózati vagy kiszolgálóprobléma is lehet."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Nem tudtuk megjeleníteni a szoba előnézetét"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"Az %1$s még nem támogatja a tereket. A tereket a weben érheti el."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"A terek még nem támogatottak"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Kattintson az alábbi gombra, és a szoba adminisztrátora értesítést kap. A jóváhagyást követően csatlakozhat a beszélgetéshez."</string>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"Zostałeś zbanowany z tego pokoju przez %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"Zostałeś zbanowany z tego pokoju"</string>
|
||||
<string name="screen_join_room_ban_reason">"Powód: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Anuluj prośbę"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Tak, anuluj"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Czy na pewno chcesz anulować prośbę o dołączenie do tego pokoju?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Anuluj prośbę o dołączenie"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Tak, odrzuć i zablokuj"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Czy na pewno chcesz odrzucić zaproszenie dołączenia do tego pokoju? %1$s nie będzie mógł się również z Tobą skontaktować, ani zaprosić Cię do pokoju."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Odrzuć zaproszenie i zablokuj"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Odrzuć i zablokuj"</string>
|
||||
<string name="screen_join_room_fail_message">"Nie udało się dołączyć do pokoju."</string>
|
||||
<string name="screen_join_room_fail_reason">"Ten pokój wymaga zaproszenia lub jest ograniczony z poziomu przestrzeni."</string>
|
||||
<string name="screen_join_room_forget_action">"Zapomnij o tym pokoju"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Potrzebujesz zaproszenia, aby dołączyć do tego pokoju"</string>
|
||||
<string name="screen_join_room_join_action">"Dołącz do pokoju"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Aby dołączyć, musisz uzyskać zaproszenie lub być członkiem danej przestrzeni."</string>
|
||||
<string name="screen_join_room_knock_action">"Wyślij prośbę o dołączenie"</string>
|
||||
<string name="screen_join_room_knock_message_description">"Wiadomość (opcjonalne)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Otrzymasz zaproszenie dołączenia do pokoju, jeśli prośba zostanie zaakceptowana."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Wysłano prośbę o dołączenie"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Nie udało się wyświetlić podglądu pokoju. Może to być spowodowane problemami z siecią lub serwerem."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Nie udało nam się wyświetlić podglądu tego pokoju"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s jeszcze nie obsługuje przestrzeni. Uzyskaj dostęp do przestrzeni w wersji web."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Przestrzenie nie są jeszcze obsługiwane"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Kliknij przycisk poniżej, aby powiadomić administratora pokoju. Po zatwierdzeniu będziesz mógł dołączyć do rozmowy."</string>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"Foste banido desta sala por %1$s."</string>
|
||||
<string name="screen_join_room_ban_message">"Foste banido desta sala."</string>
|
||||
<string name="screen_join_room_ban_reason">"Razão: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Cancelar pedido"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Sim, cancelar"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Tens a certeza de que queres cancelar o teu pedido de entrada nesta sala?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Cancela o pedido de adesão"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Sim, recusar & bloquear"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Tens a certeza de que queres recusar o convite para entrar nesta sala? Isto também evitará que %1$s te contacte ou te convide para salas."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Recusar convite & bloquear"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Recusar e bloquear"</string>
|
||||
<string name="screen_join_room_fail_message">"Falha ao entrar na sala."</string>
|
||||
<string name="screen_join_room_fail_reason">"A entrada nesta sala ou está limitada a convites ou a alguma configuração de espaço."</string>
|
||||
<string name="screen_join_room_forget_action">"Esquecer esta sala"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Precisas de um convite para entrares nesta sala"</string>
|
||||
<string name="screen_join_room_join_action">"Entrar na sala"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Podes ter que ser convidado ou pertenceres a um espaço para poderes entrar."</string>
|
||||
<string name="screen_join_room_knock_action">"Bater à porta"</string>
|
||||
<string name="screen_join_room_knock_message_description">"Mensagem (opcional)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Irá receber um convite para participar na sala se seu pedido for aceite."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Pedido de adesão enviado"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Não conseguimos exibir a pré-visualização da sala. Isso pode ser devido a problemas de rede ou servidor."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Não foi possível exibir a pré-visualização desta sala"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"A %1$s ainda não funciona com espaços. Podes usá-los na aplicação web."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Os espaços ainda não estão implementados"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Carrega no botão abaixo para notificar um administrador da sala. Poderás entrar quando te aprovarem."</string>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
<string name="screen_join_room_knock_message_description">"Сообщение (опционально)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Вы получите приглашение присоединиться к комнате, как только ваш запрос будет принят."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Запрос на присоединение отправлен"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Не удалось отобразить предварительный просмотр комнаты. Это может быть связано с проблемами сети или сервера."</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s еще не поддерживает пространства. Вы можете получить к ним доступ в веб-версии."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Пространства пока не поддерживаются"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Нажмите кнопку ниже и администратор комнаты получит уведомление. После одобрения вы сможете присоединиться к обсуждению."</string>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Áno, zrušiť"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Ste si istí, že chcete zrušiť svoju žiadosť o vstup do tejto miestnosti?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Zrušiť žiadosť o pripojenie"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Áno, odmietnuť a zablokovať"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Ste si istí, že chcete odmietnuť pozvanie na vstup do tejto miestnosti? To tiež zabráni tomu, aby vás %1$s kontaktoval/a alebo vás pozval/a do miestností."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Odmietnuť pozvánku a zablokovať"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Odmietnuť a zablokovať"</string>
|
||||
<string name="screen_join_room_fail_message">"Pripojenie do miestnosti zlyhalo."</string>
|
||||
<string name="screen_join_room_fail_reason">"Táto miestnosť je buď len pre pozvaných, alebo môžu existovať obmedzenia na prístup na úrovni priestoru."</string>
|
||||
<string name="screen_join_room_forget_action">"Zabudnúť túto miestnosť"</string>
|
||||
|
|
@ -17,6 +21,8 @@
|
|||
<string name="screen_join_room_knock_message_description">"Správa (voliteľné)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Ak bude vaša žiadosť prijatá, dostanete pozvánku na vstup do miestnosti."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Žiadosť o pripojenie bola odoslaná"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Nepodarilo sa zobraziť ukážku miestnosti. Môže to byť spôsobené problémami so sieťou alebo serverom."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Ukážku tejto miestnosti sa nepodarilo zobraziť"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s zatiaľ nepodporuje priestory. K priestorom môžete pristupovať na webe."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Priestory zatiaľ nie sú podporované"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Kliknite na tlačidlo nižšie a správca miestnosti bude informovaný. Po schválení sa budete môcť pripojiť ku konverzácii."</string>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_cancel_knock_action">"Avbryt begäran"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Ja, avbryt"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Är du säker på att du vill avbryta din begäran om att gå med i det här rummet?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Avbryt begäran om att gå med"</string>
|
||||
<string name="screen_join_room_join_action">"Gå med i rummet"</string>
|
||||
<string name="screen_join_room_knock_action">"Knacka för att gå med"</string>
|
||||
<string name="screen_join_room_knock_message_description">"Meddelande (valfritt)"</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"%1$s tarafından bu odadan yasaklandınız."</string>
|
||||
<string name="screen_join_room_ban_message">"Bu odadan yasaklandın"</string>
|
||||
<string name="screen_join_room_ban_reason">"Neden: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"İsteği iptal et"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Evet, iptal et"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Bu odaya katılma isteğinizi iptal etmek istediğinizden emin misiniz?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Katılma isteğini iptal et"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Evet, reddet ve engelle"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Bu odaya katılma davetini reddetmek istediğinizden emin misiniz? Bu aynı zamanda %1$s sizinle iletişim kurmasını veya sizi odalara davet etmesini de engeller."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Daveti reddet ve engelle"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Reddet ve engelle"</string>
|
||||
<string name="screen_join_room_fail_message">"Odaya katılım başarısız oldu."</string>
|
||||
<string name="screen_join_room_fail_reason">"Bu odaya yalnızca davetle girilebilir veya alan düzeyinde erişim kısıtlamaları olabilir."</string>
|
||||
<string name="screen_join_room_forget_action">"Bu odayı unut"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Bu odaya katılmak için bir davete ihtiyacınız var"</string>
|
||||
<string name="screen_join_room_join_action">"Odaya katıl"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Katılmak için davet edilmeniz veya bir alana üye olmanız gerekebilir."</string>
|
||||
<string name="screen_join_room_knock_action">"Katılma isteği gönder"</string>
|
||||
<string name="screen_join_room_knock_message_description">"Mesaj (isteğe bağlı)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Talebiniz kabul edilirse odaya katılmanız için bir davet alacaksınız."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Katılma isteği gönderildi"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Oda önizlemesini görüntüleyemedik. Bunun nedeni ağ veya sunucu sorunları olabilir."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Bu oda önizlemesini görüntüleyemedik"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s henüz alanları desteklemiyor. Alanlara web üzerinden erişebilirsiniz."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Alanlar henüz desteklenmiyor"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Aşağıdaki düğmeyi tıkladığınızda bir oda yöneticisi bilgilendirilecektir. Onaylandıktan sonra görüşmeye katılabilirsiniz."</string>
|
||||
<string name="screen_join_room_subtitle_no_preview">"Mesaj geçmişini görüntülemek için bu odaya üye olmanız gerekmektedir."</string>
|
||||
<string name="screen_join_room_title_knock">"Bu odaya katılmak ister misiniz?"</string>
|
||||
<string name="screen_join_room_title_no_preview">"Önizleme mevcut değil"</string>
|
||||
</resources>
|
||||
|
|
@ -1,14 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_join_room_ban_by_message">"%1$s забороняє вам відвідувати цю кімнату."</string>
|
||||
<string name="screen_join_room_ban_message">"Вам заборонили відвідувати цю кімнату"</string>
|
||||
<string name="screen_join_room_ban_reason">"Причина: %1$s."</string>
|
||||
<string name="screen_join_room_cancel_knock_action">"Скасувати запит"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Так, скасувати"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Ви впевнені, що бажаєте скасувати свій запит на приєднання до цієї кімнати?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Скасувати запит на приєднання"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Так, відхилити та заблокувати"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Ви впевнені, що хочете відхилити запрошення приєднатися до цієї кімнати? Це також завадить %1$s зв\'язатися з вами або запрошувати вас в кімнати."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Відхилити запрошення та заблокувати"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Відхилити та заблокувати"</string>
|
||||
<string name="screen_join_room_fail_message">"Не вдалося приєднатися до кімнати."</string>
|
||||
<string name="screen_join_room_fail_reason">"Ця кімната доступна лише за запрошенням або на рівні простору можуть бути обмеження доступу."</string>
|
||||
<string name="screen_join_room_forget_action">"Забути цю кімнату"</string>
|
||||
<string name="screen_join_room_invite_required_message">"Вам потрібне запрошення, щоб приєднатися до цієї кімнати"</string>
|
||||
<string name="screen_join_room_join_action">"Приєднатися до кімнати"</string>
|
||||
<string name="screen_join_room_join_restricted_message">"Можливо, вам знадобиться отримати запрошення або стати учасником простору, щоб приєднатися."</string>
|
||||
<string name="screen_join_room_knock_action">"Постукати, щоб приєднатися"</string>
|
||||
<string name="screen_join_room_knock_message_description">"Повідомлення (необов\'язково)"</string>
|
||||
<string name="screen_join_room_knock_sent_description">"Ви отримаєте запрошення приєднатися до кімнати, якщо ваш запит буде прийнятий."</string>
|
||||
<string name="screen_join_room_knock_sent_title">"Запит на приєднання надіслано"</string>
|
||||
<string name="screen_join_room_loading_alert_message">"Ми не змогли показати попередній перегляд кімнати. Це може бути пов\'язано з проблемами мережі або сервера."</string>
|
||||
<string name="screen_join_room_loading_alert_title">"Ми не можемо показати попередній перегляд цієї кімнати"</string>
|
||||
<string name="screen_join_room_space_not_supported_description">"%1$s ще не підтримує простори. Ви можете отримати доступ до них у вебверсії."</string>
|
||||
<string name="screen_join_room_space_not_supported_title">"Простори поки що не підтримуються"</string>
|
||||
<string name="screen_join_room_subtitle_knock">"Натисніть кнопку нижче, і адміністратор кімнати отримає сповіщення. Ви зможете приєднатися до розмови після схвалення."</string>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
<string name="screen_join_room_cancel_knock_alert_confirmation">"Yes, cancel"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_description">"Are you sure that you want to cancel your request to join this room?"</string>
|
||||
<string name="screen_join_room_cancel_knock_alert_title">"Cancel request to join"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_confirmation">"Yes, decline & block"</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_message">"Are you sure you want to decline the invite to join this room? This will also prevent %1$s from contacting you or inviting you to rooms."</string>
|
||||
<string name="screen_join_room_decline_and_block_alert_title">"Decline invite & block"</string>
|
||||
<string name="screen_join_room_decline_and_block_button_title">"Decline and block"</string>
|
||||
<string name="screen_join_room_fail_message">"Joining the room failed."</string>
|
||||
<string name="screen_join_room_fail_reason">"This room is either invite-only or there might be restrictions to access at space level."</string>
|
||||
<string name="screen_join_room_forget_action">"Forget this room"</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Прыняць"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Приемане"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Aceptar"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"پذیرش"</string>
|
||||
</resources>
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<string name="screen_knock_requests_list_empty_state_description">"Ha valaki csatlakozni kíván a szobához, itt láthatja a kérését."</string>
|
||||
<string name="screen_knock_requests_list_empty_state_title">"Nincs függőben lévő csatlakozási kérelem"</string>
|
||||
<string name="screen_knock_requests_list_initial_loading_title">"Csatlakozási kérések betöltése…"</string>
|
||||
<string name="screen_knock_requests_list_title">"Csatlakozási kérelmek"</string>
|
||||
<string name="screen_knock_requests_list_title">"Csatlakozási kérelem"</string>
|
||||
<plurals name="screen_room_multiple_knock_requests_title">
|
||||
<item quantity="one">"%1$s és még %2$d felhasználó szeretne csatlakozni ehhez a szobához"</item>
|
||||
<item quantity="other">"%1$s és még %2$d felhasználó szeretne csatlakozni ehhez a szobához"</item>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"მიღება"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Godta"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Accepteren"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Aceitar"</string>
|
||||
</resources>
|
||||
|
|
@ -4,15 +4,26 @@
|
|||
<string name="screen_knock_requests_list_accept_all_alert_description">"Tens a certeza de que queres aceitar todos os pedidos de entrada?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_alert_title">"Aceitar todos os pedidos"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_button_title">"Aceitar todos"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_description">"Não foi possível aceitar todos os pedidos. Queres tentar novamente?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_title">"Falha ao aceitar todos os pedidos"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_loading_title">"A aceitar todos os pedidos de entrada"</string>
|
||||
<string name="screen_knock_requests_list_accept_failed_alert_description">"Não foi possível aceitar este pedido. Queres tentar novamente?"</string>
|
||||
<string name="screen_knock_requests_list_accept_failed_alert_title">"Falha ao aceitar pedido"</string>
|
||||
<string name="screen_knock_requests_list_accept_loading_title">"A aceitar pedido de entrada"</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_confirm_button_title">"Sim, recusar e proibir"</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_description">"Tens a certeza de que queres recusar e banir %1$s? Este utilizador não poderá voltar a pedir para entrar nesta sala."</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_title">"Recusar e banir"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_confirm_button_title">"Sim, recusar"</string>
|
||||
<string name="screen_knock_requests_list_ban_loading_title">"A rejeitar pedido e a banir o utilizador"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_confirm_button_title">"Sim, rejeitar"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_description">"Tens a certeza que queres recusar o pedido de entrada de %1$s?"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_title">"Recusar entrada"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_title">"Rejeitar entrada"</string>
|
||||
<string name="screen_knock_requests_list_decline_and_ban_action_title">"Recusar e banir"</string>
|
||||
<string name="screen_knock_requests_list_decline_failed_alert_description">"Não foi possível rejeitar este pedido. Queres tentar novamente?"</string>
|
||||
<string name="screen_knock_requests_list_decline_failed_alert_title">"Falha ao rejeitar pedido"</string>
|
||||
<string name="screen_knock_requests_list_decline_loading_title">"A rejeitar pedido de entrada"</string>
|
||||
<string name="screen_knock_requests_list_empty_state_description">"Quando alguém pedir para entrar na sala, irás poder rever o pedido aqui."</string>
|
||||
<string name="screen_knock_requests_list_empty_state_title">"Sem pedidos de entrada"</string>
|
||||
<string name="screen_knock_requests_list_initial_loading_title">"A carregar pedidos de entrada…"</string>
|
||||
<string name="screen_knock_requests_list_title">"Pedidos de entrada"</string>
|
||||
<plurals name="screen_room_multiple_knock_requests_title">
|
||||
<item quantity="one">"%1$s +%2$d outro querem entrar nesta sala"</item>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Acceptați"</string>
|
||||
</resources>
|
||||
|
|
@ -24,14 +24,14 @@
|
|||
<string name="screen_knock_requests_list_empty_state_description">"Вы сможете увидеть запрос, когда кто-то попросит присоединиться к комнате."</string>
|
||||
<string name="screen_knock_requests_list_empty_state_title">"Нет ожидающих запросов на присоединение"</string>
|
||||
<string name="screen_knock_requests_list_initial_loading_title">"Загрузка запросов на присоединение…"</string>
|
||||
<string name="screen_knock_requests_list_title">"Запросы на присоединение"</string>
|
||||
<string name="screen_knock_requests_list_title">"Запросы на вступление"</string>
|
||||
<plurals name="screen_room_multiple_knock_requests_title">
|
||||
<item quantity="one">"%1$s +%2$d хочет присоединиться к этой комнате"</item>
|
||||
<item quantity="few">"%1$s +%2$d хотят присоединиться к этой комнате"</item>
|
||||
<item quantity="many">"%1$s +%2$d хотят присоединиться к этой комнате"</item>
|
||||
</plurals>
|
||||
<string name="screen_room_multiple_knock_requests_view_all_button_title">"Показать все"</string>
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Принять"</string>
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Разрешить"</string>
|
||||
<string name="screen_room_single_knock_request_title">"%1$s хочет присоединиться к этой комнате"</string>
|
||||
<string name="screen_room_single_knock_request_view_button_title">"Просмотр"</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<string name="screen_knock_requests_list_empty_state_description">"Keď niekto požiada, aby sa pripojil k miestnosti, jeho žiadosť si môžete pozrieť tu."</string>
|
||||
<string name="screen_knock_requests_list_empty_state_title">"Žiadna čakajúca žiadosť o pripojenie"</string>
|
||||
<string name="screen_knock_requests_list_initial_loading_title">"Načítavajú sa žiadosti o pripojenie…"</string>
|
||||
<string name="screen_knock_requests_list_title">"Žiadosti o pripojenie"</string>
|
||||
<string name="screen_knock_requests_list_title">"Žiadosti o vstup"</string>
|
||||
<plurals name="screen_room_multiple_knock_requests_title">
|
||||
<item quantity="one">"%1$s +%2$d ďalší chcú vstúpiť do tejto miestnosti"</item>
|
||||
<item quantity="few">"%1$s +%2$d ďalší chcú vstúpiť do tejto miestnosti"</item>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_knock_requests_list_accept_all_alert_confirm_button_title">"Ja, acceptera alla"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_alert_description">"Är du säker på att du vill acceptera alla förfrågningar om att gå med?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_alert_title">"Acceptera alla förfrågningar"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_button_title">"Acceptera alla"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_title">"Misslyckades att acceptera alla förfrågningar"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_loading_title">"Accepterar alla förfrågningar om att gå med"</string>
|
||||
<string name="screen_knock_requests_list_accept_loading_title">"Accepterar begäran om att gå med"</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_confirm_button_title">"Ja, avslå och förbjud"</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_description">"Är du säker på att du vill avvisa och förbjuda%1$s? Den här användaren kommer inte att kunna begära åtkomst för att gå med i det här rummet igen."</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_title">"Avvisa och förbjud åtkomst"</string>
|
||||
<string name="screen_knock_requests_list_ban_loading_title">"Avvisar och bannar åtkomst"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_confirm_button_title">"Ja, avböj"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_description">"Är du säker på att du vill avslå %1$s begäran om att gå med i det här rummet?"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_title">"Avvisa åtkomst"</string>
|
||||
<string name="screen_knock_requests_list_decline_and_ban_action_title">"Avvisa och förbjud"</string>
|
||||
<string name="screen_knock_requests_list_decline_loading_title">"Avvisa begäran om att gå med"</string>
|
||||
<string name="screen_knock_requests_list_empty_state_description">"När någon begär om att gå med i rummet, kan du se deras förfrågan här."</string>
|
||||
<string name="screen_knock_requests_list_empty_state_title">"Ingen väntande begäran om att gå med"</string>
|
||||
<string name="screen_knock_requests_list_initial_loading_title">"Laddar förfrågningar om att gå med …"</string>
|
||||
<string name="screen_knock_requests_list_title">"Begäran om att gå med"</string>
|
||||
<plurals name="screen_room_multiple_knock_requests_title">
|
||||
<item quantity="one">"%1$s+ %2$d annan vill gå med i detta rum"</item>
|
||||
<item quantity="other">"%1$s+ %2$d andra vill gå med i detta rum"</item>
|
||||
</plurals>
|
||||
<string name="screen_room_multiple_knock_requests_view_all_button_title">"Visa alla"</string>
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Godkänn"</string>
|
||||
<string name="screen_room_single_knock_request_title">"%1$s vill gå med i det här rummet"</string>
|
||||
<string name="screen_room_single_knock_request_view_button_title">"Visa"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_knock_requests_list_accept_all_alert_confirm_button_title">"Evet, tümünü kabul et"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_alert_description">"Tüm katılma isteklerini kabul etmek istediğinizden emin misiniz?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_alert_title">"Tüm istekleri kabul et"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_button_title">"Tümünü kabul et"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_description">"Tüm istekleri kabul edemedik. Tekrar denemek ister misiniz?"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_failed_alert_title">"Tüm istekler kabul edilemedi"</string>
|
||||
<string name="screen_knock_requests_list_accept_all_loading_title">"Tüm katılım istekleri kabul ediliyor"</string>
|
||||
<string name="screen_knock_requests_list_accept_failed_alert_description">"Bu isteği kabul edemedik. Tekrar denemek ister misiniz?"</string>
|
||||
<string name="screen_knock_requests_list_accept_failed_alert_title">"İstek kabul edilemedi"</string>
|
||||
<string name="screen_knock_requests_list_accept_loading_title">"Katılma isteği kabul ediliyor"</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_confirm_button_title">"Evet, reddet ve yasakla"</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_description">"%1$s reddetmek ve yasaklamak istediğinizden emin misiniz? Bu kullanıcı, bu odaya tekrar katılmak için erişim isteğinde bulunamaz."</string>
|
||||
<string name="screen_knock_requests_list_ban_alert_title">"Reddet ve erişimi yasakla"</string>
|
||||
<string name="screen_knock_requests_list_ban_loading_title">"Reddediliyor ve erişim yasaklanıyor"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_confirm_button_title">"Evet, reddet"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_description">"Bu odaya katılma isteğini reddetmek istediğinizden emin misiniz %1$s?"</string>
|
||||
<string name="screen_knock_requests_list_decline_alert_title">"Erişimi reddet"</string>
|
||||
<string name="screen_knock_requests_list_decline_and_ban_action_title">"Reddet ve yasakla"</string>
|
||||
<string name="screen_knock_requests_list_decline_failed_alert_description">"Bu isteği reddedemedik. Tekrar denemek ister misiniz?"</string>
|
||||
<string name="screen_knock_requests_list_decline_failed_alert_title">"İsteği reddetme başarısız oldu"</string>
|
||||
<string name="screen_knock_requests_list_decline_loading_title">"Katılma isteği reddediliyor"</string>
|
||||
<string name="screen_knock_requests_list_empty_state_description">"Birisi odaya katılmak istediğinde, isteklerini burada görebileceksiniz."</string>
|
||||
<string name="screen_knock_requests_list_empty_state_title">"Bekleyen katılım isteği yok"</string>
|
||||
<string name="screen_knock_requests_list_initial_loading_title">"Katılma istekleri yükleniyor…"</string>
|
||||
<string name="screen_knock_requests_list_title">"Katılma istekleri"</string>
|
||||
<plurals name="screen_room_multiple_knock_requests_title">
|
||||
<item quantity="one">"%1$s +%2$d kişi daha bu odaya katılmak istiyor"</item>
|
||||
<item quantity="other">"%1$s +%2$d kişi daha bu odaya katılmak istiyor"</item>
|
||||
</plurals>
|
||||
<string name="screen_room_multiple_knock_requests_view_all_button_title">"Tümünü görüntüle"</string>
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Kabul et"</string>
|
||||
<string name="screen_room_single_knock_request_title">"%1$s bu odaya katılmak istiyor"</string>
|
||||
<string name="screen_room_single_knock_request_view_button_title">"Görüntüle"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_room_single_knock_request_accept_button_title">"Qabul qiling"</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="leave_conversation_alert_subtitle">"Bu sohbetten ayrılmak istediğinizden emin misiniz? Bu sohbet herkese açık değil ve davet olmadan tekrar katılamayacaksınız."</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"Bu odadan ayrılmak istediğinizden emin misiniz? Burada tek kişi sizsiniz. Ayrılırsanız, siz de dahil olmak üzere gelecekte kimse katılamayacak."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"Bu odadan ayrılmak istediğinizden emin misiniz? Bu oda herkese açık değildir ve davet olmadan tekrar katılamazsınız."</string>
|
||||
<string name="leave_room_alert_subtitle">"Odadan çıkmak istediğinden emin misin?"</string>
|
||||
</resources>
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
<string name="screen_app_lock_biometric_authentication">"biometrisk autentisering"</string>
|
||||
<string name="screen_app_lock_biometric_unlock">"biometrisk upplåsning"</string>
|
||||
<string name="screen_app_lock_biometric_unlock_title_android">"Lås upp med biometri"</string>
|
||||
<string name="screen_app_lock_confirm_biometric_authentication_android">"Bekräfta biometriskt"</string>
|
||||
<string name="screen_app_lock_forgot_pin">"Glömt PIN-kod?"</string>
|
||||
<string name="screen_app_lock_settings_change_pin">"Byt PIN-kod"</string>
|
||||
<string name="screen_app_lock_settings_enable_biometric_unlock">"Tillåt biometrisk upplåsning"</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_app_lock_biometric_authentication">"biyometrik kimlik doğrulama"</string>
|
||||
<string name="screen_app_lock_biometric_unlock">"biyometrik kilit açma"</string>
|
||||
<string name="screen_app_lock_biometric_unlock_title_android">"Biyometrik ile kilit aç"</string>
|
||||
<string name="screen_app_lock_confirm_biometric_authentication_android">"Biyometrik doğrulama"</string>
|
||||
<string name="screen_app_lock_forgot_pin">"PIN\'i unuttum"</string>
|
||||
<string name="screen_app_lock_settings_change_pin">"PIN kodunu değiştir"</string>
|
||||
<string name="screen_app_lock_settings_enable_biometric_unlock">"Biyometrik kilit açmaya izin ver"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin">"PIN kodunu kaldır"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_message">"PIN\'i kaldırmak istediğinizden emin misiniz?"</string>
|
||||
<string name="screen_app_lock_settings_remove_pin_alert_title">"PIN\'i kaldır?"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_allow_title">"İzin ver %1$s"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_skip">"PIN kullanmayı tercih ederim"</string>
|
||||
<string name="screen_app_lock_setup_biometric_unlock_subtitle">"%1$s kullanarak oturum açarken kendinize zaman kazandırın"</string>
|
||||
<string name="screen_app_lock_setup_choose_pin">"PIN Seç"</string>
|
||||
<string name="screen_app_lock_setup_confirm_pin">"PIN\'i onayla"</string>
|
||||
<string name="screen_app_lock_setup_pin_context">"Sohbetlerinize ekstra güvenlik eklemek için %1$s kilitleyin.
|
||||
|
||||
Hatırlanabilir bir şey seçin. Bu PIN\'i unutursanız, uygulamadan çıkış yaparsınız."</string>
|
||||
<string name="screen_app_lock_setup_pin_forbidden_dialog_content">"Güvenlik nedeniyle bunu PIN kodunuz olarak seçemezsiniz"</string>
|
||||
<string name="screen_app_lock_setup_pin_forbidden_dialog_title">"Farklı bir PIN seçin"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_content">"Lütfen aynı PIN\'i iki kez girin"</string>
|
||||
<string name="screen_app_lock_setup_pin_mismatch_dialog_title">"PIN\'ler eşleşmiyor"</string>
|
||||
<string name="screen_app_lock_signout_alert_message">"Devam etmek için yeniden oturum açmanız ve yeni bir PIN oluşturmanız gerekir"</string>
|
||||
<string name="screen_app_lock_signout_alert_title">"Oturumunuz kapatılıyor"</string>
|
||||
<plurals name="screen_app_lock_subtitle">
|
||||
<item quantity="one">"Kilidi açmak için %1$d deneme hakkınız var"</item>
|
||||
<item quantity="other">"Kilidi açmak için %1$d deneme hakkınız var"</item>
|
||||
</plurals>
|
||||
<plurals name="screen_app_lock_subtitle_wrong_pin">
|
||||
<item quantity="one">"Yanlış PIN. %1$d kere daha şansınız var"</item>
|
||||
<item quantity="other">"Yanlış PIN. %1$d kere daha şansınız var"</item>
|
||||
</plurals>
|
||||
<string name="screen_app_lock_use_biometric_android">"Biyometrik kullan"</string>
|
||||
<string name="screen_app_lock_use_pin_android">"PIN kullan"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Oturum kapatılıyor…"</string>
|
||||
</resources>
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
<string name="screen_change_account_provider_subtitle">"Използвайте друг доставчик на акаунт, като например собствен частен сървър или работен акаунт."</string>
|
||||
<string name="screen_change_account_provider_title">"Промяна на доставчика на акаунт"</string>
|
||||
<string name="screen_change_server_subtitle">"Какъв е адресът на вашия сървър?"</string>
|
||||
<string name="screen_create_account_title">"Създаване на акаунт"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Този акаунт бе деактивиран."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Неправилно потребителско име и/или парола"</string>
|
||||
<string name="screen_login_form_header">"Въведете своите данни"</string>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
<string name="screen_change_server_form_notice">"Solo puedes conectarte a un servidor que soporte sliding sync. El administrador de tu servidor tendrá que configurarlo. %1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"¿Cuál es la dirección de tu servidor?"</string>
|
||||
<string name="screen_change_server_title">"Selecciona tu servidor"</string>
|
||||
<string name="screen_create_account_title">"Crear cuenta"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Esta cuenta ha sido desactivada."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Usuario y/o contraseña incorrectos"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Este no es un id de usuario válido. Formato esperado: \'@user:homeserver.org\'"</string>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<string name="screen_change_server_form_notice">"თქვენ შეგიძლიათ დაუკავშირდეთ მხოლოდ იმ სერვერს, რომელიც მხარს უჭერს \"sliding sync\"-ს. თქვენი სახლის სერვერის ადმინისტრატორს დასჭირდება მისი კონფიგურაცია.%1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"რა არის თქვენი სერვერის მისამართი?"</string>
|
||||
<string name="screen_change_server_title">"აირჩიეთ თქვენი სერვერი"</string>
|
||||
<string name="screen_create_account_title">"ანგარიშის შექმნა"</string>
|
||||
<string name="screen_login_error_deactivated_account">"ეს ანგარიში დეაქტივირებულია."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"არასწორი მომხმარებლის სახელი და/ან პაროლი"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"მოცემული მომხმარებლის იდენტიფიკატორი არასწორია. დასაშვები ფორმატი: ‘@user:homeserver.org’"</string>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_account_provider_change">"Bytt kontotilbyder"</string>
|
||||
<string name="screen_account_provider_form_hint">"Hjemmeserveradresse"</string>
|
||||
<string name="screen_account_provider_form_subtitle">"Søk etter et selskap, fellesskap eller privat server."</string>
|
||||
<string name="screen_account_provider_form_title">"Finn en kontoleverandør"</string>
|
||||
|
|
@ -7,10 +8,15 @@
|
|||
<string name="screen_account_provider_signin_title">"Du er i ferd med å logge inn på %s"</string>
|
||||
<string name="screen_account_provider_signup_subtitle">"Det er her samtalene dine vil ligge - akkurat som du ville brukt en e-postleverandør til å oppbevare e-postene dine."</string>
|
||||
<string name="screen_account_provider_signup_title">"Du er i ferd med å opprette en konto på %s"</string>
|
||||
<string name="screen_change_account_provider_other">"Annet"</string>
|
||||
<string name="screen_change_account_provider_subtitle">"Bruk en annen kontotilbyder, for eksempel din egen private server eller en arbeidskonto."</string>
|
||||
<string name="screen_change_account_provider_title">"Bytt kontotilbyder"</string>
|
||||
<string name="screen_change_server_error_invalid_homeserver">"Vi kunne ikke nå denne hjemmeserveren. Kontroller at du har skrevet inn hjemmeserverens URL riktig. Hvis URL-en er riktig, kontakt administratoren for hjemmeserveren din for å få mer hjelp."</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"Denne serveren støtter for øyeblikket ikke sliding sync."</string>
|
||||
<string name="screen_change_server_form_header">"URL til hjemmeserver"</string>
|
||||
<string name="screen_change_server_form_notice">"Du kan bare koble til en eksisterende server som støtter sliding sync. Administrator for din hjemmeserver må konfigurere det. %1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"Hva er adressen til serveren din?"</string>
|
||||
<string name="screen_create_account_title">"Opprett konto"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Denne kontoen er deaktivert."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Feil brukernavn og/eller passord"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Dette er ikke en gyldig brukeridentifikator. Forventet format: \'@bruker:homeserver.org\'"</string>
|
||||
|
|
@ -18,6 +24,8 @@
|
|||
<string name="screen_login_form_header">"Skriv inn opplysningene dine"</string>
|
||||
<string name="screen_login_subtitle">"Matrix er et åpent nettverk for sikker, desentralisert kommunikasjon."</string>
|
||||
<string name="screen_login_title">"Velkommen tilbake!"</string>
|
||||
<string name="screen_login_title_with_homeserver">"Logg inn på %1$s"</string>
|
||||
<string name="screen_server_confirmation_change_server">"Bytt kontotilbyder"</string>
|
||||
<string name="screen_server_confirmation_message_login_element_dot_io">"En privat server for Element-ansatte."</string>
|
||||
<string name="screen_server_confirmation_message_login_matrix_dot_org">"Matrix er et åpent nettverk for sikker, desentralisert kommunikasjon."</string>
|
||||
<string name="screen_server_confirmation_message_register">"Det er her samtalene dine vil ligge - akkurat som du ville brukt en e-postleverandør til å oppbevare e-postene dine."</string>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<string name="screen_change_server_form_notice">"Você só pode se conectar a um servidor existente que ofereça suporte à tecnologia sliding sync. O administrador do seu servidor precisará configurá-lo. %1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"Qual é o endereço do seu servidor?"</string>
|
||||
<string name="screen_change_server_title">"Selecione seu servidor"</string>
|
||||
<string name="screen_create_account_title">"Criar conta"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Essa conta foi desativada."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Nome de usuário e/ou senha incorretos"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Esse não é um identificador de usuário válido. Formato esperado: \'@usuário:servidor.org\'"</string>
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@
|
|||
<string name="screen_qr_code_login_device_not_signed_in_scan_state_subtitle">"O outro dispositivo não tem a sessão iniciada"</string>
|
||||
<string name="screen_qr_code_login_error_cancelled_subtitle">"O início de sessão foi cancelado no outro dispositivo."</string>
|
||||
<string name="screen_qr_code_login_error_cancelled_title">"Pedido de início de sessão cancelado"</string>
|
||||
<string name="screen_qr_code_login_error_declined_subtitle">"O início de sessão foi recusado no outro dispositivo."</string>
|
||||
<string name="screen_qr_code_login_error_declined_title">"Início de sessão cancelado"</string>
|
||||
<string name="screen_qr_code_login_error_declined_subtitle">"O início de sessão foi rejeitado no outro dispositivo."</string>
|
||||
<string name="screen_qr_code_login_error_declined_title">"Início de sessão rejeitado"</string>
|
||||
<string name="screen_qr_code_login_error_expired_subtitle">"O início de sessão expirou. Por favor, tenta novamente."</string>
|
||||
<string name="screen_qr_code_login_error_expired_title">"O início de sessão não foi concluído a tempo"</string>
|
||||
<string name="screen_qr_code_login_error_linking_not_suported_subtitle">"O teu outro dispositivo não suporta o início de sessão na %s com um código QR.
|
||||
|
|
|
|||
83
features/login/impl/src/main/res/values-tr/translations.xml
Normal file
83
features/login/impl/src/main/res/values-tr/translations.xml
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_account_provider_change">"Hesap sağlayıcısını değiştir"</string>
|
||||
<string name="screen_account_provider_form_hint">"Ana sunucu adresi"</string>
|
||||
<string name="screen_account_provider_form_notice">"Bir arama terimi veya alan adı adresi girin."</string>
|
||||
<string name="screen_account_provider_form_subtitle">"Bir şirket, topluluk veya özel sunucu arayın."</string>
|
||||
<string name="screen_account_provider_form_title">"Bir hesap sağlayıcısı bulun"</string>
|
||||
<string name="screen_account_provider_signin_subtitle">"Konuşmalarınızın saklanacağı yer burasıdır - tıpkı e-postalarınızı saklamak için bir e-posta sağlayıcısı kullandığınız gibi."</string>
|
||||
<string name="screen_account_provider_signin_title">"Oturum açmak üzeresiniz %s"</string>
|
||||
<string name="screen_account_provider_signup_subtitle">"Konuşmalarınızın saklanacağı yer burasıdır - tıpkı e-postalarınızı saklamak için bir e-posta sağlayıcısı kullandığınız gibi."</string>
|
||||
<string name="screen_account_provider_signup_title">"%s üzerinde bir hesap oluşturmak üzeresiniz"</string>
|
||||
<string name="screen_change_account_provider_matrix_org_subtitle">"Matrix.org, Matrix.org Vakfı tarafından yönetilen, güvenli, merkezi olmayan iletişim için halka açık Matrix ağında büyük, ücretsiz bir sunucudur."</string>
|
||||
<string name="screen_change_account_provider_other">"Diğer"</string>
|
||||
<string name="screen_change_account_provider_subtitle">"Kendi özel sunucunuz veya iş hesabınız gibi farklı bir hesap sağlayıcı kullanın."</string>
|
||||
<string name="screen_change_account_provider_title">"Hesap sağlayıcısını değiştir"</string>
|
||||
<string name="screen_change_server_error_invalid_homeserver">"Bu ana sunucuya ulaşamadık. Lütfen ana sunucu URL\'sini doğru girip girmediğinizi kontrol edin. URL doğruysa, daha fazla yardım için ana sunucu yöneticinize başvurun."</string>
|
||||
<string name="screen_change_server_error_invalid_well_known">"Sliding sync, iyi bilinen dosyadaki bir sorun nedeniyle kullanılamıyor:
|
||||
%1$s"</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"Bu sunucu şu anda sliding sync desteklemiyor."</string>
|
||||
<string name="screen_change_server_form_header">"Ana sunucu URL\'si"</string>
|
||||
<string name="screen_change_server_form_notice">"Yalnızca sliding sync destekleyen mevcut bir sunucuya bağlanabilirsiniz. Ana sunucu yöneticinizin bunu yapılandırması gerekecektir. %1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"Sunucunuzun adresi nedir?"</string>
|
||||
<string name="screen_change_server_title">"Sunucunuzu seçin"</string>
|
||||
<string name="screen_create_account_title">"Hesap oluştur"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Hesap devre dışı bırakıldı."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Yanlış kullanıcı adı ve/veya şifre"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Bu geçerli bir kullanıcı tanımlayıcısı değil. Kullanılması gereken biçim: \'@user:homeserver.org\'"</string>
|
||||
<string name="screen_login_error_refresh_tokens">"Bu sunucu, yenileme belirteçlerini kullanacak şekilde yapılandırılmıştır. Parola tabanlı oturum açma kullanılırken bunlar desteklenmez."</string>
|
||||
<string name="screen_login_error_unsupported_authentication">"Seçilen ana sunucu parola veya OIDC oturum açmayı desteklemiyor. Lütfen yöneticinizle iletişime geçin veya başka bir ana sunucu seçin."</string>
|
||||
<string name="screen_login_form_header">"Bilgilerinizi girin"</string>
|
||||
<string name="screen_login_subtitle">"Matrix, güvenli, merkezi olmayan iletişim için açık bir ağdır."</string>
|
||||
<string name="screen_login_title">"Tekrar hoş geldiniz!"</string>
|
||||
<string name="screen_login_title_with_homeserver">"%1$s adresinde oturum aç"</string>
|
||||
<string name="screen_qr_code_login_connecting_subtitle">"Güvenli bir bağlantı kuruluyor"</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_description">"Yeni cihaza güvenli bir bağlantı kurulamadı. Mevcut cihazlarınız hala güvende ve onlar için endişelenmenize gerek yok."</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_list_header">"Şimdi ne olacak?"</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_list_item_1">"Bunun bir ağ sorunu olması ihtimaline karşı bir QR koduyla tekrar oturum açmayı deneyin"</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_list_item_2">"Aynı sorunla karşılaşırsanız, farklı bir wifi ağı deneyin veya wifi yerine mobil verinizi kullanın"</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_list_item_3">"Bu işe yaramazsa, manuel olarak oturum açın"</string>
|
||||
<string name="screen_qr_code_login_connection_note_secure_state_title">"Bağlantı güvenli değil"</string>
|
||||
<string name="screen_qr_code_login_device_code_subtitle">"Bu cihazda gösterilen iki haneyi girmeniz istenecektir."</string>
|
||||
<string name="screen_qr_code_login_device_code_title">"Aşağıdaki numarayı diğer cihazınıza girin"</string>
|
||||
<string name="screen_qr_code_login_device_not_signed_in_scan_state_description">"Diğer cihazınızda oturum açın ve ardından tekrar deneyin veya zaten oturum açmış başka bir cihaz kullanın."</string>
|
||||
<string name="screen_qr_code_login_device_not_signed_in_scan_state_subtitle">"Diğer cihaz oturum açmamış"</string>
|
||||
<string name="screen_qr_code_login_error_cancelled_subtitle">"Oturum açma işlemi diğer cihazda iptal edildi."</string>
|
||||
<string name="screen_qr_code_login_error_cancelled_title">"Oturum açma isteği iptal edildi"</string>
|
||||
<string name="screen_qr_code_login_error_declined_subtitle">"Diğer cihazda oturum açma işlemi reddedildi."</string>
|
||||
<string name="screen_qr_code_login_error_declined_title">"Oturum açma reddedildi"</string>
|
||||
<string name="screen_qr_code_login_error_expired_subtitle">"Oturum açma süresi doldu. Lütfen tekrar deneyin."</string>
|
||||
<string name="screen_qr_code_login_error_expired_title">"Oturum açma işlemi zamanında tamamlanmadı"</string>
|
||||
<string name="screen_qr_code_login_error_linking_not_suported_subtitle">"Diğer cihazınız %s QR koduyla oturum açmayı desteklemiyor.
|
||||
|
||||
Manuel olarak oturum açmayı deneyin veya QR kodunu başka bir cihazla tarayın."</string>
|
||||
<string name="screen_qr_code_login_error_linking_not_suported_title">"QR kodu desteklenmiyor"</string>
|
||||
<string name="screen_qr_code_login_error_sliding_sync_not_supported_subtitle">"Hesap sağlayıcınız %1$s desteklemiyor."</string>
|
||||
<string name="screen_qr_code_login_error_sliding_sync_not_supported_title">"%1$s desteklenmiyor"</string>
|
||||
<string name="screen_qr_code_login_initial_state_button_title">"Taramaya hazır"</string>
|
||||
<string name="screen_qr_code_login_initial_state_item_1">"Bir masaüstü cihazda %1$s açın"</string>
|
||||
<string name="screen_qr_code_login_initial_state_item_2">"Avatarınıza tıklayın"</string>
|
||||
<string name="screen_qr_code_login_initial_state_item_3">"Seç %1$s"</string>
|
||||
<string name="screen_qr_code_login_initial_state_item_3_action">"\"Yeni cihaz bağla\""</string>
|
||||
<string name="screen_qr_code_login_initial_state_item_4">"QR kodunu bu cihazla tarayın"</string>
|
||||
<string name="screen_qr_code_login_initial_state_subtitle">"Yalnızca hesap sağlayıcınız destekliyorsa kullanılabilir."</string>
|
||||
<string name="screen_qr_code_login_initial_state_title">"QR kodunu almak için %1$s uygulamasını başka bir cihazda açın"</string>
|
||||
<string name="screen_qr_code_login_invalid_scan_state_description">"Diğer cihazda gösterilen QR kodunu kullan."</string>
|
||||
<string name="screen_qr_code_login_invalid_scan_state_retry_button">"Tekrar deneyin"</string>
|
||||
<string name="screen_qr_code_login_invalid_scan_state_subtitle">"Yanlış QR kodu"</string>
|
||||
<string name="screen_qr_code_login_no_camera_permission_button">"Kamera ayarlarına git"</string>
|
||||
<string name="screen_qr_code_login_no_camera_permission_state_description">"Devam etmek için %1$s cihazınızın kamerasını kullanmasına izin vermeniz gerekir."</string>
|
||||
<string name="screen_qr_code_login_no_camera_permission_state_title">"QR kodunu taramak için kamera erişimine izin verin"</string>
|
||||
<string name="screen_qr_code_login_scanning_state_title">"QR kodunu tara"</string>
|
||||
<string name="screen_qr_code_login_start_over_button">"Yeniden Başla"</string>
|
||||
<string name="screen_qr_code_login_unknown_error_description">"Beklenmeyen bir hata oluştu. Lütfen tekrar deneyin."</string>
|
||||
<string name="screen_qr_code_login_verify_code_loading">"Diğer cihazınız bekleniyor"</string>
|
||||
<string name="screen_qr_code_login_verify_code_subtitle">"Hesap sağlayıcınız, oturum açmayı doğrulamak için aşağıdaki kodu isteyebilir."</string>
|
||||
<string name="screen_qr_code_login_verify_code_title">"Doğrulama kodunuz"</string>
|
||||
<string name="screen_server_confirmation_change_server">"Hesap sağlayıcısını değiştir"</string>
|
||||
<string name="screen_server_confirmation_message_login_element_dot_io">"Element çalışanları için özel bir sunucu."</string>
|
||||
<string name="screen_server_confirmation_message_login_matrix_dot_org">"Matrix, güvenli, merkezi olmayan iletişim için açık bir ağdır."</string>
|
||||
<string name="screen_server_confirmation_message_register">"Konuşmalarınızın saklanacağı yer burasıdır - tıpkı e-postalarınızı saklamak için bir e-posta sağlayıcısı kullandığınız gibi."</string>
|
||||
<string name="screen_server_confirmation_title_login">"%1$s sunucusunda oturum açmak üzeresiniz"</string>
|
||||
<string name="screen_server_confirmation_title_register">"%1$s sunucusunda bir hesap oluşturmak üzeresiniz"</string>
|
||||
</resources>
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
<string name="screen_change_server_form_notice">"Siz faqat siljish sinxronlashni qo\'llab-quvvatlaydigan mavjud serverga ulanishingiz mumkin. Uy serveringiz administratori uni sozlashi kerak.%1$s"</string>
|
||||
<string name="screen_change_server_subtitle">"Serveringizning manzili nima?"</string>
|
||||
<string name="screen_change_server_title">"Serveringizni tanlang"</string>
|
||||
<string name="screen_create_account_title">"Hisob yaratish"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Bu hisob o‘chirilgan."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Notog\'ri foydalanuvchi nomi va/yoki parol"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Bu haqiqiy foydalanuvchi identifikatori emas. Kutilayotgan format: \'@user:homeserver.org\'"</string>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ interface LogoutEntryPoint : FeatureEntryPoint {
|
|||
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
|
||||
|
||||
interface NodeBuilder {
|
||||
fun onSuccessfulLogoutPendingAction(action: () -> Unit): NodeBuilder
|
||||
fun callback(callback: Callback): NodeBuilder
|
||||
fun build(): Node
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,15 +27,6 @@ class DefaultLogoutEntryPoint @Inject constructor() : LogoutEntryPoint {
|
|||
return this
|
||||
}
|
||||
|
||||
override fun onSuccessfulLogoutPendingAction(action: () -> Unit): LogoutEntryPoint.NodeBuilder {
|
||||
plugins += object : LogoutNode.SuccessfulLogoutPendingAction, Plugin {
|
||||
override fun onSuccessfulLogoutPendingAction() {
|
||||
action()
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override fun build(): Node {
|
||||
return parentNode.createNode<LogoutNode>(buildContext, plugins)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,6 @@ class LogoutNode @AssistedInject constructor(
|
|||
plugins<LogoutEntryPoint.Callback>().forEach { it.onChangeRecoveryKeyClick() }
|
||||
}
|
||||
|
||||
interface SuccessfulLogoutPendingAction : Plugin {
|
||||
fun onSuccessfulLogoutPendingAction()
|
||||
}
|
||||
|
||||
private val customOnSuccessfulLogoutPendingAction = plugins<SuccessfulLogoutPendingAction>().firstOrNull()
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val state = presenter.present()
|
||||
|
|
@ -47,7 +41,6 @@ class LogoutNode @AssistedInject constructor(
|
|||
state = state,
|
||||
onChangeRecoveryKeyClick = ::onChangeRecoveryKeyClick,
|
||||
onSuccessLogout = {
|
||||
customOnSuccessfulLogoutPendingAction?.onSuccessfulLogoutPendingAction()
|
||||
onSuccessLogout(activity, isDark, it)
|
||||
},
|
||||
onBackClick = ::navigateUp,
|
||||
|
|
|
|||
18
features/logout/impl/src/main/res/values-tr/translations.xml
Normal file
18
features/logout/impl/src/main/res/values-tr/translations.xml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_signout_confirmation_dialog_content">"Çıkış yapmak istediğinize emin misiniz?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Oturumu kapat"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Oturumu kapat"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Oturum kapatılıyor…"</string>
|
||||
<string name="screen_signout_key_backup_disabled_subtitle">"Son oturumunuzdan çıkmak üzeresiniz. Şimdi çıkış yaparsanız, şifrelenmiş mesajlarınıza erişiminizi kaybedersiniz."</string>
|
||||
<string name="screen_signout_key_backup_disabled_title">"Yedeklemeyi kapattınız"</string>
|
||||
<string name="screen_signout_key_backup_offline_subtitle">"Çevrimdışı olduğunuzda anahtarlarınız hala yedekleniyordu. Oturumu kapatmadan önce anahtarlarınızın yedeklenebilmesi için yeniden bağlanın."</string>
|
||||
<string name="screen_signout_key_backup_offline_title">"Anahtarlarınız hala yedekleniyor"</string>
|
||||
<string name="screen_signout_key_backup_ongoing_subtitle">"Lütfen oturumu kapatmadan önce bunun tamamlanmasını bekleyin."</string>
|
||||
<string name="screen_signout_key_backup_ongoing_title">"Anahtarlarınız hala yedekleniyor"</string>
|
||||
<string name="screen_signout_preference_item">"Oturumu kapat"</string>
|
||||
<string name="screen_signout_recovery_disabled_subtitle">"Son oturumunuzdan çıkmak üzeresiniz. Şimdi çıkış yaparsanız şifrelenmiş mesajlarınıza erişiminizi kaybedersiniz."</string>
|
||||
<string name="screen_signout_recovery_disabled_title">"Kurtarma ayarlanmadı"</string>
|
||||
<string name="screen_signout_save_recovery_key_subtitle">"Son oturumunuzdan çıkmak üzeresiniz. Şimdi oturumu kapatırsanız şifrelenmiş mesajlarınıza erişiminizi kaybedebilirsiniz."</string>
|
||||
<string name="screen_signout_save_recovery_key_title">"Kurtarma anahtarınızı kaydettiniz mi?"</string>
|
||||
</resources>
|
||||
|
|
@ -71,6 +71,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkData
|
|||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.alias.matches
|
||||
import io.element.android.libraries.matrix.api.room.joinedRoomMembers
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.ui.messages.LocalRoomMemberProfilesCache
|
||||
import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache
|
||||
|
|
@ -187,8 +188,11 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
callbacks.forEach { it.onRoomDetailsClick() }
|
||||
}
|
||||
|
||||
override fun onEventClick(event: TimelineItem.Event): Boolean {
|
||||
return processEventClick(event)
|
||||
override fun onEventClick(isLive: Boolean, event: TimelineItem.Event): Boolean {
|
||||
return processEventClick(
|
||||
timelineMode = if (isLive) Timeline.Mode.LIVE else Timeline.Mode.FOCUSED_ON_EVENT,
|
||||
event = event,
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPreviewAttachments(attachments: ImmutableList<Attachment>) {
|
||||
|
|
@ -316,7 +320,10 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
NavTarget.PinnedMessagesList -> {
|
||||
val callback = object : PinnedMessagesListNode.Callback {
|
||||
override fun onEventClick(event: TimelineItem.Event) {
|
||||
processEventClick(event)
|
||||
processEventClick(
|
||||
timelineMode = Timeline.Mode.PINNED_EVENTS,
|
||||
event = event,
|
||||
)
|
||||
}
|
||||
|
||||
override fun onUserDataClick(userId: UserId) {
|
||||
|
|
@ -358,11 +365,14 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
callbacks.forEach { it.onPermalinkClick(permalinkData, pushToBackstack = false) }
|
||||
}
|
||||
|
||||
private fun processEventClick(event: TimelineItem.Event): Boolean {
|
||||
private fun processEventClick(
|
||||
timelineMode: Timeline.Mode,
|
||||
event: TimelineItem.Event,
|
||||
): Boolean {
|
||||
val navTarget = when (event.content) {
|
||||
is TimelineItemImageContent -> {
|
||||
buildMediaViewerNavTarget(
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineImagesAndVideos,
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineImagesAndVideos(timelineMode),
|
||||
event = event,
|
||||
content = event.content,
|
||||
mediaSource = event.content.mediaSource,
|
||||
|
|
@ -374,7 +384,7 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
if encrypted on certain bridges */
|
||||
event.content.preferredMediaSource?.let { preferredMediaSource ->
|
||||
buildMediaViewerNavTarget(
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineImagesAndVideos,
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineImagesAndVideos(timelineMode),
|
||||
event = event,
|
||||
content = event.content,
|
||||
mediaSource = preferredMediaSource,
|
||||
|
|
@ -384,7 +394,7 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
}
|
||||
is TimelineItemVideoContent -> {
|
||||
buildMediaViewerNavTarget(
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineImagesAndVideos,
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineImagesAndVideos(timelineMode),
|
||||
event = event,
|
||||
content = event.content,
|
||||
mediaSource = event.content.mediaSource,
|
||||
|
|
@ -393,7 +403,7 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
}
|
||||
is TimelineItemFileContent -> {
|
||||
buildMediaViewerNavTarget(
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios,
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios(timelineMode),
|
||||
event = event,
|
||||
content = event.content,
|
||||
mediaSource = event.content.mediaSource,
|
||||
|
|
@ -402,7 +412,7 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
}
|
||||
is TimelineItemAudioContent -> {
|
||||
buildMediaViewerNavTarget(
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios,
|
||||
mode = MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios(timelineMode),
|
||||
event = event,
|
||||
content = event.content,
|
||||
mediaSource = event.content.mediaSource,
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class MessagesNode @AssistedInject constructor(
|
|||
|
||||
interface Callback : Plugin {
|
||||
fun onRoomDetailsClick()
|
||||
fun onEventClick(event: TimelineItem.Event): Boolean
|
||||
fun onEventClick(isLive: Boolean, event: TimelineItem.Event): Boolean
|
||||
fun onPreviewAttachments(attachments: ImmutableList<Attachment>)
|
||||
fun onUserDataClick(userId: UserId)
|
||||
fun onPermalinkClick(data: PermalinkData)
|
||||
|
|
@ -120,12 +120,12 @@ class MessagesNode @AssistedInject constructor(
|
|||
callbacks.forEach { it.onRoomDetailsClick() }
|
||||
}
|
||||
|
||||
private fun onEventClick(event: TimelineItem.Event): Boolean {
|
||||
private fun onEventClick(isLive: Boolean, event: TimelineItem.Event): Boolean {
|
||||
// Note: cannot use `callbacks.all { it.onEventClick(event) }` because:
|
||||
// - if callbacks is empty, it will return true and we want to return false.
|
||||
// - if a callback returns false, the other callback will not be invoked.
|
||||
return callbacks.takeIf { it.isNotEmpty() }
|
||||
?.map { it.onEventClick(event) }
|
||||
?.map { it.onEventClick(isLive, event) }
|
||||
?.all { it }
|
||||
.orFalse()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc
|
|||
import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState
|
||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents
|
||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||
import io.element.android.features.messages.impl.messagecomposer.observeRoomMemberIdentityStateChange
|
||||
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState
|
||||
import io.element.android.features.messages.impl.timeline.TimelineController
|
||||
import io.element.android.features.messages.impl.timeline.TimelineEvents
|
||||
|
|
@ -78,6 +79,7 @@ import io.element.android.libraries.matrix.ui.model.getAvatarData
|
|||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -154,7 +156,9 @@ class MessagesPresenter @AssistedInject constructor(
|
|||
var hasDismissedInviteDialog by rememberSaveable {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
val roomMemberIdentityStateChanges by produceState(persistentListOf()) {
|
||||
observeRoomMemberIdentityStateChange(room)
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
// Remove the unread flag on entering but don't send read receipts
|
||||
// as those will be handled by the timeline.
|
||||
|
|
@ -211,6 +215,7 @@ class MessagesPresenter @AssistedInject constructor(
|
|||
roomAvatar = roomAvatar,
|
||||
heroes = heroes,
|
||||
composerState = composerState,
|
||||
roomMemberIdentityStateChanges = roomMemberIdentityStateChanges,
|
||||
userEventPermissions = userEventPermissions,
|
||||
voiceMessageComposerState = voiceMessageComposerState,
|
||||
timelineState = timelineState,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ package io.element.android.features.messages.impl
|
|||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.features.messages.impl.actionlist.ActionListState
|
||||
import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState
|
||||
import io.element.android.features.messages.impl.crypto.identity.RoomMemberIdentityStateChange
|
||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState
|
||||
import io.element.android.features.messages.impl.timeline.TimelineState
|
||||
|
|
@ -33,6 +34,7 @@ data class MessagesState(
|
|||
val heroes: ImmutableList<AvatarData>,
|
||||
val userEventPermissions: UserEventPermissions,
|
||||
val composerState: MessageComposerState,
|
||||
val roomMemberIdentityStateChanges: ImmutableList<RoomMemberIdentityStateChange>,
|
||||
val voiceMessageComposerState: VoiceMessageComposerState,
|
||||
val timelineState: TimelineState,
|
||||
val timelineProtectionState: TimelineProtectionState,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
|||
import io.element.android.features.messages.impl.actionlist.ActionListState
|
||||
import io.element.android.features.messages.impl.actionlist.anActionListState
|
||||
import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState
|
||||
import io.element.android.features.messages.impl.crypto.identity.RoomMemberIdentityStateChange
|
||||
import io.element.android.features.messages.impl.crypto.identity.anIdentityChangeState
|
||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||
import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState
|
||||
|
|
@ -41,6 +42,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
|||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||
import io.element.android.libraries.textcomposer.model.aTextEditorStateRich
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentSetOf
|
||||
|
||||
|
|
@ -92,6 +94,7 @@ fun aMessagesState(
|
|||
isFullScreen = false,
|
||||
mode = MessageComposerMode.Normal,
|
||||
),
|
||||
roomMemberIdentityStateChanges: ImmutableList<RoomMemberIdentityStateChange> = persistentListOf(),
|
||||
voiceMessageComposerState: VoiceMessageComposerState = aVoiceMessageComposerState(),
|
||||
timelineState: TimelineState = aTimelineState(
|
||||
timelineItems = aTimelineItemList(aTimelineItemTextContent()),
|
||||
|
|
@ -117,6 +120,7 @@ fun aMessagesState(
|
|||
heroes = persistentListOf(),
|
||||
userEventPermissions = userEventPermissions,
|
||||
composerState = composerState,
|
||||
roomMemberIdentityStateChanges = roomMemberIdentityStateChanges,
|
||||
voiceMessageComposerState = voiceMessageComposerState,
|
||||
timelineProtectionState = timelineProtectionState,
|
||||
identityChangeState = identityChangeState,
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import io.element.android.features.messages.impl.actionlist.ActionListView
|
|||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
|
||||
import io.element.android.features.messages.impl.crypto.identity.IdentityChangeStateView
|
||||
import io.element.android.features.messages.impl.messagecomposer.AttachmentsBottomSheet
|
||||
import io.element.android.features.messages.impl.messagecomposer.DisabledComposerView
|
||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents
|
||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerView
|
||||
import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsPickerView
|
||||
|
|
@ -97,6 +98,7 @@ 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.EventId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
|
||||
import io.element.android.libraries.textcomposer.model.TextEditorState
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -109,7 +111,7 @@ fun MessagesView(
|
|||
state: MessagesState,
|
||||
onBackClick: () -> Unit,
|
||||
onRoomDetailsClick: () -> Unit,
|
||||
onEventContentClick: (event: TimelineItem.Event) -> Boolean,
|
||||
onEventContentClick: (isLive: Boolean, event: TimelineItem.Event) -> Boolean,
|
||||
onUserDataClick: (UserId) -> Unit,
|
||||
onLinkClick: (String, Boolean) -> Unit,
|
||||
onSendLocationClick: () -> Unit,
|
||||
|
|
@ -140,7 +142,7 @@ fun MessagesView(
|
|||
|
||||
fun onContentClick(event: TimelineItem.Event) {
|
||||
Timber.v("onMessageClick= ${event.id}")
|
||||
val hideKeyboard = onEventContentClick(event)
|
||||
val hideKeyboard = onEventContentClick(state.timelineState.isLive, event)
|
||||
if (hideKeyboard) {
|
||||
localView.hideKeyboard()
|
||||
}
|
||||
|
|
@ -425,13 +427,20 @@ private fun MessagesViewComposerBottomSheetContents(
|
|||
onLinkClick = onLinkClick,
|
||||
)
|
||||
}
|
||||
MessageComposerView(
|
||||
state = state.composerState,
|
||||
voiceMessageState = state.voiceMessageComposerState,
|
||||
subcomposing = subcomposing,
|
||||
enableVoiceMessages = state.enableVoiceMessages,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
val verificationViolation = state.roomMemberIdentityStateChanges.firstOrNull {
|
||||
it.identityState == IdentityState.VerificationViolation
|
||||
}
|
||||
if (verificationViolation != null) {
|
||||
DisabledComposerView(modifier = Modifier.fillMaxWidth())
|
||||
} else {
|
||||
MessageComposerView(
|
||||
state = state.composerState,
|
||||
voiceMessageState = state.voiceMessageComposerState,
|
||||
subcomposing = subcomposing,
|
||||
enableVoiceMessages = state.enableVoiceMessages,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CantSendMessageBanner()
|
||||
|
|
@ -535,7 +544,7 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class)
|
|||
state = state,
|
||||
onBackClick = {},
|
||||
onRoomDetailsClick = {},
|
||||
onEventContentClick = { false },
|
||||
onEventContentClick = { _, _ -> false },
|
||||
onUserDataClick = {},
|
||||
onLinkClick = { _, _ -> },
|
||||
onSendLocationClick = {},
|
||||
|
|
|
|||
|
|
@ -10,5 +10,6 @@ package io.element.android.features.messages.impl.crypto.identity
|
|||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
||||
sealed interface IdentityChangeEvent {
|
||||
data class Submit(val userId: UserId) : IdentityChangeEvent
|
||||
data class PinIdentity(val userId: UserId) : IdentityChangeEvent
|
||||
data class WithdrawVerification(val userId: UserId) : IdentityChangeEvent
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,30 +8,16 @@
|
|||
package io.element.android.features.messages.impl.crypto.identity
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ProduceStateScope
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import io.element.android.features.messages.impl.messagecomposer.observeRoomMemberIdentityStateChange
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
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.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.room.roomMembers
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
|
@ -44,12 +30,17 @@ class IdentityChangeStatePresenter @Inject constructor(
|
|||
override fun present(): IdentityChangeState {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val roomMemberIdentityStateChange by produceState(persistentListOf()) {
|
||||
observeRoomMemberIdentityStateChange()
|
||||
observeRoomMemberIdentityStateChange(room)
|
||||
}
|
||||
|
||||
fun handleEvent(event: IdentityChangeEvent) {
|
||||
when (event) {
|
||||
is IdentityChangeEvent.Submit -> coroutineScope.pinUserIdentity(event.userId)
|
||||
is IdentityChangeEvent.WithdrawVerification -> {
|
||||
coroutineScope.withdrawVerification(event.userId)
|
||||
}
|
||||
is IdentityChangeEvent.PinIdentity -> {
|
||||
coroutineScope.pinUserIdentity(event.userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,56 +50,17 @@ class IdentityChangeStatePresenter @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private fun ProduceStateScope<PersistentList<RoomMemberIdentityStateChange>>.observeRoomMemberIdentityStateChange() {
|
||||
room.syncUpdateFlow
|
||||
.filter {
|
||||
// Room cannot become unencrypted, so we can just apply a filter here.
|
||||
room.isEncrypted
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest {
|
||||
combine(room.identityStateChangesFlow, room.membersStateFlow) { identityStateChanges, membersState ->
|
||||
identityStateChanges.map { identityStateChange ->
|
||||
val member = membersState.roomMembers()
|
||||
?.firstOrNull { roomMember -> roomMember.userId == identityStateChange.userId }
|
||||
?.toIdentityRoomMember()
|
||||
?: createDefaultRoomMemberForIdentityChange(identityStateChange.userId)
|
||||
RoomMemberIdentityStateChange(
|
||||
identityRoomMember = member,
|
||||
identityState = identityStateChange.identityState,
|
||||
)
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.onEach { roomMemberIdentityStateChanges ->
|
||||
value = roomMemberIdentityStateChanges.toPersistentList()
|
||||
}
|
||||
}
|
||||
.launchIn(this)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.pinUserIdentity(userId: UserId) = launch {
|
||||
encryptionService.pinUserIdentity(userId)
|
||||
.onFailure {
|
||||
Timber.e(it, "Failed to pin identity for user $userId")
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.withdrawVerification(userId: UserId) = launch {
|
||||
encryptionService.withdrawVerification(userId)
|
||||
.onFailure {
|
||||
Timber.e(it, "Failed to withdraw verification for user $userId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun RoomMember.toIdentityRoomMember() = IdentityRoomMember(
|
||||
userId = userId,
|
||||
displayNameOrDefault = displayNameOrDefault,
|
||||
avatarData = getAvatarData(AvatarSize.ComposerAlert),
|
||||
)
|
||||
|
||||
private fun createDefaultRoomMemberForIdentityChange(userId: UserId) = IdentityRoomMember(
|
||||
userId = userId,
|
||||
displayNameOrDefault = userId.extractedDisplayName,
|
||||
avatarData = AvatarData(
|
||||
id = userId.value,
|
||||
name = null,
|
||||
url = null,
|
||||
size = AvatarSize.ComposerAlert,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class IdentityChangeStateProvider : PreviewParameterProvider<IdentityChangeState
|
|||
roomMemberIdentityStateChanges = listOf(
|
||||
aRoomMemberIdentityStateChange(
|
||||
identityRoomMember = anIdentityRoomMember(displayNameOrDefault = "Alice"),
|
||||
identityState = IdentityState.PinViolation,
|
||||
identityState = IdentityState.VerificationViolation,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -47,9 +47,10 @@ internal fun aRoomMemberIdentityStateChange(
|
|||
|
||||
internal fun anIdentityChangeState(
|
||||
roomMemberIdentityStateChanges: List<RoomMemberIdentityStateChange> = emptyList(),
|
||||
eventSink: (IdentityChangeEvent) -> Unit = {},
|
||||
) = IdentityChangeState(
|
||||
roomMemberIdentityStateChanges = roomMemberIdentityStateChanges.toImmutableList(),
|
||||
eventSink = {},
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
||||
internal fun anIdentityRoomMember(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.features.messages.impl.crypto.identity
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -17,10 +18,12 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.appconfig.LearnMoreConfig
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
|
||||
import io.element.android.libraries.matrix.api.encryption.identity.isAViolation
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
|
|
@ -29,63 +32,90 @@ fun IdentityChangeStateView(
|
|||
onLinkClick: (String, Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
// Pick the first identity change to PinViolation
|
||||
val pinViolationIdentityChange = state.roomMemberIdentityStateChanges.firstOrNull {
|
||||
// For now only render PinViolation
|
||||
it.identityState == IdentityState.PinViolation
|
||||
// Pick the first identity change that is a violation
|
||||
val identityChangeViolation = state.roomMemberIdentityStateChanges.firstOrNull {
|
||||
it.identityState.isAViolation()
|
||||
}
|
||||
if (pinViolationIdentityChange != null) {
|
||||
ComposerAlertMolecule(
|
||||
when (identityChangeViolation?.identityState) {
|
||||
IdentityState.PinViolation -> ViolationAlert(
|
||||
identityChangeViolation = identityChangeViolation,
|
||||
onLinkClick = onLinkClick,
|
||||
textId = CommonStrings.crypto_identity_change_pin_violation_new,
|
||||
isCritical = false,
|
||||
submitTextId = CommonStrings.action_ok,
|
||||
onSubmitClick = { state.eventSink(IdentityChangeEvent.PinIdentity(identityChangeViolation.identityRoomMember.userId)) },
|
||||
modifier = modifier,
|
||||
avatar = pinViolationIdentityChange.identityRoomMember.avatarData,
|
||||
content = buildAnnotatedString {
|
||||
val learnMoreStr = stringResource(CommonStrings.action_learn_more)
|
||||
val displayName = pinViolationIdentityChange.identityRoomMember.displayNameOrDefault
|
||||
val userIdStr = stringResource(
|
||||
CommonStrings.crypto_identity_change_pin_violation_new_user_id,
|
||||
pinViolationIdentityChange.identityRoomMember.userId,
|
||||
)
|
||||
val fullText = stringResource(
|
||||
id = CommonStrings.crypto_identity_change_pin_violation_new,
|
||||
displayName,
|
||||
userIdStr,
|
||||
learnMoreStr,
|
||||
)
|
||||
append(fullText)
|
||||
val userIdStartIndex = fullText.indexOf(userIdStr)
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
start = userIdStartIndex,
|
||||
end = userIdStartIndex + userIdStr.length,
|
||||
)
|
||||
val learnMoreStartIndex = fullText.lastIndexOf(learnMoreStr)
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
textDecoration = TextDecoration.Underline,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
start = learnMoreStartIndex,
|
||||
end = learnMoreStartIndex + learnMoreStr.length,
|
||||
)
|
||||
addLink(
|
||||
url = LinkAnnotation.Url(
|
||||
url = LearnMoreConfig.IDENTITY_CHANGE_URL,
|
||||
linkInteractionListener = {
|
||||
onLinkClick(LearnMoreConfig.IDENTITY_CHANGE_URL, true)
|
||||
}
|
||||
),
|
||||
start = learnMoreStartIndex,
|
||||
end = learnMoreStartIndex + learnMoreStr.length,
|
||||
)
|
||||
},
|
||||
onSubmitClick = { state.eventSink(IdentityChangeEvent.Submit(pinViolationIdentityChange.identityRoomMember.userId)) },
|
||||
isCritical = pinViolationIdentityChange.identityState == IdentityState.VerificationViolation,
|
||||
)
|
||||
IdentityState.VerificationViolation -> ViolationAlert(
|
||||
identityChangeViolation = identityChangeViolation,
|
||||
onLinkClick = onLinkClick,
|
||||
textId = CommonStrings.crypto_identity_change_verification_violation_new,
|
||||
isCritical = true,
|
||||
submitTextId = CommonStrings.crypto_identity_change_withdraw_verification_action,
|
||||
onSubmitClick = { state.eventSink(IdentityChangeEvent.WithdrawVerification(identityChangeViolation.identityRoomMember.userId)) },
|
||||
modifier = modifier,
|
||||
)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ViolationAlert(
|
||||
identityChangeViolation: RoomMemberIdentityStateChange,
|
||||
onLinkClick: (String, Boolean) -> Unit,
|
||||
@StringRes textId: Int,
|
||||
isCritical: Boolean,
|
||||
@StringRes submitTextId: Int,
|
||||
onSubmitClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
ComposerAlertMolecule(
|
||||
modifier = modifier,
|
||||
avatar = identityChangeViolation.identityRoomMember.avatarData,
|
||||
content = buildAnnotatedString {
|
||||
val learnMoreStr = stringResource(CommonStrings.action_learn_more)
|
||||
val displayName = identityChangeViolation.identityRoomMember.displayNameOrDefault
|
||||
val userIdStr = stringResource(
|
||||
CommonStrings.crypto_identity_change_pin_violation_new_user_id,
|
||||
identityChangeViolation.identityRoomMember.userId,
|
||||
)
|
||||
val fullText = stringResource(textId, displayName, userIdStr, learnMoreStr)
|
||||
append(fullText)
|
||||
val userIdStartIndex = fullText.indexOf(userIdStr)
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
start = userIdStartIndex,
|
||||
end = userIdStartIndex + userIdStr.length,
|
||||
)
|
||||
val learnMoreStartIndex = fullText.lastIndexOf(learnMoreStr)
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
textDecoration = TextDecoration.Underline,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = ElementTheme.colors.textPrimary
|
||||
),
|
||||
start = learnMoreStartIndex,
|
||||
end = learnMoreStartIndex + learnMoreStr.length,
|
||||
)
|
||||
addLink(
|
||||
url = LinkAnnotation.Url(
|
||||
url = LearnMoreConfig.IDENTITY_CHANGE_URL,
|
||||
linkInteractionListener = {
|
||||
onLinkClick(LearnMoreConfig.IDENTITY_CHANGE_URL, true)
|
||||
}
|
||||
),
|
||||
start = learnMoreStartIndex,
|
||||
end = learnMoreStartIndex + learnMoreStr.length,
|
||||
)
|
||||
},
|
||||
submitText = stringResource(submitTextId),
|
||||
onSubmitClick = onSubmitClick,
|
||||
isCritical = isCritical,
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun IdentityChangeStateViewPreview(
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ internal fun MessagesViewWithIdentityChangePreview(
|
|||
),
|
||||
onBackClick = {},
|
||||
onRoomDetailsClick = {},
|
||||
onEventContentClick = { false },
|
||||
onEventContentClick = { _, _ -> false },
|
||||
onUserDataClick = {},
|
||||
onLinkClick = { _, _ -> },
|
||||
onSendLocationClick = {},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.messages.impl.messagecomposer
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeightIn
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
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.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.IconButton
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.textcomposer.R
|
||||
|
||||
@Composable
|
||||
internal fun DisabledComposerView(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier.padding(3.dp)
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
IconButton(
|
||||
modifier = Modifier
|
||||
.size(48.dp),
|
||||
enabled = false,
|
||||
onClick = {},
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(30.dp),
|
||||
resourceId = CommonDrawables.ic_plus_composer,
|
||||
contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment),
|
||||
tint = ElementTheme.colors.iconDisabled,
|
||||
)
|
||||
}
|
||||
|
||||
val bgColor = ElementTheme.colors.bgCanvasDisabled
|
||||
val borderColor = ElementTheme.colors.borderDisabled
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(21.dp))
|
||||
.border(0.5.dp, borderColor, RoundedCornerShape(21.dp))
|
||||
.background(color = bgColor)
|
||||
.size(42.dp)
|
||||
.requiredHeightIn(min = 42.dp)
|
||||
.weight(1f),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
IconButton(
|
||||
modifier = Modifier
|
||||
.padding(start = 2.dp)
|
||||
.size(48.dp),
|
||||
enabled = false,
|
||||
onClick = {},
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(30.dp),
|
||||
imageVector = CompoundIcons.SendSolid(),
|
||||
contentDescription = "",
|
||||
tint = ElementTheme.colors.iconQuaternary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun DisabledComposerViewPreview() = ElementPreview {
|
||||
Column {
|
||||
DisabledComposerView(
|
||||
modifier = Modifier.height(IntrinsicSize.Min),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -389,6 +389,7 @@ class MessageComposerPresenter @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MessageComposerState(
|
||||
textEditorState = textEditorState,
|
||||
isFullScreen = isFullScreen.value,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.messages.impl.messagecomposer
|
||||
|
||||
import androidx.compose.runtime.ProduceStateScope
|
||||
import io.element.android.features.messages.impl.crypto.identity.IdentityRoomMember
|
||||
import io.element.android.features.messages.impl.crypto.identity.RoomMemberIdentityStateChange
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.room.roomMembers
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun ProduceStateScope<PersistentList<RoomMemberIdentityStateChange>>.observeRoomMemberIdentityStateChange(room: MatrixRoom) {
|
||||
room.syncUpdateFlow
|
||||
.filter {
|
||||
// Room cannot become unencrypted, so we can just apply a filter here.
|
||||
room.isEncrypted
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest {
|
||||
combine(room.identityStateChangesFlow, room.membersStateFlow) { identityStateChanges, membersState ->
|
||||
identityStateChanges.map { identityStateChange ->
|
||||
val member = membersState.roomMembers()
|
||||
?.firstOrNull { roomMember -> roomMember.userId == identityStateChange.userId }
|
||||
?.toIdentityRoomMember()
|
||||
?: createDefaultRoomMemberForIdentityChange(identityStateChange.userId)
|
||||
RoomMemberIdentityStateChange(
|
||||
identityRoomMember = member,
|
||||
identityState = identityStateChange.identityState,
|
||||
)
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.onEach { roomMemberIdentityStateChanges ->
|
||||
value = roomMemberIdentityStateChanges.toPersistentList()
|
||||
}
|
||||
}
|
||||
.launchIn(this)
|
||||
}
|
||||
|
||||
private fun RoomMember.toIdentityRoomMember() = IdentityRoomMember(
|
||||
userId = userId,
|
||||
displayNameOrDefault = displayNameOrDefault,
|
||||
avatarData = getAvatarData(AvatarSize.ComposerAlert),
|
||||
)
|
||||
|
||||
private fun createDefaultRoomMemberForIdentityChange(userId: UserId) = IdentityRoomMember(
|
||||
userId = userId,
|
||||
displayNameOrDefault = userId.extractedDisplayName,
|
||||
avatarData = AvatarData(
|
||||
id = userId.value,
|
||||
name = null,
|
||||
url = null,
|
||||
size = AvatarSize.ComposerAlert,
|
||||
),
|
||||
)
|
||||
|
|
@ -139,6 +139,7 @@ internal fun MessageComposerViewPreview(
|
|||
enableVoiceMessages = true,
|
||||
subcomposing = false,
|
||||
)
|
||||
DisabledComposerView()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue