Merge remote-tracking branch 'origin/develop' into feature/fre/start_chat_with_matrix_id
This commit is contained in:
28
.github/workflows/sync-localazy.yml
vendored
Normal file
28
.github/workflows/sync-localazy.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Sync Localazy
|
||||
on:
|
||||
schedule:
|
||||
# At 00:00 on every Monday UTC
|
||||
- cron: '0 0 * * 1'
|
||||
|
||||
jobs:
|
||||
sync-localazy:
|
||||
runs-on: ubuntu-latest
|
||||
# Skip in forks
|
||||
if: github.repository == 'vector-im/element-x-android'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Run Localazy script
|
||||
run: ./tools/localazy/downloadStrings.sh --all
|
||||
- name: Create Pull Request for Strings
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
commit-message: Sync Strings from Localazy
|
||||
title: Sync Strings
|
||||
body: |
|
||||
- Update Strings from Localazy
|
||||
branch: sync-localazy
|
||||
base: develop
|
||||
@@ -5,7 +5,9 @@
|
||||
* [Contributing code to Matrix](#contributing-code-to-matrix)
|
||||
* [Android Studio settings](#android-studio-settings)
|
||||
* [Compilation](#compilation)
|
||||
* [I want to help translating Element](#i-want-to-help-translating-element)
|
||||
* [Strings](#strings)
|
||||
* [I want to add new strings to the project](#i-want-to-add-new-strings-to-the-project)
|
||||
* [I want to help translating Element](#i-want-to-help-translating-element)
|
||||
* [I want to submit a PR to fix an issue](#i-want-to-submit-a-pr-to-fix-an-issue)
|
||||
* [Kotlin](#kotlin)
|
||||
* [Changelog](#changelog)
|
||||
@@ -15,7 +17,6 @@
|
||||
* [lint](#lint)
|
||||
* [Unit tests](#unit-tests)
|
||||
* [Tests](#tests)
|
||||
* [Internationalisation](#internationalisation)
|
||||
* [Accessibility](#accessibility)
|
||||
* [Jetpack Compose](#jetpack-compose)
|
||||
* [Authors](#authors)
|
||||
@@ -40,11 +41,28 @@ Please ensure that you're using the project formatting rules (which are in the p
|
||||
|
||||
This project should compile without any special action. Just clone it and open it with Android Studio, or compile from command line using `gradlew`.
|
||||
|
||||
## I want to help translating Element
|
||||
Note: please make sure that the configuration is `app` and not `samples.minimal`.
|
||||
|
||||
For now strings are coming from Element Android project, so:
|
||||
- If you want to fix an issue with an English string, please submit a PR on Element Android.
|
||||
- If you want to fix an issue in other languages, or add a missing translation, or even add a new language, please use [Weblate](https://translate.element.io/projects/element-android/).
|
||||
## Strings
|
||||
|
||||
The strings of the project are managed externally using [https://localazy.com](https://localazy.com) and shared with ElementX iOS.
|
||||
|
||||
### I want to add new strings to the project
|
||||
|
||||
Only the core team can modify or add English strings to Localazy. As an external contributor, if you want to add new strings, feel free to add an Android resource file to the project (for instance a file named `temporary.xml`), with a note in the description of the PR for the reviewer to integrate the String into `Localazy`. If accepted, the reviewer will add the String(s) for you, and then you can download them on your branch (following these [instructions](./tools/localazy/README.md#download-translations)) and remove the temporary file.
|
||||
|
||||
Please follow the naming rules for the key. More details in [the dedicated section in this README.md](./tools/localazy/README.md#key-naming-rules)
|
||||
|
||||
### I want to help translating Element
|
||||
|
||||
Please note that the Localazy project is not open yet for external contributions.
|
||||
|
||||
To help translating, please go to [https://localazy.com/p/element](https://localazy.com/p/element).
|
||||
|
||||
- If you want to fix an issue with an English string, please open an issue on the github project of ElementX (Android or iOS). Only the core team can modify or add English strings.
|
||||
- If you want to fix an issue in other languages, or add a missing translation, or even add a new language, please go to [https://localazy.com/p/element](https://localazy.com/p/element).
|
||||
|
||||
More informations can be found [in this README.md](./tools/localazy/README.md).
|
||||
|
||||
## I want to submit a PR to fix an issue
|
||||
|
||||
@@ -135,10 +153,6 @@ Also, if possible, please test your change on a real device. Testing on Android
|
||||
|
||||
You should consider adding Unit tests with your PR, and also integration tests (AndroidTest). Please refer to [this document](./docs/integration_tests.md) to install and run the integration test environment.
|
||||
|
||||
### Internationalisation
|
||||
|
||||
For now strings are coming from Element Android project, so please read [the documentation](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#internationalisation) from there.
|
||||
|
||||
### Accessibility
|
||||
|
||||
Please consider accessibility as an important point. As a minimum requirement, in layout XML files please use attributes such as `android:contentDescription` and `android:importantForAccessibility`, and test with a screen reader if it's working well. You can add new string resources, dedicated to accessibility, in this case, please prefix theirs id with `a11y_`.
|
||||
|
||||
@@ -22,6 +22,7 @@ import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
@@ -78,4 +79,10 @@ object AppModule {
|
||||
diffUpdateDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@SingleIn(AppScope::class)
|
||||
fun provideSnackbarDispatcher(): SnackbarDispatcher {
|
||||
return SnackbarDispatcher()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ dependencies {
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.matrixui)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
implementation(projects.features.verifysession.api)
|
||||
implementation(projects.features.roomdetails.api)
|
||||
implementation(projects.tests.uitests)
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav
|
||||
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
import io.element.android.libraries.ui.strings.R
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
class LoggedInEventProcessor @Inject constructor(
|
||||
private val snackbarDispatcher: SnackbarDispatcher,
|
||||
roomMembershipObserver: RoomMembershipObserver,
|
||||
sessionVerificationService: SessionVerificationService,
|
||||
) {
|
||||
|
||||
private var observingJob: Job? = null
|
||||
|
||||
private val displayLeftRoomMessage = roomMembershipObserver.updates
|
||||
.map { !it.isUserInRoom }
|
||||
|
||||
private val displayVerificationSuccessfulMessage = sessionVerificationService.verificationFlowState
|
||||
.map { it == VerificationFlowState.Finished }
|
||||
|
||||
fun observeEvents(coroutineScope: CoroutineScope) {
|
||||
observingJob = coroutineScope.launch {
|
||||
displayLeftRoomMessage.onEach {
|
||||
displayMessage(R.string.common_current_user_left_room)
|
||||
}.launchIn(this)
|
||||
|
||||
displayVerificationSuccessfulMessage
|
||||
.drop(1)
|
||||
.onEach {
|
||||
displayMessage(R.string.common_verification_complete)
|
||||
}.launchIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun stopObserving() {
|
||||
observingJob?.cancel()
|
||||
observingJob = null
|
||||
}
|
||||
|
||||
private suspend fun displayMessage(message: Int) {
|
||||
snackbarDispatcher.post(SnackbarMessage(message))
|
||||
}
|
||||
}
|
||||
@@ -47,13 +47,17 @@ import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.MAIN_SPACE
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.ui.di.MatrixUIBindings
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
@ContributesNode(AppScope::class)
|
||||
class LoggedInFlowNode @AssistedInject constructor(
|
||||
@@ -64,6 +68,8 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
private val createRoomEntryPoint: CreateRoomEntryPoint,
|
||||
private val appNavigationStateService: AppNavigationStateService,
|
||||
private val verifySessionEntryPoint: VerifySessionEntryPoint,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
snackbarDispatcher: SnackbarDispatcher,
|
||||
) : BackstackNode<LoggedInFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
initialElement = NavTarget.RoomList,
|
||||
@@ -88,6 +94,11 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
) : NodeInputs
|
||||
|
||||
private val inputs: Inputs = inputs()
|
||||
private val loggedInFlowProcessor = LoggedInEventProcessor(
|
||||
snackbarDispatcher,
|
||||
inputs.matrixClient.roomMembershipObserver(),
|
||||
inputs.matrixClient.sessionVerificationService(),
|
||||
)
|
||||
|
||||
override fun onBuilt() {
|
||||
super.onBuilt()
|
||||
@@ -100,6 +111,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
appNavigationStateService.onNavigateToSession(inputs.matrixClient.sessionId)
|
||||
// TODO We do not support Space yet, so directly navigate to main space
|
||||
appNavigationStateService.onNavigateToSpace(MAIN_SPACE)
|
||||
loggedInFlowProcessor.observeEvents(coroutineScope)
|
||||
},
|
||||
onDestroy = {
|
||||
val imageLoaderFactory = bindings<MatrixUIBindings>().notLoggedInImageLoaderFactory()
|
||||
@@ -107,6 +119,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||
plugins<LifecycleCallback>().forEach { it.onFlowReleased(inputs.matrixClient) }
|
||||
appNavigationStateService.onLeavingSpace()
|
||||
appNavigationStateService.onLeavingSession()
|
||||
loggedInFlowProcessor.stopObserving()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.element.android.appnav
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.bumble.appyx.core.composable.Children
|
||||
import com.bumble.appyx.core.lifecycle.subscribe
|
||||
@@ -38,7 +39,12 @@ import io.element.android.libraries.architecture.animation.rememberDefaultTransi
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import timber.log.Timber
|
||||
|
||||
@@ -49,6 +55,8 @@ class RoomFlowNode @AssistedInject constructor(
|
||||
private val messagesEntryPoint: MessagesEntryPoint,
|
||||
private val roomDetailsEntryPoint: RoomDetailsEntryPoint,
|
||||
private val appNavigationStateService: AppNavigationStateService,
|
||||
roomMembershipObserver: RoomMembershipObserver,
|
||||
coroutineScope: CoroutineScope,
|
||||
) : BackstackNode<RoomFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
initialElement = NavTarget.Messages,
|
||||
@@ -68,6 +76,7 @@ class RoomFlowNode @AssistedInject constructor(
|
||||
) : NodeInputs
|
||||
|
||||
private val inputs: Inputs = inputs()
|
||||
private val timeline = inputs.room.timeline()
|
||||
|
||||
private val roomFlowPresenter = RoomFlowPresenter(inputs.room)
|
||||
|
||||
@@ -85,6 +94,13 @@ class RoomFlowNode @AssistedInject constructor(
|
||||
appNavigationStateService.onLeavingRoom()
|
||||
}
|
||||
)
|
||||
|
||||
roomMembershipObserver.updates
|
||||
.filter { update -> update.roomId == inputs.room.roomId && !update.isUserInRoom }
|
||||
.onEach {
|
||||
navigateUp()
|
||||
}
|
||||
.launchIn(coroutineScope)
|
||||
}
|
||||
|
||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||
@@ -97,7 +113,7 @@ class RoomFlowNode @AssistedInject constructor(
|
||||
})
|
||||
}
|
||||
NavTarget.RoomDetails -> {
|
||||
roomDetailsEntryPoint.createNode(this, buildContext)
|
||||
roomDetailsEntryPoint.createNode(this, buildContext, emptyList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
changelog.d/286.feature
Normal file
1
changelog.d/286.feature
Normal file
@@ -0,0 +1 @@
|
||||
Add leave room functionality to the Room Details screen.
|
||||
@@ -0,0 +1,6 @@
|
||||
<?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">"Nueva sala"</string>
|
||||
<string name="screen_create_room_action_invite_people">"Invitar gente"</string>
|
||||
<string name="screen_create_room_add_people_title">"Añadir personas"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?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">"Nuova stanza"</string>
|
||||
<string name="screen_create_room_action_invite_people">"Invita persone"</string>
|
||||
<string name="screen_create_room_add_people_title">"Aggiungi persone"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?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">"Cameră nouă"</string>
|
||||
<string name="screen_create_room_action_invite_people">"Invitați persoane"</string>
|
||||
<string name="screen_create_room_add_people_title">"Adaugați persoane"</string>
|
||||
</resources>
|
||||
20
features/login/impl/src/main/res/values-es/translations.xml
Normal file
20
features/login/impl/src/main/res/values-es/translations.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_change_server_error_invalid_homeserver">"No hemos podido acceder a este servidor. Comprueba que has introducido correctamente la dirección del servidor. Si la dirección es correcta, ponte en contacto con el administrador del servidor para obtener más ayuda."</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"Este servidor no soporta sliding sync."</string>
|
||||
<string name="screen_change_server_form_header">"Dirección del homeserver"</string>
|
||||
<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_submit">"Continuar"</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_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>
|
||||
<string name="screen_login_error_unsupported_authentication">"El servidor seleccionado no admite contraseñas ni inicio de sesión OIDC. Póngase en contacto con su administrador o elija otro homeserver."</string>
|
||||
<string name="screen_login_form_header">"Introduce tus datos"</string>
|
||||
<string name="screen_login_password_hint">"Contraseña"</string>
|
||||
<string name="screen_login_server_header">"Donde viven tus conversaciones"</string>
|
||||
<string name="screen_login_submit">"Continuar"</string>
|
||||
<string name="screen_login_title">"¡Hola de nuevo!"</string>
|
||||
<string name="screen_login_username_hint">"Usuario"</string>
|
||||
</resources>
|
||||
20
features/login/impl/src/main/res/values-it/translations.xml
Normal file
20
features/login/impl/src/main/res/values-it/translations.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_change_server_error_invalid_homeserver">"Non siamo riusciti a raggiungere questo homserver. Verifica di aver inserito correttamente l\'URL del server domestico. Se l\'URL è corretto, contatta l\'amministratore del tuo server domestico per ulteriore assistenza."</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"Questo server attualmente non supporta la sincronizzazione scorrevole."</string>
|
||||
<string name="screen_change_server_form_header">"URL dell\'homeserver"</string>
|
||||
<string name="screen_change_server_form_notice">"Puoi connetterti solo a un server esistente che supporta la sincronizzazione scorrevole. L\'amministratore del tuo server domestico dovrà configurarlo. %1$s"</string>
|
||||
<string name="screen_change_server_submit">"Continua"</string>
|
||||
<string name="screen_change_server_subtitle">"Qual è l\'indirizzo del tuo server?"</string>
|
||||
<string name="screen_change_server_title">"Seleziona il tuo server"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Questo profilo è stato disattivato."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Nome utente e/o password errati"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Questo non è un identificatore utente valido. Formato previsto: \'@user:homeserver.org\'"</string>
|
||||
<string name="screen_login_error_unsupported_authentication">"L\'homeserver selezionato non supporta la password o l\'accesso OIDC. Contatta il tuo amministratore o scegli un altro homeserver."</string>
|
||||
<string name="screen_login_form_header">"Inserisci i tuoi dati"</string>
|
||||
<string name="screen_login_password_hint">"Password"</string>
|
||||
<string name="screen_login_server_header">"Dove vivono le tue conversazioni"</string>
|
||||
<string name="screen_login_submit">"Continua"</string>
|
||||
<string name="screen_login_title">"Bentornato!"</string>
|
||||
<string name="screen_login_username_hint">"Nome utente"</string>
|
||||
</resources>
|
||||
20
features/login/impl/src/main/res/values-ro/translations.xml
Normal file
20
features/login/impl/src/main/res/values-ro/translations.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_change_server_error_invalid_homeserver">"Nu am putut accesa acest homeserver. Te rugăm să verifici că ai introdus corect adresa URL a homeserver-ului. Dacă adresa URL este corectă, contactează administratorul homeserver-ului pentru ajutor suplimentar."</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"Momentan acest server nu oferă suport pentru sliding sync."</string>
|
||||
<string name="screen_change_server_form_header">"Adresa URL a homeserver-ului"</string>
|
||||
<string name="screen_change_server_form_notice">"Vă putețo conecta numai la un server existent care oferă suport pentru sliding sync. Administratorul homeserver-ului dumneavoastră va trebui să îl configureze. %1$s"</string>
|
||||
<string name="screen_change_server_submit">"Continuați"</string>
|
||||
<string name="screen_change_server_subtitle">"Care este adresa serverului dumneavoastră?"</string>
|
||||
<string name="screen_change_server_title">"Selectați serverul"</string>
|
||||
<string name="screen_login_error_deactivated_account">"Acest cont a fost dezactivat."</string>
|
||||
<string name="screen_login_error_invalid_credentials">"Utilizator și/sau parolă incorecte"</string>
|
||||
<string name="screen_login_error_invalid_user_id">"Acesta nu este un identificator de utilizator valid. Format așteptat: „@user:homeserver.org”"</string>
|
||||
<string name="screen_login_error_unsupported_authentication">"Homeserver-ul selectat nu acceptă autentificarea prin parola sau OIDC. Te rugăm să contactezi administratorul sau să alegi un alt homeserver."</string>
|
||||
<string name="screen_login_form_header">"Introduceți detaliile"</string>
|
||||
<string name="screen_login_password_hint">"Parolă"</string>
|
||||
<string name="screen_login_server_header">"Locul unde trăiesc conversațiile tale"</string>
|
||||
<string name="screen_login_submit">"Continuați"</string>
|
||||
<string name="screen_login_title">"Bine ați revenit!"</string>
|
||||
<string name="screen_login_username_hint">"Utilizator"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?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">"¿Estás seguro de que quieres cerrar sesión?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Cerrar sesión"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Cerrar sesión"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Cerrando sesión…"</string>
|
||||
<string name="screen_signout_preference_item">"Cerrar sesión"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?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">"Sei sicuro di voler uscire?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Esci"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Esci"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Uscita in corso…"</string>
|
||||
<string name="screen_signout_preference_item">"Esci"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?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">"Sunteți sigur că vreți să vă deconectați?"</string>
|
||||
<string name="screen_signout_confirmation_dialog_submit">"Deconectați-vă"</string>
|
||||
<string name="screen_signout_confirmation_dialog_title">"Deconectați-vă"</string>
|
||||
<string name="screen_signout_in_progress_dialog_content">"Deconectare în curs…"</string>
|
||||
<string name="screen_signout_preference_item">"Deconectați-vă"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_onboarding_welcome_subtitle">"Bienvenido a la beta de %1$s. Vitaminado, para mayor rapidez y sencillez."</string>
|
||||
<string name="screen_onboarding_welcome_title">"Siéntente en tu Elemento"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_onboarding_welcome_subtitle">"Benvenuto nella beta di %1$s. Potenziato in velocità e semplicità."</string>
|
||||
<string name="screen_onboarding_welcome_title">"Sii nel tuo elemento"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_onboarding_welcome_subtitle">"Bun venit la versiunea beta a %1$s. Supraalimentat, pentru viteză și simplitate."</string>
|
||||
<string name="screen_onboarding_welcome_title">"Fii în Elementul tău"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="crash_detection_dialog_content">"%1$s se cerró inesperadamente la última vez que se lo usaste. ¿Quieres compartir un informe de error con nosotros?"</string>
|
||||
<string name="rageshake_detection_dialog_content">"Parece que sacudes el teléfono con frustración. ¿Quieres abrir la pantalla de informe de errores?"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="crash_detection_dialog_content">"%1$s si è chiuso inaspettatamente l\'ultima volta che è stato usato. Vuoi condividere con noi un rapporto sull\'arresto anomalo?"</string>
|
||||
<string name="rageshake_detection_dialog_content">"Sembra che tu stia scuotendo il telefono per la frustrazione. Vuoi aprire la schermata di segnalazione dei problemi?"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="crash_detection_dialog_content">"%1$s s-a blocat ultima dată când a fost folosit. Doriți să ne trimiteți un raport?"</string>
|
||||
<string name="rageshake_detection_dialog_content">"Se pare că scuturați telefonul de frustrare. Doriți să deschdeți ecranul de raportare a unei erori?"</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_bug_report_attach_screenshot">"Adjuntar captura de pantalla"</string>
|
||||
<string name="screen_bug_report_contact_me">"Podéis poneros en contacto conmigo para resolver dudas relacionadas"</string>
|
||||
<string name="screen_bug_report_edit_screenshot">"Editar captura de pantalla"</string>
|
||||
<string name="screen_bug_report_editor_description">"Describe el problema. ¿Qué hiciste? ¿Qué esperabas que ocurriera? ¿Qué ocurrió en realidad? Por favor, detállalo todo lo que puedas."</string>
|
||||
<string name="screen_bug_report_editor_placeholder">"Describe el error…"</string>
|
||||
<string name="screen_bug_report_editor_supporting">"Si es posible, escriba la descripción en inglés."</string>
|
||||
<string name="screen_bug_report_include_crash_logs">"Enviar registros de fallos"</string>
|
||||
<string name="screen_bug_report_include_logs">"Enviar registros para ayudar"</string>
|
||||
<string name="screen_bug_report_include_screenshot">"Enviar captura de pantalla"</string>
|
||||
<string name="screen_bug_report_logs_description">"Para comprobar que todo funciona correctamente, se enviarán registros de fallos con su mensaje. Serán privados. Para enviar sólo tu mensaje, desactiva esta opción."</string>
|
||||
<string name="screen_bug_report_rash_logs_alert_title">"%1$s se cerró inesperadamente la última vez que se lo usaste. ¿Quieres compartir un informe de error con nosotros?"</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_bug_report_attach_screenshot">"Allega istantanea schermo"</string>
|
||||
<string name="screen_bug_report_contact_me">"Potete contattarmi per qualsiasi altra domanda"</string>
|
||||
<string name="screen_bug_report_edit_screenshot">"Modifica istantanea schermo"</string>
|
||||
<string name="screen_bug_report_editor_description">"Descrivi il bug. Che cosa hai fatto? Cosa ti aspettavi che accadesse? Cosa è effettivamente accaduto. Si prega di inserire il maggior numero di dettagli possibile."</string>
|
||||
<string name="screen_bug_report_editor_placeholder">"Descrivi il problema…"</string>
|
||||
<string name="screen_bug_report_editor_supporting">"Se possibile, scrivere la descrizione in inglese."</string>
|
||||
<string name="screen_bug_report_include_crash_logs">"Invia i log degli arresti anomali"</string>
|
||||
<string name="screen_bug_report_include_logs">"Invia i log per aiutarci"</string>
|
||||
<string name="screen_bug_report_include_screenshot">"Invia istantanea schermo"</string>
|
||||
<string name="screen_bug_report_logs_description">"Per verificare che le cose funzionino come previsto, i log verranno inviati con il tuo messaggio. Questi saranno privati. Per inviare solo il tuo messaggio, disattiva questa impostazione."</string>
|
||||
<string name="screen_bug_report_rash_logs_alert_title">"%1$s si è chiuso inaspettatamente l\'ultima volta che è stato usato. Vuoi condividere con noi un rapporto sull\'arresto anomalo?"</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_bug_report_attach_screenshot">"Atașați o captură de ecran"</string>
|
||||
<string name="screen_bug_report_contact_me">"Puteți să mă contactați dacă aveți întrebări suplimentare"</string>
|
||||
<string name="screen_bug_report_edit_screenshot">"Editați captura de ecran"</string>
|
||||
<string name="screen_bug_report_editor_description">"Vă rugăm să descrieți eroarea. Ce ați făcut? Ce vă aşteptați să se întâmple? Ce s-a întâmplat de fapt. Vă rugam să intrați în cât mai multe detalii cu putință."</string>
|
||||
<string name="screen_bug_report_editor_placeholder">"Descrieți eroarea…"</string>
|
||||
<string name="screen_bug_report_editor_supporting">"Dacă posibil, vă rugăm să scrieți descrierea în engleză."</string>
|
||||
<string name="screen_bug_report_include_crash_logs">"Trimiteți log-uri"</string>
|
||||
<string name="screen_bug_report_include_logs">"Trimiteți log-uri pentru a ajuta"</string>
|
||||
<string name="screen_bug_report_include_screenshot">"Trimiteți captură de ecran"</string>
|
||||
<string name="screen_bug_report_logs_description">"Pentru a verifica că lucrurile funcționează conform așteptărilor, log-uri vor fi trimise împreună cu mesajul. Acestea vor fi private. Pentru a trimite doar mesajul, dezactivați această setare."</string>
|
||||
<string name="screen_bug_report_rash_logs_alert_title">"%1$s s-a blocat ultima dată când a fost folosit. Dorești să ne trimiti un raport?"</string>
|
||||
</resources>
|
||||
@@ -18,9 +18,9 @@ package io.element.android.features.roomdetails.api
|
||||
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import io.element.android.libraries.architecture.FeatureEntryPoint
|
||||
|
||||
interface RoomDetailsEntryPoint : FeatureEntryPoint {
|
||||
fun createNode(parentNode: Node, buildContext: BuildContext): Node
|
||||
|
||||
fun createNode(parentNode: Node, buildContext: BuildContext, plugins: List<Plugin>): Node
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.element.android.features.roomdetails.impl
|
||||
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
@@ -26,7 +27,7 @@ import javax.inject.Inject
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultRoomDetailsEntryPoint @Inject constructor() : RoomDetailsEntryPoint {
|
||||
override fun createNode(parentNode: Node, buildContext: BuildContext): Node {
|
||||
return parentNode.createNode<RoomDetailsFlowNode>(buildContext)
|
||||
override fun createNode(parentNode: Node, buildContext: BuildContext, plugins: List<Plugin>): Node {
|
||||
return parentNode.createNode<RoomDetailsFlowNode>(buildContext, plugins)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,8 @@
|
||||
|
||||
package io.element.android.features.roomdetails.impl
|
||||
|
||||
sealed interface RoomDetailsEvent
|
||||
sealed interface RoomDetailsEvent {
|
||||
data class LeaveRoom(val needsConfirmation: Boolean) : RoomDetailsEvent
|
||||
object ClearLeaveRoomWarning : RoomDetailsEvent
|
||||
object ClearError : RoomDetailsEvent
|
||||
}
|
||||
|
||||
@@ -21,22 +21,31 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomDetailsPresenter @Inject constructor(
|
||||
private val room: MatrixRoom,
|
||||
private val roomMembershipObserver: RoomMembershipObserver,
|
||||
) : Presenter<RoomDetailsState> {
|
||||
|
||||
@Composable
|
||||
override fun present(): RoomDetailsState {
|
||||
// fun handleEvents(event: RoomDetailsEvent) {}
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var leaveRoomWarning by remember {
|
||||
mutableStateOf<LeaveRoomWarning?>(null)
|
||||
}
|
||||
var error by remember {
|
||||
mutableStateOf<RoomDetailsError?>(null)
|
||||
}
|
||||
var memberCount: Async<Int> by remember { mutableStateOf(Async.Loading()) }
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
@@ -47,6 +56,28 @@ class RoomDetailsPresenter @Inject constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
fun handleEvents(event: RoomDetailsEvent) {
|
||||
when (event) {
|
||||
is RoomDetailsEvent.LeaveRoom -> {
|
||||
if (event.needsConfirmation) {
|
||||
leaveRoomWarning = LeaveRoomWarning.computeLeaveRoomWarning(room.isPublic, memberCount)
|
||||
} else {
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
room.leave()
|
||||
.onSuccess {
|
||||
roomMembershipObserver.notifyUserLeftRoom(room.roomId)
|
||||
}.onFailure {
|
||||
error = RoomDetailsError.AlertGeneric
|
||||
}
|
||||
leaveRoomWarning = null
|
||||
}
|
||||
}
|
||||
}
|
||||
is RoomDetailsEvent.ClearLeaveRoomWarning -> leaveRoomWarning = null
|
||||
RoomDetailsEvent.ClearError -> error = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return RoomDetailsState(
|
||||
roomId = room.roomId.value,
|
||||
@@ -56,7 +87,9 @@ class RoomDetailsPresenter @Inject constructor(
|
||||
roomTopic = room.topic,
|
||||
memberCount = memberCount,
|
||||
isEncrypted = room.isEncrypted,
|
||||
// eventSink = ::handleEvents
|
||||
displayLeaveRoomWarning = leaveRoomWarning,
|
||||
error = error,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
package io.element.android.features.roomdetails.impl
|
||||
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.isLoading
|
||||
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
|
||||
data class RoomDetailsState(
|
||||
val roomId: String,
|
||||
@@ -26,5 +29,27 @@ data class RoomDetailsState(
|
||||
val roomTopic: String?,
|
||||
val memberCount: Async<Int>,
|
||||
val isEncrypted: Boolean,
|
||||
// val eventSink: (RoomDetailsEvent) -> Unit
|
||||
val displayLeaveRoomWarning: LeaveRoomWarning?,
|
||||
val error: RoomDetailsError?,
|
||||
val eventSink: (RoomDetailsEvent) -> Unit
|
||||
)
|
||||
|
||||
sealed class LeaveRoomWarning {
|
||||
object Generic : LeaveRoomWarning()
|
||||
object PrivateRoom : LeaveRoomWarning()
|
||||
object LastUserInRoom : LeaveRoomWarning()
|
||||
|
||||
companion object {
|
||||
fun computeLeaveRoomWarning(isPublic: Boolean, memberCount: Async<Int>): LeaveRoomWarning {
|
||||
return when {
|
||||
!isPublic -> PrivateRoom
|
||||
(memberCount as? Async.Success<Int>)?.state == 1 -> LastUserInRoom
|
||||
else -> Generic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface RoomDetailsError {
|
||||
object AlertGeneric : RoomDetailsError
|
||||
}
|
||||
|
||||
@@ -43,5 +43,7 @@ fun aRoomDetailsState() = RoomDetailsState(
|
||||
"|| MAI iki/Marketing...",
|
||||
memberCount = Async.Success(32),
|
||||
isEncrypted = true,
|
||||
// eventSink = {}
|
||||
displayLeaveRoomWarning = null,
|
||||
error = null,
|
||||
eventSink = {}
|
||||
)
|
||||
|
||||
@@ -49,6 +49,8 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
@@ -57,6 +59,7 @@ import io.element.android.libraries.designsystem.theme.LocalColors
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -101,7 +104,24 @@ fun RoomDetailsView(
|
||||
SecuritySection()
|
||||
}
|
||||
|
||||
OtherActionsSection()
|
||||
OtherActionsSection(onLeaveRoom = {
|
||||
state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
|
||||
})
|
||||
|
||||
if (state.displayLeaveRoomWarning != null) {
|
||||
ConfirmLeaveRoomDialog(
|
||||
leaveRoomWarning = state.displayLeaveRoomWarning,
|
||||
onConfirmLeave = { state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = false)) },
|
||||
onDismiss = { state.eventSink(RoomDetailsEvent.ClearLeaveRoomWarning) }
|
||||
)
|
||||
}
|
||||
|
||||
if (state.error != null) {
|
||||
ErrorDialog(
|
||||
content = stringResource(StringR.string.error_unknown),
|
||||
onDismiss = { state.eventSink(RoomDetailsEvent.ClearError) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,16 +209,38 @@ internal fun SecuritySection(modifier: Modifier = Modifier) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun OtherActionsSection(modifier: Modifier = Modifier) {
|
||||
internal fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(showDivider = false, modifier = modifier) {
|
||||
PreferenceText(
|
||||
title = stringResource(R.string.screen_room_details_leave_room_title),
|
||||
icon = ImageVector.vectorResource(R.drawable.ic_door_open),
|
||||
tintColor = LocalColors.current.textActionCritical,
|
||||
onClick = onLeaveRoom,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun ConfirmLeaveRoomDialog(
|
||||
leaveRoomWarning: LeaveRoomWarning,
|
||||
onConfirmLeave: () -> Unit,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val content = stringResource(
|
||||
when (leaveRoomWarning) {
|
||||
LeaveRoomWarning.PrivateRoom -> StringR.string.leave_room_alert_private_subtitle
|
||||
LeaveRoomWarning.LastUserInRoom -> StringR.string.leave_room_alert_empty_subtitle
|
||||
LeaveRoomWarning.Generic -> StringR.string.leave_room_alert_subtitle
|
||||
}
|
||||
)
|
||||
ConfirmationDialog(
|
||||
content = content,
|
||||
submitText = stringResource(StringR.string.action_leave),
|
||||
onSubmitClicked = onConfirmLeave,
|
||||
onDismiss = onDismiss,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun RoomDetailsLightPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<plurals name="screen_room_member_list_header_title">
|
||||
<item quantity="one">"Una persona"</item>
|
||||
<item quantity="other">"%1$d personas"</item>
|
||||
</plurals>
|
||||
<string name="screen_dm_details_block_alert_action">"Bloquear"</string>
|
||||
<string name="screen_dm_details_block_alert_description">"Los usuarios bloqueados no podrán enviarte mensajes y se ocultarán todos sus mensajes. Puedes revertir esta acción en cualquier momento."</string>
|
||||
<string name="screen_dm_details_block_user">"Bloquear usuario"</string>
|
||||
<string name="screen_dm_details_unblock_alert_action">"Desbloquear"</string>
|
||||
<string name="screen_dm_details_unblock_alert_description">"Al desbloquear al usuario, podrás volver a ver todos sus mensajes."</string>
|
||||
<string name="screen_dm_details_unblock_user">"Desbloquear usuario"</string>
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"Los mensajes están protegidos con \"candados\". Sólo tú y los destinatarios tenéis las llaves únicas para abrirlos."</string>
|
||||
<string name="screen_room_details_encryption_enabled_title">"Cifrado de mensajes activado"</string>
|
||||
<string name="screen_room_details_invite_people_title">"Invitar a otras personas"</string>
|
||||
<string name="screen_room_details_leave_room_title">"Salir de la sala"</string>
|
||||
<string name="screen_room_details_people_title">"Personas"</string>
|
||||
<string name="screen_room_details_security_title">"Seguridad"</string>
|
||||
<string name="screen_room_details_share_room_title">"Compartir sala"</string>
|
||||
<string name="screen_room_details_topic_title">"Tema"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<plurals name="screen_room_member_list_header_title">
|
||||
<item quantity="one">"1 persona"</item>
|
||||
<item quantity="other">"%1$d persone"</item>
|
||||
</plurals>
|
||||
<string name="screen_dm_details_block_alert_action">"Blocca"</string>
|
||||
<string name="screen_dm_details_block_alert_description">"Gli utenti bloccati non saranno in grado di inviarti messaggi e tutti i loro messaggi saranno nascosti. Potrai annullare questa azione in qualsiasi momento."</string>
|
||||
<string name="screen_dm_details_block_user">"Blocca utente"</string>
|
||||
<string name="screen_dm_details_unblock_alert_action">"Sblocca"</string>
|
||||
<string name="screen_dm_details_unblock_alert_description">"Dopo aver sbloccato l\'utente, potrai vedere nuovamente tutti i suoi messaggi."</string>
|
||||
<string name="screen_dm_details_unblock_user">"Sblocca utente"</string>
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"I messaggi sono protetti da lucchetti. Solo tu e i destinatari avete le chiavi univoche per sbloccarli."</string>
|
||||
<string name="screen_room_details_encryption_enabled_title">"Crittografia messaggi abilitata"</string>
|
||||
<string name="screen_room_details_invite_people_title">"Invita persone"</string>
|
||||
<string name="screen_room_details_leave_room_title">"Esci dalla stanza"</string>
|
||||
<string name="screen_room_details_people_title">"Persone"</string>
|
||||
<string name="screen_room_details_security_title">"Sicurezza"</string>
|
||||
<string name="screen_room_details_share_room_title">"Condividi stanza"</string>
|
||||
<string name="screen_room_details_topic_title">"Oggetto"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<plurals name="screen_room_member_list_header_title">
|
||||
<item quantity="one">"o persoană"</item>
|
||||
<item quantity="few"></item>
|
||||
<item quantity="other">"%1$d persoane"</item>
|
||||
</plurals>
|
||||
<string name="screen_dm_details_block_alert_action">"Blocați"</string>
|
||||
<string name="screen_dm_details_block_alert_description">"Utilizatorii blocați nu vă vor putea trimite mesaje și toate mesajele lor vor fi ascunse. Puteți anula această acțiune oricând."</string>
|
||||
<string name="screen_dm_details_block_user">"Blocați utilizatorul"</string>
|
||||
<string name="screen_dm_details_unblock_alert_action">"Deblocați"</string>
|
||||
<string name="screen_dm_details_unblock_alert_description">"La deblocarea utilizatorului, veți putea vedea din nou toate mesajele de la acesta."</string>
|
||||
<string name="screen_dm_details_unblock_user">"Deblocați utilizatorul"</string>
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"Mesajele sunt securizate cu încuietori. Doar dumneavoastră și destinatarii aveți cheile unice pentru a le debloca."</string>
|
||||
<string name="screen_room_details_encryption_enabled_title">"Criptarea mesajelor este activată"</string>
|
||||
<string name="screen_room_details_invite_people_title">"Invitați persoane"</string>
|
||||
<string name="screen_room_details_leave_room_title">"Părăsiți camera"</string>
|
||||
<string name="screen_room_details_people_title">"Persoane"</string>
|
||||
<string name="screen_room_details_security_title">"Securitate"</string>
|
||||
<string name="screen_room_details_share_room_title">"Partajați camera"</string>
|
||||
<string name="screen_room_details_topic_title">"Subiect"</string>
|
||||
</resources>
|
||||
@@ -4,6 +4,12 @@
|
||||
<item quantity="one">"1 person"</item>
|
||||
<item quantity="other">"%1$d people"</item>
|
||||
</plurals>
|
||||
<string name="screen_dm_details_block_alert_action">"Block"</string>
|
||||
<string name="screen_dm_details_block_alert_description">"Blocked users will not be able to send you messages and all message by them will be hidden. You can reverse this action anytime."</string>
|
||||
<string name="screen_dm_details_block_user">"Block user"</string>
|
||||
<string name="screen_dm_details_unblock_alert_action">"Unblock"</string>
|
||||
<string name="screen_dm_details_unblock_alert_description">"On unblocking the user, you will be able to see all messages by them again."</string>
|
||||
<string name="screen_dm_details_unblock_user">"Unblock user"</string>
|
||||
<string name="screen_room_details_encryption_enabled_subtitle">"Messages are secured with locks. Only you and the recipients have the unique keys to unlock them."</string>
|
||||
<string name="screen_room_details_encryption_enabled_title">"Message encryption enabled"</string>
|
||||
<string name="screen_room_details_invite_people_title">"Invite people"</string>
|
||||
|
||||
@@ -20,21 +20,37 @@ import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import io.element.android.features.roomdetails.impl.LeaveRoomWarning
|
||||
import io.element.android.features.roomdetails.impl.RoomDetailsEvent
|
||||
import io.element.android.features.roomdetails.impl.RoomDetailsPresenter
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_NAME
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class RoomDetailsPresenterTests {
|
||||
|
||||
private val roomMembershipObserver = RoomMembershipObserver(A_SESSION_ID)
|
||||
|
||||
@Test
|
||||
fun `present - initial state is created from room info`() = runTest {
|
||||
val room = aMatrixRoom()
|
||||
val presenter = RoomDetailsPresenter(room)
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
@@ -53,7 +69,7 @@ class RoomDetailsPresenterTests {
|
||||
@Test
|
||||
fun `present - room member count is calculated asynchronously`() = runTest {
|
||||
val room = aMatrixRoom()
|
||||
val presenter = RoomDetailsPresenter(room)
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
@@ -68,7 +84,7 @@ class RoomDetailsPresenterTests {
|
||||
@Test
|
||||
fun `present - initial state with no room name`() = runTest {
|
||||
val room = aMatrixRoom(name = null)
|
||||
val presenter = RoomDetailsPresenter(room)
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
@@ -84,7 +100,7 @@ class RoomDetailsPresenterTests {
|
||||
val room = aMatrixRoom(name = null).apply {
|
||||
givenFetchMemberResult(Result.failure(Throwable()))
|
||||
}
|
||||
val presenter = RoomDetailsPresenter(room)
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
@@ -94,6 +110,100 @@ class RoomDetailsPresenterTests {
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - Leave with confirmation on private room shows a specific warning`() = runTest {
|
||||
val room = aMatrixRoom(isPublic = false)
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
// Allow room member count to load
|
||||
skipItems(1)
|
||||
|
||||
initialState.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
|
||||
val confirmationState = awaitItem()
|
||||
Truth.assertThat(confirmationState.displayLeaveRoomWarning).isEqualTo(LeaveRoomWarning.PrivateRoom)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - Leave with confirmation on empty room shows a specific warning`() = runTest {
|
||||
val room = aMatrixRoom(members = listOf(aRoomMember()))
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
// Allow room member count to load
|
||||
skipItems(1)
|
||||
|
||||
initialState.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
|
||||
val confirmationState = awaitItem()
|
||||
Truth.assertThat(confirmationState.displayLeaveRoomWarning).isEqualTo(LeaveRoomWarning.LastUserInRoom)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - Leave with confirmation shows a generic warning`() = runTest {
|
||||
val room = aMatrixRoom()
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
// Allow room member count to load
|
||||
skipItems(1)
|
||||
|
||||
initialState.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true))
|
||||
val confirmationState = awaitItem()
|
||||
Truth.assertThat(confirmationState.displayLeaveRoomWarning).isEqualTo(LeaveRoomWarning.Generic)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - Leave without confirmation leaves the room`() = runTest {
|
||||
val room = aMatrixRoom()
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
// Allow room member count to load
|
||||
skipItems(1)
|
||||
|
||||
initialState.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = false))
|
||||
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
|
||||
// Membership observer should receive a 'left room' change
|
||||
roomMembershipObserver.updates.take(1)
|
||||
.onEach { update -> Truth.assertThat(update.change).isEqualTo(MembershipChange.LEFT) }
|
||||
.collect()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - ClearError removes any error present`() = runTest {
|
||||
val room = aMatrixRoom().apply {
|
||||
givenLeaveRoomError(Throwable())
|
||||
}
|
||||
val presenter = RoomDetailsPresenter(room, roomMembershipObserver)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
// Allow room member count to load
|
||||
skipItems(1)
|
||||
|
||||
initialState.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = false))
|
||||
val errorState = awaitItem()
|
||||
Truth.assertThat(errorState.error).isNotNull()
|
||||
errorState.eventSink(RoomDetailsEvent.ClearError)
|
||||
Truth.assertThat(awaitItem().error).isNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun aMatrixRoom(
|
||||
@@ -104,6 +214,7 @@ fun aMatrixRoom(
|
||||
avatarUrl: String? = "https://matrix.org/avatar.jpg",
|
||||
members: List<RoomMember> = emptyList(),
|
||||
isEncrypted: Boolean = true,
|
||||
isPublic: Boolean = true,
|
||||
) = FakeMatrixRoom(
|
||||
roomId = roomId,
|
||||
name = name,
|
||||
@@ -112,4 +223,23 @@ fun aMatrixRoom(
|
||||
avatarUrl = avatarUrl,
|
||||
members = members,
|
||||
isEncrypted = isEncrypted,
|
||||
isPublic = isPublic,
|
||||
)
|
||||
|
||||
fun aRoomMember(
|
||||
userId: UserId = A_USER_ID,
|
||||
displayName: String? = null,
|
||||
avatarUrl: String? = null,
|
||||
membership: RoomMembershipState = RoomMembershipState.JOIN,
|
||||
isNameAmbiguous: Boolean = false,
|
||||
powerLevel: Long = 0L,
|
||||
normalizedPowerLevel: Long = 0L
|
||||
) = RoomMember(
|
||||
userId = userId.value,
|
||||
displayName = displayName,
|
||||
avatarUrl = avatarUrl,
|
||||
membership = membership,
|
||||
isNameAmbiguous = isNameAmbiguous,
|
||||
powerLevel = powerLevel,
|
||||
normalizedPowerLevel = normalizedPowerLevel,
|
||||
)
|
||||
|
||||
@@ -20,5 +20,4 @@ sealed interface RoomListEvents {
|
||||
data class UpdateFilter(val newFilter: String) : RoomListEvents
|
||||
data class UpdateVisibleRange(val range: IntRange) : RoomListEvents
|
||||
object DismissRequestVerificationPrompt : RoomListEvents
|
||||
object ClearSuccessfulVerificationMessage : RoomListEvents
|
||||
}
|
||||
|
||||
@@ -34,12 +34,14 @@ import io.element.android.libraries.core.extensions.orEmpty
|
||||
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.handleSnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.room.RoomSummary
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -56,8 +58,11 @@ class RoomListPresenter @Inject constructor(
|
||||
private val lastMessageTimestampFormatter: LastMessageTimestampFormatter,
|
||||
private val roomLastMessageFormatter: RoomLastMessageFormatter,
|
||||
private val sessionVerificationService: SessionVerificationService,
|
||||
private val snackbarDispatcher: SnackbarDispatcher,
|
||||
) : Presenter<RoomListState> {
|
||||
|
||||
private val roomMembershipObserver: RoomMembershipObserver = client.roomMembershipObserver()
|
||||
|
||||
@Composable
|
||||
override fun present(): RoomListState {
|
||||
val matrixUser: MutableState<MatrixUser?> = remember {
|
||||
@@ -86,19 +91,11 @@ class RoomListPresenter @Inject constructor(
|
||||
derivedStateOf { sessionVerifiedStatus == SessionVerifiedStatus.NotVerified && !verificationPromptDismissed }
|
||||
}
|
||||
|
||||
// Current verification flow status, if any (initial, requesting, accepted, etc.)
|
||||
val currentVerificationFlowStatus by sessionVerificationService.verificationFlowState.collectAsState()
|
||||
// We only care about the 'Finished' state to display the 'verification success' message
|
||||
val presentVerificationSuccessfulMessage = remember {
|
||||
derivedStateOf { currentVerificationFlowStatus == VerificationFlowState.Finished }
|
||||
}
|
||||
|
||||
fun handleEvents(event: RoomListEvents) {
|
||||
when (event) {
|
||||
is RoomListEvents.UpdateFilter -> filter = event.newFilter
|
||||
is RoomListEvents.UpdateVisibleRange -> updateVisibleRange(event.range)
|
||||
RoomListEvents.DismissRequestVerificationPrompt -> verificationPromptDismissed = true
|
||||
RoomListEvents.ClearSuccessfulVerificationMessage -> sessionVerificationService.reset()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,12 +103,14 @@ class RoomListPresenter @Inject constructor(
|
||||
filteredRoomSummaries.value = updateFilteredRoomSummaries(roomSummaries, filter)
|
||||
}
|
||||
|
||||
val snackbarMessage = handleSnackbarMessage(snackbarDispatcher)
|
||||
|
||||
return RoomListState(
|
||||
matrixUser = matrixUser.value,
|
||||
roomList = filteredRoomSummaries.value,
|
||||
filter = filter,
|
||||
presentVerificationSuccessfulMessage = presentVerificationSuccessfulMessage.value,
|
||||
displayVerificationPrompt = displayVerificationPrompt,
|
||||
snackbarMessage = snackbarMessage,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.element.android.features.roomlist.impl
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@@ -26,7 +27,7 @@ data class RoomListState(
|
||||
val matrixUser: MatrixUser?,
|
||||
val roomList: ImmutableList<RoomListRoomSummary>,
|
||||
val filter: String,
|
||||
val presentVerificationSuccessfulMessage: Boolean,
|
||||
val displayVerificationPrompt: Boolean,
|
||||
val snackbarMessage: SnackbarMessage?,
|
||||
val eventSink: (RoomListEvents) -> Unit
|
||||
)
|
||||
|
||||
@@ -20,17 +20,19 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
|
||||
override val values: Sequence<RoomListState>
|
||||
get() = sequenceOf(
|
||||
aRoomListState(),
|
||||
aRoomListState().copy(displayVerificationPrompt = true),
|
||||
aRoomListState().copy(presentVerificationSuccessfulMessage = true),
|
||||
aRoomListState().copy(snackbarMessage = SnackbarMessage(StringR.string.common_verification_complete)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -39,7 +41,7 @@ internal fun aRoomListState() = RoomListState(
|
||||
roomList = aRoomListRoomSummaryList(),
|
||||
filter = "filter",
|
||||
eventSink = {},
|
||||
presentVerificationSuccessfulMessage = false,
|
||||
snackbarMessage = null,
|
||||
displayVerificationPrompt = false,
|
||||
)
|
||||
|
||||
|
||||
@@ -40,10 +40,11 @@ import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
@@ -67,6 +68,7 @@ import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import kotlinx.coroutines.launch
|
||||
import io.element.android.libraries.designsystem.R as DrawableR
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@@ -130,14 +132,18 @@ fun RoomListContent(
|
||||
}
|
||||
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val verificationCompleteMessage = stringResource(StringR.string.common_verification_complete)
|
||||
LaunchedEffect(state.presentVerificationSuccessfulMessage) {
|
||||
if (state.presentVerificationSuccessfulMessage) {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = verificationCompleteMessage,
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
state.eventSink(RoomListEvents.ClearSuccessfulVerificationMessage)
|
||||
val snackbarMessageText = if (state.snackbarMessage != null ) {
|
||||
stringResource(state.snackbarMessage.messageResId)
|
||||
} else null
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
if (snackbarMessageText != null) {
|
||||
SideEffect {
|
||||
coroutineScope.launch {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = snackbarMessageText,
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_roomlist_a11y_create_message">"Crear una nueva conversación o sala"</string>
|
||||
<string name="screen_roomlist_main_space_title">"Todos los chats"</string>
|
||||
<string name="session_verification_banner_message">"Parece que estás usando un nuevo dispositivo. Verifica que eres tú para acceder a tus mensajes cifrados."</string>
|
||||
<string name="session_verification_banner_title">"Accede a tu historial de mensajes"</string>
|
||||
<string name="state_event_avatar_changed_too">"(el avatar también cambió)"</string>
|
||||
<string name="state_event_avatar_url_changed">"%1$s cambió su avatar"</string>
|
||||
<string name="state_event_avatar_url_changed_by_you">"Cambiaste tu avatar"</string>
|
||||
<string name="state_event_display_name_changed_from">"%1$s cambió su nombre de %2$s a %3$s"</string>
|
||||
<string name="state_event_display_name_changed_from_by_you">"Cambiaste tu nombre de %1$s a %2$s"</string>
|
||||
<string name="state_event_display_name_removed">"%1$s eliminó su nombre (era %2$s)"</string>
|
||||
<string name="state_event_display_name_removed_by_you">"Eliminaste tu nombre (era %1$s)"</string>
|
||||
<string name="state_event_display_name_set">"%1$s cambió su nombre a %2$s"</string>
|
||||
<string name="state_event_display_name_set_by_you">"Cambiaste tu nombre a %1$s"</string>
|
||||
<string name="state_event_room_avatar_changed">"%1$s cambió el avatar de la sala"</string>
|
||||
<string name="state_event_room_avatar_changed_by_you">"Cambiaste el avatar de la sala"</string>
|
||||
<string name="state_event_room_avatar_removed">"%1$s eliminó el avatar de la sala"</string>
|
||||
<string name="state_event_room_avatar_removed_by_you">"Eliminaste el avatar de la sala"</string>
|
||||
<string name="state_event_room_ban">"%1$s expulsó permanentemente a %2$s"</string>
|
||||
<string name="state_event_room_ban_by_you">"Expulsaste permanentemente a %1$s"</string>
|
||||
<string name="state_event_room_created">"%1$s creó la sala"</string>
|
||||
<string name="state_event_room_created_by_you">"Tú creaste la sala"</string>
|
||||
<string name="state_event_room_invite">"%1$s invitó a %2$s"</string>
|
||||
<string name="state_event_room_invite_accepted">"%1$s aceptó la invitación"</string>
|
||||
<string name="state_event_room_invite_accepted_by_you">"Aceptaste la invitación"</string>
|
||||
<string name="state_event_room_invite_by_you">"Invitaste a %1$s"</string>
|
||||
<string name="state_event_room_invite_you">"%1$s te invitó."</string>
|
||||
<string name="state_event_room_join">"%1$s se unió a la sala"</string>
|
||||
<string name="state_event_room_join_by_you">"Te uniste a la sala"</string>
|
||||
<string name="state_event_room_knock">"%1$s solicitó unirse"</string>
|
||||
<string name="state_event_room_knock_accepted">"%1$s permitió que %2$s se uniera"</string>
|
||||
<string name="state_event_room_knock_accepted_by_you">"%1$s te permitió unirte"</string>
|
||||
<string name="state_event_room_knock_by_you">"Solicitaste unirte"</string>
|
||||
<string name="state_event_room_knock_denied">"%1$s rechazó la solicitud de %2$s para unirse"</string>
|
||||
<string name="state_event_room_knock_denied_by_you">"Rechazaste la solicitud de %1$s para unirte"</string>
|
||||
<string name="state_event_room_knock_denied_you">"%1$s rechazó su solicitud para unirte"</string>
|
||||
<string name="state_event_room_knock_retracted">"%1$s ya no está interesado en unirse"</string>
|
||||
<string name="state_event_room_knock_retracted_by_you">"Cancelaste tu solicitud de unirte"</string>
|
||||
<string name="state_event_room_leave">"%1$s salió de la sala"</string>
|
||||
<string name="state_event_room_leave_by_you">"Saliste de la sala"</string>
|
||||
<string name="state_event_room_name_changed">"%1$s cambió el nombre de la sala a: %2$s"</string>
|
||||
<string name="state_event_room_name_changed_by_you">"Cambiaste el nombre de la sala a: %1$s"</string>
|
||||
<string name="state_event_room_name_removed">"%1$s eliminó el nombre de la sala"</string>
|
||||
<string name="state_event_room_name_removed_by_you">"Eliminaste el nombre de la sala"</string>
|
||||
<string name="state_event_room_reject">"%1$s rechazó la invitación"</string>
|
||||
<string name="state_event_room_reject_by_you">"Rechazaste la invitación"</string>
|
||||
<string name="state_event_room_remove">"%1$s echó a %2$s"</string>
|
||||
<string name="state_event_room_remove_by_you">"Echaste a %1$s"</string>
|
||||
<string name="state_event_room_third_party_invite">"%1$s envió una invitación a %2$s para unirse a la sala"</string>
|
||||
<string name="state_event_room_third_party_invite_by_you">"Enviaste una invitación a %1$s para unirse a la sala"</string>
|
||||
<string name="state_event_room_third_party_revoked_invite">"%1$s revocó la invitación a %2$s para unirse a la sala"</string>
|
||||
<string name="state_event_room_third_party_revoked_invite_by_you">"Revocaste la invitación de %1$s para unirse a la sala"</string>
|
||||
<string name="state_event_room_topic_changed">"%1$s cambió el tema a: %2$s"</string>
|
||||
<string name="state_event_room_topic_changed_by_you">"Cambiaste el tema a: %1$s"</string>
|
||||
<string name="state_event_room_topic_removed">"%1$s eliminó el tema de la sala"</string>
|
||||
<string name="state_event_room_topic_removed_by_you">"Eliminaste el tema de la sala"</string>
|
||||
<string name="state_event_room_unban">"%1$s readmitió a %2$s"</string>
|
||||
<string name="state_event_room_unban_by_you">"Readmitiste a %1$s"</string>
|
||||
<string name="state_event_room_unknown_membership_change">"%1$s realizó un cambio desconocido en su membresía"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_roomlist_a11y_create_message">"Crea una nuova conversazione o stanza"</string>
|
||||
<string name="screen_roomlist_main_space_title">"Tutte le conversazioni"</string>
|
||||
<string name="session_verification_banner_message">"Sembra che tu stia utilizzando un nuovo dispositivo. Verifica di essere tu per accedere ai tuoi messaggi crittografati."</string>
|
||||
<string name="session_verification_banner_title">"Accedi alla cronologia dei messaggi"</string>
|
||||
<string name="state_event_avatar_changed_too">"(anche l\'avatar è stato cambiato)"</string>
|
||||
<string name="state_event_avatar_url_changed">"%1$s ha cambiato il proprio avatar"</string>
|
||||
<string name="state_event_avatar_url_changed_by_you">"Hai cambiato il tuo avatar"</string>
|
||||
<string name="state_event_display_name_changed_from">"%1$s ha cambiato il proprio nome visualizzato da %2$s a %3$s"</string>
|
||||
<string name="state_event_display_name_changed_from_by_you">"Hai cambiato il tuo nome visualizzato da %1$s a %2$s"</string>
|
||||
<string name="state_event_display_name_removed">"%1$s ha rimosso il proprio nome visualizzato (era %2$s)"</string>
|
||||
<string name="state_event_display_name_removed_by_you">"Hai rimosso il tuo nome visualizzato (era %1$s)"</string>
|
||||
<string name="state_event_display_name_set">"%1$s ha impostato il proprio nome visualizzato su %2$s"</string>
|
||||
<string name="state_event_display_name_set_by_you">"Hai impostato il tuo nome visualizzato su %1$s"</string>
|
||||
<string name="state_event_room_avatar_changed">"%1$s ha cambiato l\'avatar della stanza"</string>
|
||||
<string name="state_event_room_avatar_changed_by_you">"Hai cambiato l\'avatar della stanza"</string>
|
||||
<string name="state_event_room_avatar_removed">"%1$s ha rimosso l\'avatar della stanza"</string>
|
||||
<string name="state_event_room_avatar_removed_by_you">"Hai rimosso l\'avatar della stanza"</string>
|
||||
<string name="state_event_room_ban">"%1$s ha rimosso %2$s"</string>
|
||||
<string name="state_event_room_ban_by_you">"Hai rimosso %1$s"</string>
|
||||
<string name="state_event_room_created">"%1$s ha creato la stanza"</string>
|
||||
<string name="state_event_room_created_by_you">"Hai creato la stanza"</string>
|
||||
<string name="state_event_room_invite">"%1$s ha invitato %2$s"</string>
|
||||
<string name="state_event_room_invite_accepted">"%1$s ha accettato l\'invito"</string>
|
||||
<string name="state_event_room_invite_accepted_by_you">"Hai accettato l\'invito"</string>
|
||||
<string name="state_event_room_invite_by_you">"Hai invitato %1$s"</string>
|
||||
<string name="state_event_room_invite_you">"%1$s ti ha invitato"</string>
|
||||
<string name="state_event_room_join">"%1$s si è unito alla stanza"</string>
|
||||
<string name="state_event_room_join_by_you">"Ti sei unito alla stanza"</string>
|
||||
<string name="state_event_room_knock">"%1$s ha chiesto di unirsi"</string>
|
||||
<string name="state_event_room_knock_accepted">"%1$s ha permesso a %2$s di unirsi"</string>
|
||||
<string name="state_event_room_knock_accepted_by_you">"%1$s ti ha permesso di unirti"</string>
|
||||
<string name="state_event_room_knock_by_you">"Hai richiesto di unirti"</string>
|
||||
<string name="state_event_room_knock_denied">"%1$s ha rifiutato la richiesta di unirsi di %2$s"</string>
|
||||
<string name="state_event_room_knock_denied_by_you">"Hai rifiutato la richiesta di unirsi di %1$s"</string>
|
||||
<string name="state_event_room_knock_denied_you">"%1$s ha rifiutato la tua richiesta di unirti"</string>
|
||||
<string name="state_event_room_knock_retracted">"%1$s non è più interessato a partecipare"</string>
|
||||
<string name="state_event_room_knock_retracted_by_you">"Hai annullato la tua richiesta di unirti"</string>
|
||||
<string name="state_event_room_leave">"%1$s ha lasciato la stanza"</string>
|
||||
<string name="state_event_room_leave_by_you">"Hai lasciato la stanza"</string>
|
||||
<string name="state_event_room_name_changed">"%1$s ha cambiato il nome della stanza in: %2$s"</string>
|
||||
<string name="state_event_room_name_changed_by_you">"Hai cambiato il nome della stanza in: %1$s"</string>
|
||||
<string name="state_event_room_name_removed">"%1$s ha rimosso il nome della stanza"</string>
|
||||
<string name="state_event_room_name_removed_by_you">"Hai rimosso il nome della stanza"</string>
|
||||
<string name="state_event_room_reject">"%1$s ha rifiutato l\'invito"</string>
|
||||
<string name="state_event_room_reject_by_you">"Hai rifiutato l\'invito"</string>
|
||||
<string name="state_event_room_remove">"%1$s ha rimosso %2$s"</string>
|
||||
<string name="state_event_room_remove_by_you">"Hai rimosso %1$s"</string>
|
||||
<string name="state_event_room_third_party_invite">"%1$s ha inviato un invito a %2$s per unirsi alla stanza"</string>
|
||||
<string name="state_event_room_third_party_invite_by_you">"Hai inviato un invito a %1$s per unirsi alla stanza"</string>
|
||||
<string name="state_event_room_third_party_revoked_invite">"%1$s ha revocato l\'invito di %2$s ad unirsi alla stanza."</string>
|
||||
<string name="state_event_room_third_party_revoked_invite_by_you">"Hai revocato l\'invito a %1$s a universi alla stanza"</string>
|
||||
<string name="state_event_room_topic_changed">"%1$s ha cambiato l\'oggetto in: %2$s"</string>
|
||||
<string name="state_event_room_topic_changed_by_you">"Hai cambiato l\'oggetto in: %1$s"</string>
|
||||
<string name="state_event_room_topic_removed">"%1$s ha rimosso l\'oggetto della stanza"</string>
|
||||
<string name="state_event_room_topic_removed_by_you">"Hai rimosso l\'oggetto della stanza"</string>
|
||||
<string name="state_event_room_unban">"%1$s ha sbloccato %2$s"</string>
|
||||
<string name="state_event_room_unban_by_you">"Hai sbloccato %1$s"</string>
|
||||
<string name="state_event_room_unknown_membership_change">"%1$s ha apportato una modifica sconosciuta alla propria iscrizione"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_roomlist_a11y_create_message">"Creați o conversație sau o cameră nouă"</string>
|
||||
<string name="screen_roomlist_main_space_title">"Toate conversatiile"</string>
|
||||
<string name="session_verification_banner_message">"Se pare că folosiți un dispozitiv nou. Verificați-vă identitatea pentru acces la mesajele dumneavoastră criptate."</string>
|
||||
<string name="session_verification_banner_title">"Accesați istoricul mesajelor"</string>
|
||||
<string name="state_event_avatar_changed_too">"(s-a schimbat si avatarul)"</string>
|
||||
<string name="state_event_avatar_url_changed">"%1$s și-a schimbat avatarul"</string>
|
||||
<string name="state_event_avatar_url_changed_by_you">"V-ați schimbat avatarul"</string>
|
||||
<string name="state_event_display_name_changed_from">"%1$s și-a schimbat numele din %2$s în %3$s"</string>
|
||||
<string name="state_event_display_name_changed_from_by_you">"V-ați schimbat numele din %1$s în %2$s"</string>
|
||||
<string name="state_event_display_name_removed">"%1$s și-a sters numele (era %2$s)"</string>
|
||||
<string name="state_event_display_name_removed_by_you">"V-ați sters numele (era %1$s)"</string>
|
||||
<string name="state_event_display_name_set">"%1$s și-a schimbat numele %2$s"</string>
|
||||
<string name="state_event_display_name_set_by_you">"V-ați schimbat numele în %1$s"</string>
|
||||
<string name="state_event_room_avatar_changed">"%1$s a schimbat avatarul camerei"</string>
|
||||
<string name="state_event_room_avatar_changed_by_you">"Ați schimbat avatarul camerei"</string>
|
||||
<string name="state_event_room_avatar_removed">"%1$s a șters avatarul camerei"</string>
|
||||
<string name="state_event_room_avatar_removed_by_you">"Ați șters avatarul camerei"</string>
|
||||
<string name="state_event_room_ban">"%1$s a adăugat o interdicție pentru %2$s"</string>
|
||||
<string name="state_event_room_ban_by_you">"Ați adăugat o interdicție pentru %1$s"</string>
|
||||
<string name="state_event_room_created">"%1$s a creat camera"</string>
|
||||
<string name="state_event_room_created_by_you">"Ați creat camera"</string>
|
||||
<string name="state_event_room_invite">"%1$s l-a invitat pe %2$s"</string>
|
||||
<string name="state_event_room_invite_accepted">"%1$s a acceptat invitația"</string>
|
||||
<string name="state_event_room_invite_accepted_by_you">"Ați acceptat invitația"</string>
|
||||
<string name="state_event_room_invite_by_you">"L-ați invitat pe %1$s"</string>
|
||||
<string name="state_event_room_invite_you">"%1$s v-a invitat"</string>
|
||||
<string name="state_event_room_join">"%1$s a intrat în cameră"</string>
|
||||
<string name="state_event_room_join_by_you">"Ați intrat în cameră"</string>
|
||||
<string name="state_event_room_knock">"%1$s a solicitat să se alăture camerei"</string>
|
||||
<string name="state_event_room_knock_accepted">"%1$s i-a permis lui %2$s să se alăture camerei"</string>
|
||||
<string name="state_event_room_knock_accepted_by_you">"%1$s v-a permis să vă alăturați camerei"</string>
|
||||
<string name="state_event_room_knock_by_you">"Ați solicitat să vă alăturați camerei"</string>
|
||||
<string name="state_event_room_knock_denied">"%1$s a respins solicitarea de alăturare a lui %2$s"</string>
|
||||
<string name="state_event_room_knock_denied_by_you">"Ați respins solicitarea de alăturare a lui %1$s"</string>
|
||||
<string name="state_event_room_knock_denied_you">"%1$s a respins cererea dumneavoastră de alăturare"</string>
|
||||
<string name="state_event_room_knock_retracted">"%1$s nu mai este interesat să se alăture camerei"</string>
|
||||
<string name="state_event_room_knock_retracted_by_you">"Ați anulat cererea de alăturare"</string>
|
||||
<string name="state_event_room_leave">"%1$s a părăsit camera"</string>
|
||||
<string name="state_event_room_leave_by_you">"Ați părăsit camera"</string>
|
||||
<string name="state_event_room_name_changed">"%1$s a schimbat numele camerei în: %2$s"</string>
|
||||
<string name="state_event_room_name_changed_by_you">"Ați schimbat numele camerei în: %1$s"</string>
|
||||
<string name="state_event_room_name_removed">"%1$s a sters numele camerei"</string>
|
||||
<string name="state_event_room_name_removed_by_you">"Ați șters numele camerei"</string>
|
||||
<string name="state_event_room_reject">"%1$s a respins invitația"</string>
|
||||
<string name="state_event_room_reject_by_you">"Ați respins invitația"</string>
|
||||
<string name="state_event_room_remove">"%1$s l-a îndepărtat pe %2$s"</string>
|
||||
<string name="state_event_room_remove_by_you">"L-ați îndepărtat pe %1$s"</string>
|
||||
<string name="state_event_room_third_party_invite">"%1$s a trimis o invitație către %2$s pentru a se alătura camerei"</string>
|
||||
<string name="state_event_room_third_party_invite_by_you">"Ați trimis o invitație către %1$s pentru a se alătura camerei"</string>
|
||||
<string name="state_event_room_third_party_revoked_invite">"%1$s a revocat invitația pentru %2$s de a se alătura camerei"</string>
|
||||
<string name="state_event_room_third_party_revoked_invite_by_you">"Ați revocat invitația pentru %1$s de a se alătura camerei"</string>
|
||||
<string name="state_event_room_topic_changed">"%1$s a schimbat subiectul în: %2$s"</string>
|
||||
<string name="state_event_room_topic_changed_by_you">"Ați schimbat subiectul în: %1$s"</string>
|
||||
<string name="state_event_room_topic_removed">"%1$s a șters subiectul camerei"</string>
|
||||
<string name="state_event_room_topic_removed_by_you">"Ați șters subiectul camerei"</string>
|
||||
<string name="state_event_room_unban">"%1$s a anulat interdicția pentru %2$s"</string>
|
||||
<string name="state_event_room_unban_by_you">"Ați anulat interdicția pentru %1$s"</string>
|
||||
<string name="state_event_room_unknown_membership_change">"%1$s a făcut o modificare necunoscută asupra calității sale de membru"</string>
|
||||
</resources>
|
||||
@@ -24,8 +24,8 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
||||
import io.element.android.libraries.dateformatter.test.FakeLastMessageTimestampFormatter
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
@@ -49,6 +49,7 @@ class RoomListPresenterTests {
|
||||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -75,6 +76,7 @@ class RoomListPresenterTests {
|
||||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -95,6 +97,7 @@ class RoomListPresenterTests {
|
||||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -119,6 +122,7 @@ class RoomListPresenterTests {
|
||||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -148,6 +152,7 @@ class RoomListPresenterTests {
|
||||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -182,6 +187,7 @@ class RoomListPresenterTests {
|
||||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -230,6 +236,7 @@ class RoomListPresenterTests {
|
||||
givenIsReady(true)
|
||||
givenVerifiedStatus(SessionVerifiedStatus.NotVerified)
|
||||
},
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
@@ -242,32 +249,6 @@ class RoomListPresenterTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - presentVerificationSuccessfulMessage & ClearVerificationSuccesfulMessage`() = runTest {
|
||||
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||
val presenter = RoomListPresenter(
|
||||
FakeMatrixClient(
|
||||
sessionId = A_SESSION_ID,
|
||||
roomSummaryDataSource = roomSummaryDataSource
|
||||
),
|
||||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService().apply {
|
||||
givenIsReady(true)
|
||||
givenVerificationFlowState(VerificationFlowState.Finished)
|
||||
},
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
skipItems(1)
|
||||
val displayMessageItem = awaitItem()
|
||||
Truth.assertThat(displayMessageItem.presentVerificationSuccessfulMessage).isTrue()
|
||||
displayMessageItem.eventSink(RoomListEvents.ClearSuccessfulVerificationMessage)
|
||||
Truth.assertThat(awaitItem().presentVerificationSuccessfulMessage).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDateFormatter(): LastMessageTimestampFormatter {
|
||||
return FakeLastMessageTimestampFormatter().apply {
|
||||
givenFormat(A_FORMATTED_DATE)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_session_verification_cancelled_subtitle">"Algo no fue bien. Se agotó el tiempo de espera de la solicitud o se rechazó."</string>
|
||||
<string name="screen_session_verification_cancelled_title">"Verificación cancelada"</string>
|
||||
<string name="screen_session_verification_compare_emojis_subtitle">"Confirma que los emojis que aparecen a continuación coinciden con los que aparecen en tu otra sesión."</string>
|
||||
<string name="screen_session_verification_compare_emojis_title">"Comparar emojis"</string>
|
||||
<string name="screen_session_verification_complete_subtitle">"Tu nueva sesión ya está verificada. Tienes acceso a tus mensajes cifrados y otros usuarios lo considerarán de confianza."</string>
|
||||
<string name="screen_session_verification_open_existing_session_subtitle">"Demuestra que eres tú para acceder a tu historial de mensajes cifrados."</string>
|
||||
<string name="screen_session_verification_open_existing_session_title">"Abrir una sesión existente"</string>
|
||||
<string name="screen_session_verification_positive_button_canceled">"Reintentar la verificación"</string>
|
||||
<string name="screen_session_verification_positive_button_initial">"Estoy listo"</string>
|
||||
<string name="screen_session_verification_positive_button_ready">"Comenzar"</string>
|
||||
<string name="screen_session_verification_positive_button_verifying_ongoing">"Esperando a que coincida"</string>
|
||||
<string name="screen_session_verification_request_accepted_subtitle">"Compara los emoji, asegurándote de que aparecen en el mismo orden."</string>
|
||||
<string name="screen_session_verification_they_dont_match">"No coinciden"</string>
|
||||
<string name="screen_session_verification_they_match">"Coinciden"</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_subtitle">"Acepta la solicitud para iniciar el proceso de verificación en tu otra sesión para continuar."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_title">"A la espera de aceptar la solicitud"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_session_verification_cancelled_subtitle">"C\'è qualcosa che non va. La richiesta è scaduta o è stata rifiutata."</string>
|
||||
<string name="screen_session_verification_cancelled_title">"Verifica annullata"</string>
|
||||
<string name="screen_session_verification_compare_emojis_subtitle">"Verifica che gli emoji sottostanti corrispondano a quelli mostrati nell\'altra sessione."</string>
|
||||
<string name="screen_session_verification_compare_emojis_title">"Confronta le emoji"</string>
|
||||
<string name="screen_session_verification_complete_subtitle">"La tua nuova sessione è ora verificata. Ha accesso ai tuoi messaggi crittografati e gli altri utenti la vedranno come attendibile."</string>
|
||||
<string name="screen_session_verification_open_existing_session_subtitle">"Dimostra la tua identità per accedere alla cronologia dei messaggi crittografati."</string>
|
||||
<string name="screen_session_verification_open_existing_session_title">"Apri una sessione esistente"</string>
|
||||
<string name="screen_session_verification_positive_button_canceled">"Riprova la verifica"</string>
|
||||
<string name="screen_session_verification_positive_button_initial">"Sono pronto"</string>
|
||||
<string name="screen_session_verification_positive_button_ready">"Inizia"</string>
|
||||
<string name="screen_session_verification_positive_button_verifying_ongoing">"In attesa di un riscontro"</string>
|
||||
<string name="screen_session_verification_request_accepted_subtitle">"Confronta le emoji uniche, assicurandoti che appaiano nello stesso ordine."</string>
|
||||
<string name="screen_session_verification_they_dont_match">"Non corrispondono"</string>
|
||||
<string name="screen_session_verification_they_match">"Corrispondono"</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_subtitle">"Accetta la richiesta di avviare il processo di verifica nell\'altra sessione per continuare."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_title">"In attesa di accettare la richiesta"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_session_verification_cancelled_subtitle">"Ceva nu este în regulă. Fie cererea a expirat, fie a fost respinsă."</string>
|
||||
<string name="screen_session_verification_cancelled_title">"Verificare anulată"</string>
|
||||
<string name="screen_session_verification_compare_emojis_subtitle">"Confirmați că emoticoanele de mai jos se potrivesc cu cele afișate în cealaltă sesiune."</string>
|
||||
<string name="screen_session_verification_compare_emojis_title">"Comparați emoticoanele"</string>
|
||||
<string name="screen_session_verification_complete_subtitle">"Noua dumneavoastră sesiune este acum verificată. Are acces la mesajele dumneavoastră criptate, iar alți utilizatori vă vor vedea ca fiind de încredere."</string>
|
||||
<string name="screen_session_verification_open_existing_session_subtitle">"Demonstrați-vă identitatea pentru a accesa istoricul mesajelor criptate."</string>
|
||||
<string name="screen_session_verification_open_existing_session_title">"Deschideți o sesiune existentă"</string>
|
||||
<string name="screen_session_verification_positive_button_canceled">"Reîncercați verificarea"</string>
|
||||
<string name="screen_session_verification_positive_button_initial">"Sunt pregătit"</string>
|
||||
<string name="screen_session_verification_positive_button_ready">"Începeți"</string>
|
||||
<string name="screen_session_verification_positive_button_verifying_ongoing">"Se așteaptă confirmarea"</string>
|
||||
<string name="screen_session_verification_request_accepted_subtitle">"Comparăți emoticoalene asigurându-vă că apar în aceeași ordine."</string>
|
||||
<string name="screen_session_verification_they_dont_match">"Nu se potrivesc"</string>
|
||||
<string name="screen_session_verification_they_match">"Se potrivesc"</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_subtitle">"Acceptați solicitarea de a începe procesul de verificare în cealaltă sesiune pentru a continua."</string>
|
||||
<string name="screen_session_verification_waiting_to_accept_title">"Se așteptă acceptarea cererii"</string>
|
||||
</resources>
|
||||
@@ -27,9 +27,11 @@ import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class VerifySelfSessionPresenterTests {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -38,7 +38,7 @@ datetime = "0.4.0"
|
||||
serialization_json = "1.5.0"
|
||||
showkase = "1.0.0-beta17"
|
||||
jsoup = "1.15.4"
|
||||
appyx = "1.1.1"
|
||||
appyx = "1.1.2"
|
||||
dependencycheck = "8.2.1"
|
||||
stem = "2.3.0"
|
||||
sqldelight = "1.5.5"
|
||||
|
||||
@@ -37,11 +37,11 @@ import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
fun ConfirmationDialog(
|
||||
title: String,
|
||||
content: String,
|
||||
onSubmitClicked: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
title: String? = null,
|
||||
submitText: String = stringResource(id = StringR.string.action_ok),
|
||||
cancelText: String = stringResource(id = StringR.string.action_cancel),
|
||||
thirdButtonText: String? = null,
|
||||
@@ -60,7 +60,7 @@ fun ConfirmationDialog(
|
||||
modifier = modifier,
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text(text = title)
|
||||
if (title != null) { Text(text = title) }
|
||||
},
|
||||
text = {
|
||||
Text(content)
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.utils
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
|
||||
class SnackbarDispatcher {
|
||||
private val mutex = Mutex()
|
||||
|
||||
private val snackbarState = MutableStateFlow<SnackbarMessage?>(null)
|
||||
val snackbarMessage: Flow<SnackbarMessage?> = snackbarState
|
||||
|
||||
suspend fun post(message: SnackbarMessage) {
|
||||
mutex.withLock {
|
||||
snackbarState.update { message }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun clear() {
|
||||
mutex.withLock {
|
||||
snackbarState.update { null }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun handleSnackbarMessage(
|
||||
snackbarDispatcher: SnackbarDispatcher
|
||||
): SnackbarMessage? {
|
||||
val snackbarMessage by snackbarDispatcher.snackbarMessage.collectAsState(initial = null)
|
||||
LaunchedEffect(snackbarMessage) {
|
||||
if (snackbarMessage != null) {
|
||||
launch(Dispatchers.Main) {
|
||||
snackbarDispatcher.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
return snackbarMessage
|
||||
}
|
||||
|
||||
data class SnackbarMessage(
|
||||
@StringRes val messageResId: Int,
|
||||
val duration: SnackbarDuration = SnackbarDuration.Short,
|
||||
@StringRes val actionResId: Int? = null,
|
||||
val action: () -> Unit = {},
|
||||
)
|
||||
@@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.media.MediaResolver
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import java.io.Closeable
|
||||
@@ -46,4 +47,6 @@ interface MatrixClient : Closeable {
|
||||
): Result<ByteArray>
|
||||
|
||||
fun onSlidingSyncUpdate()
|
||||
|
||||
fun roomMembershipObserver(): RoomMembershipObserver
|
||||
}
|
||||
|
||||
@@ -32,8 +32,10 @@ interface MatrixRoom: Closeable {
|
||||
val topic: String?
|
||||
val avatarUrl: String?
|
||||
val isEncrypted: Boolean
|
||||
val isPublic: Boolean
|
||||
|
||||
suspend fun members() : List<RoomMember>
|
||||
|
||||
suspend fun memberCount(): Int
|
||||
|
||||
fun syncUpdateFlow(): Flow<Long>
|
||||
@@ -53,4 +55,6 @@ interface MatrixRoom: Closeable {
|
||||
suspend fun replyMessage(eventId: EventId, message: String): Result<Unit>
|
||||
|
||||
suspend fun redactEvent(eventId: EventId, reason: String? = null): Result<Unit>
|
||||
|
||||
fun leave(): Result<Unit>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.room
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
|
||||
class RoomMembershipObserver(
|
||||
private val sessionId: SessionId,
|
||||
) {
|
||||
data class RoomMembershipUpdate(
|
||||
val roomId: RoomId,
|
||||
val isUserInRoom: Boolean,
|
||||
val change: MembershipChange,
|
||||
)
|
||||
|
||||
private val _updates = MutableSharedFlow<RoomMembershipUpdate>(replay = 1)
|
||||
val updates = _updates.asSharedFlow()
|
||||
|
||||
fun notifyUserLeftRoom(roomId: RoomId) {
|
||||
_updates.tryEmit(RoomMembershipUpdate(roomId, false, MembershipChange.LEFT))
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.impl.media.RustMediaResolver
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.impl.room.RustMatrixRoom
|
||||
import io.element.android.libraries.matrix.impl.room.RustRoomSummaryDataSource
|
||||
import io.element.android.libraries.matrix.impl.sync.SlidingSyncObserverProxy
|
||||
@@ -92,6 +93,7 @@ class RustMatrixClient constructor(
|
||||
requiredState = listOf(
|
||||
RequiredState(key = "m.room.avatar", value = ""),
|
||||
RequiredState(key = "m.room.encryption", value = ""),
|
||||
RequiredState(key = "m.room.join_rules", value = ""),
|
||||
)
|
||||
)
|
||||
.filters(slidingSyncFilters)
|
||||
@@ -131,6 +133,8 @@ class RustMatrixClient constructor(
|
||||
private val mediaResolver = RustMediaResolver(this)
|
||||
private val isSyncing = AtomicBoolean(false)
|
||||
|
||||
private val roomMembershipObserver = RoomMembershipObserver(sessionId)
|
||||
|
||||
init {
|
||||
client.setDelegate(clientDelegate)
|
||||
rustRoomSummaryDataSource.init()
|
||||
@@ -153,7 +157,7 @@ class RustMatrixClient constructor(
|
||||
slidingSyncRoom = slidingSyncRoom,
|
||||
innerRoom = fullRoom,
|
||||
coroutineScope = coroutineScope,
|
||||
coroutineDispatchers = dispatchers
|
||||
coroutineDispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -270,6 +274,8 @@ class RustMatrixClient constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver
|
||||
|
||||
private fun File.deleteSessionDirectory(userID: String): Boolean {
|
||||
// Rust sanitises the user ID replacing invalid characters with an _
|
||||
val sanitisedUserID = userID.replace(":", "_")
|
||||
|
||||
@@ -22,7 +22,9 @@ import dagger.Provides
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
|
||||
@Module
|
||||
@ContributesTo(SessionScope::class)
|
||||
@@ -32,4 +34,10 @@ object SessionMatrixModule {
|
||||
fun providesRustSessionVerificationService(matrixClient: MatrixClient): SessionVerificationService {
|
||||
return matrixClient.sessionVerificationService()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@SingleIn(SessionScope::class)
|
||||
fun provideRoomMembershipObserver(matrixClient: MatrixClient): RoomMembershipObserver {
|
||||
return matrixClient.roomMembershipObserver()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,9 @@ class RustMatrixRoom(
|
||||
override val alternativeAliases: List<String>
|
||||
get() = innerRoom.alternativeAliases()
|
||||
|
||||
override val isPublic: Boolean
|
||||
get() = innerRoom.isPublic()
|
||||
|
||||
override suspend fun fetchMembers(): Result<Unit> = withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
innerRoom.fetchMembers()
|
||||
@@ -179,4 +182,8 @@ class RustMatrixRoom(
|
||||
innerRoom.redact(eventId.value, reason, transactionId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun leave(): Result<Unit> {
|
||||
return runCatching { innerRoom.leave() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.media.MediaResolver
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.test.media.FakeMediaResolver
|
||||
@@ -92,6 +93,10 @@ class FakeMatrixClient(
|
||||
|
||||
override fun onSlidingSyncUpdate() {}
|
||||
|
||||
override fun roomMembershipObserver(): RoomMembershipObserver {
|
||||
return RoomMembershipObserver(A_SESSION_ID)
|
||||
}
|
||||
|
||||
// Mocks
|
||||
|
||||
fun givenLogoutError(failure: Throwable?) {
|
||||
|
||||
@@ -37,6 +37,7 @@ class FakeMatrixRoom(
|
||||
override val isEncrypted: Boolean = false,
|
||||
override val alias: String? = null,
|
||||
override val alternativeAliases: List<String> = emptyList(),
|
||||
override val isPublic: Boolean = true,
|
||||
private val members: List<RoomMember> = emptyList(),
|
||||
private val matrixTimeline: MatrixTimeline = FakeMatrixTimeline(),
|
||||
) : MatrixRoom {
|
||||
@@ -46,6 +47,8 @@ class FakeMatrixRoom(
|
||||
var areMembersFetched: Boolean = false
|
||||
private set
|
||||
|
||||
private var leaveRoomError: Throwable? = null
|
||||
|
||||
override fun syncUpdateFlow(): Flow<Long> {
|
||||
return emptyFlow()
|
||||
}
|
||||
@@ -114,8 +117,14 @@ class FakeMatrixRoom(
|
||||
return Result.success(Unit)
|
||||
}
|
||||
|
||||
override fun leave(): Result<Unit> = leaveRoomError?.let { Result.failure(it) } ?: Result.success(Unit)
|
||||
|
||||
override fun close() = Unit
|
||||
|
||||
fun givenLeaveRoomError(throwable: Throwable?) {
|
||||
this.leaveRoomError = throwable
|
||||
}
|
||||
|
||||
fun givenFetchMemberResult(result: Result<Unit>) {
|
||||
fetchMemberResult = result
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="rich_text_editor_bullet_list">"Lista de puntos"</string>
|
||||
<string name="rich_text_editor_code_block">"Bloque de código"</string>
|
||||
<string name="rich_text_editor_composer_placeholder">"Mensaje…"</string>
|
||||
<string name="rich_text_editor_format_bold">"Aplicar formato negrita"</string>
|
||||
<string name="rich_text_editor_format_italic">"Aplicar formato cursiva"</string>
|
||||
<string name="rich_text_editor_format_strikethrough">"Aplicar formato tachado"</string>
|
||||
<string name="rich_text_editor_format_underline">"Aplicar formato de subrayado"</string>
|
||||
<string name="rich_text_editor_full_screen_toggle">"Pantalla completa"</string>
|
||||
<string name="rich_text_editor_indent">"Añadir sangría"</string>
|
||||
<string name="rich_text_editor_inline_code">"Código"</string>
|
||||
<string name="rich_text_editor_link">"Enlazar"</string>
|
||||
<string name="rich_text_editor_numbered_list">"Lista numérica"</string>
|
||||
<string name="rich_text_editor_quote">"Cita"</string>
|
||||
<string name="rich_text_editor_unindent">"Quitar sangría"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="rich_text_editor_bullet_list">"Attiva/disattiva l\'elenco puntato"</string>
|
||||
<string name="rich_text_editor_code_block">"Attiva/disattiva il blocco di codice"</string>
|
||||
<string name="rich_text_editor_composer_placeholder">"Messaggio…"</string>
|
||||
<string name="rich_text_editor_format_bold">"Applica il formato in grassetto"</string>
|
||||
<string name="rich_text_editor_format_italic">"Applicare il formato corsivo"</string>
|
||||
<string name="rich_text_editor_format_strikethrough">"Applica il formato barrato"</string>
|
||||
<string name="rich_text_editor_format_underline">"Applicare il formato di sottolineatura"</string>
|
||||
<string name="rich_text_editor_full_screen_toggle">"Attiva/disattiva la modalità a schermo intero"</string>
|
||||
<string name="rich_text_editor_indent">"Rientro a destra"</string>
|
||||
<string name="rich_text_editor_inline_code">"Applicare il formato del codice in linea"</string>
|
||||
<string name="rich_text_editor_link">"Imposta collegamento"</string>
|
||||
<string name="rich_text_editor_numbered_list">"Attiva/disattiva elenco numerato"</string>
|
||||
<string name="rich_text_editor_quote">"Attiva/disattiva citazione"</string>
|
||||
<string name="rich_text_editor_unindent">"Rientro a sinistra"</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="rich_text_editor_bullet_list">"Comutați lista cu puncte"</string>
|
||||
<string name="rich_text_editor_code_block">"Comutați blocul de cod"</string>
|
||||
<string name="rich_text_editor_composer_placeholder">"Mesaj…"</string>
|
||||
<string name="rich_text_editor_format_bold">"Aplicați formatul aldin"</string>
|
||||
<string name="rich_text_editor_format_italic">"Aplicați formatul italic"</string>
|
||||
<string name="rich_text_editor_format_strikethrough">"Aplicați formatul barat"</string>
|
||||
<string name="rich_text_editor_format_underline">"Aplică formatul de subliniere"</string>
|
||||
<string name="rich_text_editor_full_screen_toggle">"Comutați modul ecran complet"</string>
|
||||
<string name="rich_text_editor_indent">"Indentare"</string>
|
||||
<string name="rich_text_editor_inline_code">"Aplicați formatul de cod inline"</string>
|
||||
<string name="rich_text_editor_link">"Setați linkul"</string>
|
||||
<string name="rich_text_editor_numbered_list">"Comutați lista numerotată"</string>
|
||||
<string name="rich_text_editor_quote">"Aplicați citatul"</string>
|
||||
<string name="rich_text_editor_unindent">"Dez-identare"</string>
|
||||
</resources>
|
||||
@@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_confirm">"Bestätigen"</string>
|
||||
<string name="test_language_identifier">"de"</string>
|
||||
</resources>
|
||||
148
libraries/ui-strings/src/main/res/values-es/translations.xml
Normal file
148
libraries/ui-strings/src/main/res/values-es/translations.xml
Normal file
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="a11y_hide_password">"Ocultar contraseña"</string>
|
||||
<string name="a11y_send_files">"Enviar archivos"</string>
|
||||
<string name="a11y_show_password">"Mostrar contraseña"</string>
|
||||
<string name="a11y_user_menu">"Menú de usuario"</string>
|
||||
<string name="action_back">"Atrás"</string>
|
||||
<string name="action_cancel">"Cancelar"</string>
|
||||
<string name="action_clear">"Borrar"</string>
|
||||
<string name="action_close">"Cerrar"</string>
|
||||
<string name="action_complete_verification">"Completar verificación"</string>
|
||||
<string name="action_confirm">"Confirmar"</string>
|
||||
<string name="action_continue">"Continuar"</string>
|
||||
<string name="action_copy">"Copiar"</string>
|
||||
<string name="action_copy_link">"Copiar enlace"</string>
|
||||
<string name="action_create_a_room">"Crear una sala"</string>
|
||||
<string name="action_disable">"Desactivar"</string>
|
||||
<string name="action_done">"Hecho"</string>
|
||||
<string name="action_edit">"Editar"</string>
|
||||
<string name="action_enable">"Activar"</string>
|
||||
<string name="action_invite">"Invitar"</string>
|
||||
<string name="action_invite_friends_to_app">"Invitar amigos a %1$s"</string>
|
||||
<string name="action_learn_more">"Más información"</string>
|
||||
<string name="action_leave">"Salir"</string>
|
||||
<string name="action_leave_room">"Salir de la sala"</string>
|
||||
<string name="action_next">"Siguiente"</string>
|
||||
<string name="action_no">"No"</string>
|
||||
<string name="action_not_now">"Ahora no"</string>
|
||||
<string name="action_ok">"OK"</string>
|
||||
<string name="action_quick_reply">"Respuesta rápida"</string>
|
||||
<string name="action_quote">"Citar"</string>
|
||||
<string name="action_remove">"Eliminar"</string>
|
||||
<string name="action_reply">"Responder"</string>
|
||||
<string name="action_report_bug">"Informar de un error"</string>
|
||||
<string name="action_report_content">"Reportar Contenido"</string>
|
||||
<string name="action_retry">"Reintentar"</string>
|
||||
<string name="action_retry_decryption">"Reintentar descifrado"</string>
|
||||
<string name="action_save">"Guardar"</string>
|
||||
<string name="action_search">"Buscar"</string>
|
||||
<string name="action_send">"Enviar"</string>
|
||||
<string name="action_share">"Compartir"</string>
|
||||
<string name="action_share_link">"Compartir enlace"</string>
|
||||
<string name="action_skip">"Saltar"</string>
|
||||
<string name="action_start">"Comenzar"</string>
|
||||
<string name="action_start_chat">"Iniciar chat"</string>
|
||||
<string name="action_start_verification">"Iniciar la verificación"</string>
|
||||
<string name="action_view_source">"Ver Fuente"</string>
|
||||
<string name="action_yes">"Sí"</string>
|
||||
<string name="common_about">"Acerca de"</string>
|
||||
<string name="common_audio">"Sonido"</string>
|
||||
<string name="common_bubbles">"Burbujas"</string>
|
||||
<string name="common_creating_room">"Creando sala…"</string>
|
||||
<string name="common_current_user_left_room">"Saliste de la sala"</string>
|
||||
<string name="common_decryption_error">"Error de descifrado"</string>
|
||||
<string name="common_developer_options">"Opciones de desarrollador"</string>
|
||||
<string name="common_edited_suffix">"(editado)"</string>
|
||||
<string name="common_editing">"Edición"</string>
|
||||
<string name="common_encryption_enabled">"Cifrado activado"</string>
|
||||
<string name="common_error">"Error"</string>
|
||||
<string name="common_file">"Archivo"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_image">"Imagen"</string>
|
||||
<string name="common_link_copied_to_clipboard">"Enlace copiado al portapapeles"</string>
|
||||
<string name="common_loading">"Cargando…"</string>
|
||||
<string name="common_message">"Mensaje"</string>
|
||||
<string name="common_message_layout">"Diseño del mensaje"</string>
|
||||
<string name="common_message_removed">"Mensaje eliminado"</string>
|
||||
<string name="common_modern">"Moderno"</string>
|
||||
<string name="common_no_results">"No hay resultados"</string>
|
||||
<string name="common_offline">"Sin conexión"</string>
|
||||
<string name="common_password">"Contraseña"</string>
|
||||
<string name="common_people">"Personas"</string>
|
||||
<string name="common_permalink">"Enlace permanente"</string>
|
||||
<string name="common_reactions">"Reacciones"</string>
|
||||
<string name="common_replying_to">"Respondiendo a %1$s"</string>
|
||||
<string name="common_report_a_bug">"Informar de un error"</string>
|
||||
<string name="common_report_submitted">"Informe enviado"</string>
|
||||
<string name="common_search_for_someone">"Buscar a alguien"</string>
|
||||
<string name="common_security">"Seguridad"</string>
|
||||
<string name="common_select_your_server">"Selecciona tu servidor"</string>
|
||||
<string name="common_sending">"Enviando…"</string>
|
||||
<string name="common_server_not_supported">"Servidor no compatible"</string>
|
||||
<string name="common_server_url">"Dirección del servidor"</string>
|
||||
<string name="common_settings">"Ajustes"</string>
|
||||
<string name="common_sticker">"Sticker"</string>
|
||||
<string name="common_success">"Terminado"</string>
|
||||
<string name="common_suggestions">"Sugerencias"</string>
|
||||
<string name="common_topic">"Tema"</string>
|
||||
<string name="common_unable_to_decrypt">"No se puede descifrar"</string>
|
||||
<string name="common_unsupported_event">"Evento no compatible"</string>
|
||||
<string name="common_username">"Usuario"</string>
|
||||
<string name="common_verification_cancelled">"Verificación cancelada"</string>
|
||||
<string name="common_verification_complete">"Verificación completada"</string>
|
||||
<string name="common_video">"Vídeo"</string>
|
||||
<string name="common_waiting">"Esperando…"</string>
|
||||
<string name="dialog_title_confirmation">"Confirmar"</string>
|
||||
<string name="dialog_title_error">"Error"</string>
|
||||
<string name="dialog_title_success">"Terminado"</string>
|
||||
<string name="dialog_title_warning">"Atención"</string>
|
||||
<string name="emoji_picker_category_activity">"Actividades"</string>
|
||||
<string name="emoji_picker_category_flags">"Banderas"</string>
|
||||
<string name="emoji_picker_category_foods">"Comida y bebida"</string>
|
||||
<string name="emoji_picker_category_nature">"Animales y naturaleza"</string>
|
||||
<string name="emoji_picker_category_objects">"Objetos"</string>
|
||||
<string name="emoji_picker_category_people">"Emojis y personas"</string>
|
||||
<string name="emoji_picker_category_places">"Viajes y lugares"</string>
|
||||
<string name="emoji_picker_category_symbols">"Símbolos"</string>
|
||||
<string name="error_failed_creating_the_permalink">"No se pudo crear el enlace permanente"</string>
|
||||
<string name="error_failed_loading_messages">"Error al cargar mensajes"</string>
|
||||
<string name="error_no_compatible_app_found">"No se encontró ninguna aplicación compatible con esta acción."</string>
|
||||
<string name="error_some_messages_have_not_been_sent">"Algunos mensajes no se han enviado"</string>
|
||||
<string name="error_unknown">"Lo siento, se ha producido un error"</string>
|
||||
<string name="invite_friends_text">"Hola, puedes hablar conmigo en %1$s: %2$s"</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"¿Estás seguro de que quieres salir de esta sala? Eres la única persona aquí. Si te vas, nadie podrá unirse en el futuro, ni siquiera tú."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"¿Estás seguro de que quieres abandonar esta sala? Esta sala no es pública y no podrás volver a entrar sin una invitación."</string>
|
||||
<string name="leave_room_alert_subtitle">"¿Seguro que quieres salir de la habitación?"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<plurals name="common_member_count">
|
||||
<item quantity="one">"%1$d miembro"</item>
|
||||
<item quantity="other">"%1$d miembros"</item>
|
||||
</plurals>
|
||||
<plurals name="room_timeline_state_changes">
|
||||
<item quantity="one">"%1$d cambio en la sala"</item>
|
||||
<item quantity="other">"%1$d cambios en la sala"</item>
|
||||
</plurals>
|
||||
<string name="preference_rageshake">"Agitar con fuerza para informar de un error"</string>
|
||||
<string name="rageshake_dialog_content">"Parece que sacudes el teléfono con frustración. ¿Quieres abrir la pantalla de informe de errores?"</string>
|
||||
<string name="report_content_explanation">"Este mensaje se notificará al administrador de su homeserver. No podrán leer ningún mensaje cifrado."</string>
|
||||
<string name="report_content_hint">"Motivo para denunciar este contenido"</string>
|
||||
<string name="room_timeline_beginning_of_room">"Este es el principio de %1$s."</string>
|
||||
<string name="room_timeline_beginning_of_room_no_name">"Este es el principio de esta conversación."</string>
|
||||
<string name="room_timeline_read_marker_title">"Nuevos"</string>
|
||||
<string name="screen_report_content_block_user">"Bloquear usuario"</string>
|
||||
<string name="screen_report_content_block_user_hint">"Marque si quieres ocultar todos los mensajes actuales y futuros de este usuario"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Bloquear"</string>
|
||||
<string name="screen_room_member_details_block_alert_description">"Los usuarios bloqueados no podrán enviarte mensajes y se ocultarán todos sus mensajes. Puede revertir esta acción en cualquier momento."</string>
|
||||
<string name="screen_room_member_details_block_user">"Bloquear usuario"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_action">"Desbloquear"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_description">"Al desbloquear al usuario, podrás volver a ver todos sus mensajes."</string>
|
||||
<string name="screen_room_member_details_unblock_user">"Desbloquear usuario"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Se ha producido un error al intentar iniciar un chat"</string>
|
||||
<string name="screen_start_chat_unknown_profile">"No podemos validar el ID de Matrix de este usuario. Es posible que no reciba la invitación."</string>
|
||||
<string name="settings_rageshake">"Agitar con fuerza"</string>
|
||||
<string name="settings_rageshake_detection_threshold">"Umbral de detección"</string>
|
||||
<string name="settings_title_general">"General"</string>
|
||||
<string name="settings_version_number">"Versión: %1$s (%2$s)"</string>
|
||||
<string name="test_language_identifier">"es"</string>
|
||||
</resources>
|
||||
@@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_confirm">"Confirmer"</string>
|
||||
<string name="test_language_identifier">"fr"</string>
|
||||
</resources>
|
||||
148
libraries/ui-strings/src/main/res/values-it/translations.xml
Normal file
148
libraries/ui-strings/src/main/res/values-it/translations.xml
Normal file
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="a11y_hide_password">"Nascondi password"</string>
|
||||
<string name="a11y_send_files">"Invia file"</string>
|
||||
<string name="a11y_show_password">"Mostra password"</string>
|
||||
<string name="a11y_user_menu">"Menu utente"</string>
|
||||
<string name="action_back">"Indietro"</string>
|
||||
<string name="action_cancel">"Annulla"</string>
|
||||
<string name="action_clear">"Cancella"</string>
|
||||
<string name="action_close">"Chiudi"</string>
|
||||
<string name="action_complete_verification">"Completa verifica"</string>
|
||||
<string name="action_confirm">"Conferma"</string>
|
||||
<string name="action_continue">"Continua"</string>
|
||||
<string name="action_copy">"Copia"</string>
|
||||
<string name="action_copy_link">"Copia collegamento"</string>
|
||||
<string name="action_create_a_room">"Crea una stanza"</string>
|
||||
<string name="action_disable">"Disabilita"</string>
|
||||
<string name="action_done">"Fine"</string>
|
||||
<string name="action_edit">"Modifica"</string>
|
||||
<string name="action_enable">"Attiva"</string>
|
||||
<string name="action_invite">"Invita"</string>
|
||||
<string name="action_invite_friends_to_app">"Invita amici a %1$s"</string>
|
||||
<string name="action_learn_more">"Ulteriori informazioni"</string>
|
||||
<string name="action_leave">"Esci"</string>
|
||||
<string name="action_leave_room">"Esci dalla stanza"</string>
|
||||
<string name="action_next">"Avanti"</string>
|
||||
<string name="action_no">"No"</string>
|
||||
<string name="action_not_now">"Non ora"</string>
|
||||
<string name="action_ok">"OK"</string>
|
||||
<string name="action_quick_reply">"Risposta rapida"</string>
|
||||
<string name="action_quote">"Citazione"</string>
|
||||
<string name="action_remove">"Rimuovi"</string>
|
||||
<string name="action_reply">"Rispondi"</string>
|
||||
<string name="action_report_bug">"Segnala un problema"</string>
|
||||
<string name="action_report_content">"Segnala Contenuto"</string>
|
||||
<string name="action_retry">"Riprova"</string>
|
||||
<string name="action_retry_decryption">"Riprova la decrittazione"</string>
|
||||
<string name="action_save">"Salva"</string>
|
||||
<string name="action_search">"Ricerca"</string>
|
||||
<string name="action_send">"Invia"</string>
|
||||
<string name="action_share">"Condividi"</string>
|
||||
<string name="action_share_link">"Condividi collegamento"</string>
|
||||
<string name="action_skip">"Salta"</string>
|
||||
<string name="action_start">"Inizia"</string>
|
||||
<string name="action_start_chat">"Avvia conversazione"</string>
|
||||
<string name="action_start_verification">"Avvia la verifica"</string>
|
||||
<string name="action_view_source">"Vedi Sorgente"</string>
|
||||
<string name="action_yes">"Sì"</string>
|
||||
<string name="common_about">"Informazioni"</string>
|
||||
<string name="common_audio">"Audio"</string>
|
||||
<string name="common_bubbles">"Fumetti"</string>
|
||||
<string name="common_creating_room">"Creazione stanza…"</string>
|
||||
<string name="common_current_user_left_room">"Hai lasciato la stanza"</string>
|
||||
<string name="common_decryption_error">"Errore di decrittazione"</string>
|
||||
<string name="common_developer_options">"Opzioni sviluppatore"</string>
|
||||
<string name="common_edited_suffix">"(modificato)"</string>
|
||||
<string name="common_editing">"Modifica in corso"</string>
|
||||
<string name="common_encryption_enabled">"Crittografia abilitata"</string>
|
||||
<string name="common_error">"Errore"</string>
|
||||
<string name="common_file">"File"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_image">"Immagine"</string>
|
||||
<string name="common_link_copied_to_clipboard">"Collegamento copiato negli appunti"</string>
|
||||
<string name="common_loading">"Caricamento…"</string>
|
||||
<string name="common_message">"Messaggio"</string>
|
||||
<string name="common_message_layout">"Layout del messaggio"</string>
|
||||
<string name="common_message_removed">"Messaggio rimosso"</string>
|
||||
<string name="common_modern">"Moderno"</string>
|
||||
<string name="common_no_results">"Nessun risultato"</string>
|
||||
<string name="common_offline">"Non in linea"</string>
|
||||
<string name="common_password">"Password"</string>
|
||||
<string name="common_people">"Persone"</string>
|
||||
<string name="common_permalink">"Collegamento permanente"</string>
|
||||
<string name="common_reactions">"Reazioni"</string>
|
||||
<string name="common_replying_to">"Risposta a %1$s"</string>
|
||||
<string name="common_report_a_bug">"Segnala un problema"</string>
|
||||
<string name="common_report_submitted">"Segnalazione inviata"</string>
|
||||
<string name="common_search_for_someone">"Cerca qualcuno"</string>
|
||||
<string name="common_security">"Sicurezza"</string>
|
||||
<string name="common_select_your_server">"Seleziona il tuo server"</string>
|
||||
<string name="common_sending">"Invio in corso…"</string>
|
||||
<string name="common_server_not_supported">"Server non supportato"</string>
|
||||
<string name="common_server_url">"URL del server"</string>
|
||||
<string name="common_settings">"Impostazioni"</string>
|
||||
<string name="common_sticker">"Adesivo"</string>
|
||||
<string name="common_success">"Operazione riuscita"</string>
|
||||
<string name="common_suggestions">"Suggerimenti"</string>
|
||||
<string name="common_topic">"Oggetto"</string>
|
||||
<string name="common_unable_to_decrypt">"Impossibile decrittografare"</string>
|
||||
<string name="common_unsupported_event">"Evento non supportato"</string>
|
||||
<string name="common_username">"Nome utente"</string>
|
||||
<string name="common_verification_cancelled">"Verifica annullata"</string>
|
||||
<string name="common_verification_complete">"Verifica completata"</string>
|
||||
<string name="common_video">"Video"</string>
|
||||
<string name="common_waiting">"In attesa…"</string>
|
||||
<string name="dialog_title_confirmation">"Conferma"</string>
|
||||
<string name="dialog_title_error">"Errore"</string>
|
||||
<string name="dialog_title_success">"Operazione riuscita"</string>
|
||||
<string name="dialog_title_warning">"Attenzione"</string>
|
||||
<string name="emoji_picker_category_activity">"Attività"</string>
|
||||
<string name="emoji_picker_category_flags">"Bandiere"</string>
|
||||
<string name="emoji_picker_category_foods">"Cibi & Bevande"</string>
|
||||
<string name="emoji_picker_category_nature">"Animali & Natura"</string>
|
||||
<string name="emoji_picker_category_objects">"Oggetti"</string>
|
||||
<string name="emoji_picker_category_people">"Faccine & Persone"</string>
|
||||
<string name="emoji_picker_category_places">"Viaggi & Luoghi"</string>
|
||||
<string name="emoji_picker_category_symbols">"Simboli"</string>
|
||||
<string name="error_failed_creating_the_permalink">"Impossibile creare il collegamento permanente"</string>
|
||||
<string name="error_failed_loading_messages">"Caricamento dei messaggi non riuscito"</string>
|
||||
<string name="error_no_compatible_app_found">"Non è stata trovata alcuna app compatibile per gestire questa azione."</string>
|
||||
<string name="error_some_messages_have_not_been_sent">"Alcuni messaggi non sono stati inviati"</string>
|
||||
<string name="error_unknown">"Siamo spiacenti, si è verificato un errore"</string>
|
||||
<string name="invite_friends_text">"Ehi, parlami su %1$s: %2$s"</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"Sei sicuro di voler lasciare questa stanza? Sei l\'unica persona presente. Se esci, nessuno potrà unirsi in futuro, te compreso."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"Sei sicuro di voler lasciare questa stanza? Questa stanza non è pubblica e non potrai rientrare senza un invito."</string>
|
||||
<string name="leave_room_alert_subtitle">"Sei sicuro di voler lasciare la stanza?"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<plurals name="common_member_count">
|
||||
<item quantity="one">"%1$d membro"</item>
|
||||
<item quantity="other">"%1$d membri"</item>
|
||||
</plurals>
|
||||
<plurals name="room_timeline_state_changes">
|
||||
<item quantity="one">"%1$d modifica alla stanza"</item>
|
||||
<item quantity="other">"%1$d modifiche alla stanza"</item>
|
||||
</plurals>
|
||||
<string name="preference_rageshake">"Scuoti per segnalare un problema"</string>
|
||||
<string name="rageshake_dialog_content">"Sembra che tu stia scuotendo il telefono per la frustrazione. Vuoi aprire la schermata di segnalazione dei problemi?"</string>
|
||||
<string name="report_content_explanation">"Questo messaggio verrà segnalato all\'amministratore dell\'homeserver. Questi non sarà in grado di leggere i messaggi criptati."</string>
|
||||
<string name="report_content_hint">"Motivo della segnalazione di questo contenuto"</string>
|
||||
<string name="room_timeline_beginning_of_room">"Questo è l\'inizio di %1$s."</string>
|
||||
<string name="room_timeline_beginning_of_room_no_name">"Questo è l\'inizio della conversazione."</string>
|
||||
<string name="room_timeline_read_marker_title">"Nuovo"</string>
|
||||
<string name="screen_report_content_block_user">"Blocca utente"</string>
|
||||
<string name="screen_report_content_block_user_hint">"Seleziona se vuoi nascondere tutti i messaggi attuali e futuri di questo utente"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Blocca"</string>
|
||||
<string name="screen_room_member_details_block_alert_description">"Gli utenti bloccati non saranno in grado di inviarti nuovi messaggi e tutti quelli già esistenti saranno nascosti. Potrai annullare questa azione in qualsiasi momento."</string>
|
||||
<string name="screen_room_member_details_block_user">"Blocca utente"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_action">"Sblocca"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_description">"Dopo aver sbloccato l\'utente, potrai vedere nuovamente tutti i suoi messaggi."</string>
|
||||
<string name="screen_room_member_details_unblock_user">"Sblocca utente"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Si è verificato un errore durante il tentativo di avviare una chat"</string>
|
||||
<string name="screen_start_chat_unknown_profile">"Non possiamo convalidare l\'ID Matrix di questo utente. L\'invito potrebbe non essere ricevuto."</string>
|
||||
<string name="settings_rageshake">"Rageshake"</string>
|
||||
<string name="settings_rageshake_detection_threshold">"Soglia di rilevamento"</string>
|
||||
<string name="settings_title_general">"Generali"</string>
|
||||
<string name="settings_version_number">"Versione: %1$s (%2$s)"</string>
|
||||
<string name="test_language_identifier">"it"</string>
|
||||
</resources>
|
||||
@@ -1,10 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="action_confirm">"Confirmare"</string>
|
||||
<string name="a11y_hide_password">"Ascundeți parola"</string>
|
||||
<string name="a11y_send_files">"Trimiteți fișiere"</string>
|
||||
<string name="a11y_show_password">"Afișați parola"</string>
|
||||
<string name="a11y_user_menu">"Meniu utilizator"</string>
|
||||
<string name="action_back">"Înapoi"</string>
|
||||
<string name="action_cancel">"Anulați"</string>
|
||||
<string name="action_clear">"Ștergeți"</string>
|
||||
<string name="action_close">"Închideți"</string>
|
||||
<string name="action_complete_verification">"Verificare completă"</string>
|
||||
<string name="action_confirm">"Confirmați"</string>
|
||||
<string name="action_continue">"Continuați"</string>
|
||||
<string name="action_copy">"Copiați"</string>
|
||||
<string name="action_copy_link">"Copiați linkul"</string>
|
||||
<string name="action_create_a_room">"Creați o cameră"</string>
|
||||
<string name="action_done">"Gata"</string>
|
||||
<string name="action_disable">"Dezactivați"</string>
|
||||
<string name="action_done">"Efectuat"</string>
|
||||
<string name="action_edit">"Editați"</string>
|
||||
<string name="action_enable">"Activați"</string>
|
||||
<string name="action_invite">"Invitați"</string>
|
||||
<string name="action_invite_friends_to_app">"Invitați prieteni în %1$s"</string>
|
||||
<string name="action_learn_more">"Aflați mai multe"</string>
|
||||
<string name="action_leave">"Părăsiți"</string>
|
||||
<string name="action_leave_room">"Părăsiți camera"</string>
|
||||
<string name="action_next">"Următorul"</string>
|
||||
<string name="action_no">"Nu"</string>
|
||||
<string name="action_not_now">"Nu acum"</string>
|
||||
<string name="action_ok">"OK"</string>
|
||||
<string name="action_report_content">"Raportează conținutul"</string>
|
||||
<string name="action_start_chat">"Începe discuția"</string>
|
||||
<string name="action_view_source">"Vezi sursa"</string>
|
||||
<string name="action_quick_reply">"Raspuns rapid"</string>
|
||||
<string name="action_quote">"Citat"</string>
|
||||
<string name="action_remove">"Ștergeți"</string>
|
||||
<string name="action_reply">"Răspundeți"</string>
|
||||
<string name="action_report_bug">"Raportați o eroare"</string>
|
||||
<string name="action_report_content">"Raportați conținutul"</string>
|
||||
<string name="action_retry">"Reîncercați"</string>
|
||||
<string name="action_retry_decryption">"Reîncercați decriptarea"</string>
|
||||
<string name="action_save">"Salvați"</string>
|
||||
<string name="action_search">"Căutați"</string>
|
||||
<string name="action_send">"Trimiteți"</string>
|
||||
<string name="action_share">"Partajați"</string>
|
||||
<string name="action_share_link">"Partajați linkul"</string>
|
||||
<string name="action_skip">"Omiteți"</string>
|
||||
<string name="action_start">"Începeți"</string>
|
||||
<string name="action_start_chat">"Începeți discuția"</string>
|
||||
<string name="action_start_verification">"Începeți verificarea"</string>
|
||||
<string name="action_view_source">"Vedeți sursă"</string>
|
||||
<string name="action_yes">"Da"</string>
|
||||
<string name="common_about">"Despre"</string>
|
||||
<string name="common_audio">"Audio"</string>
|
||||
<string name="common_bubbles">"Baloane"</string>
|
||||
<string name="common_creating_room">"Se creează camera…"</string>
|
||||
<string name="common_current_user_left_room">"Ați parăsit camera"</string>
|
||||
<string name="common_decryption_error">"Eroare de decriptare"</string>
|
||||
<string name="common_developer_options">"Opțiuni programator"</string>
|
||||
<string name="common_edited_suffix">"(editat)"</string>
|
||||
<string name="common_editing">"Editare"</string>
|
||||
<string name="common_encryption_enabled">"Criptare activată"</string>
|
||||
<string name="common_error">"Eroare"</string>
|
||||
<string name="common_file">"Fişier"</string>
|
||||
<string name="common_gif">"GIF"</string>
|
||||
<string name="common_image">"Imagine"</string>
|
||||
<string name="common_link_copied_to_clipboard">"Linkul a fost copiat în clipboard"</string>
|
||||
<string name="common_loading">"Se încarcă…"</string>
|
||||
<string name="common_message">"Mesaj"</string>
|
||||
<string name="common_message_layout">"Aranjamentul mesajelor"</string>
|
||||
<string name="common_message_removed">"Mesaj sters"</string>
|
||||
<string name="common_modern">"Modern"</string>
|
||||
<string name="common_no_results">"Niciun rezultat"</string>
|
||||
<string name="common_offline">"Deconectat"</string>
|
||||
<string name="common_password">"Parola"</string>
|
||||
<string name="common_people">"Persoane"</string>
|
||||
<string name="common_permalink">"Permalink"</string>
|
||||
<string name="common_reactions">"Reacții"</string>
|
||||
<string name="common_replying_to">"Răspuns pentru %1$s"</string>
|
||||
<string name="common_report_a_bug">"Raportați o eroare"</string>
|
||||
<string name="common_report_submitted">"Raport trimis"</string>
|
||||
<string name="common_search_for_someone">"Căutați pe cineva"</string>
|
||||
<string name="common_security">"Securitate"</string>
|
||||
<string name="common_select_your_server">"Selectați serverul"</string>
|
||||
<string name="common_sending">"Se trimite…"</string>
|
||||
<string name="common_server_not_supported">"Serverul nu este compatibil"</string>
|
||||
<string name="common_server_url">"Adresa URL a serverului"</string>
|
||||
<string name="common_settings">"Setări"</string>
|
||||
<string name="common_sticker">"Autocolant"</string>
|
||||
<string name="common_success">"Succes"</string>
|
||||
<string name="common_suggestions">"Sugestii"</string>
|
||||
<string name="common_topic">"Subiect"</string>
|
||||
<string name="common_unable_to_decrypt">"Nu s-a putut decripta"</string>
|
||||
<string name="common_unsupported_event">"Eveniment neacceptat"</string>
|
||||
<string name="common_username">"Utilizator"</string>
|
||||
<string name="common_verification_cancelled">"Verificare anulată"</string>
|
||||
<string name="common_verification_complete">"Verificare completă"</string>
|
||||
<string name="common_video">"Video"</string>
|
||||
<string name="common_waiting">"Se aşteaptă…"</string>
|
||||
<string name="dialog_title_confirmation">"Confirmare"</string>
|
||||
<string name="dialog_title_error">"Eroare"</string>
|
||||
<string name="dialog_title_success">"Succes"</string>
|
||||
<string name="dialog_title_warning">"Avertisment"</string>
|
||||
<string name="emoji_picker_category_activity">"Activități"</string>
|
||||
<string name="emoji_picker_category_flags">"Steaguri"</string>
|
||||
<string name="emoji_picker_category_foods">"Mâncare & Băutură"</string>
|
||||
<string name="emoji_picker_category_nature">"Animale și Natură"</string>
|
||||
<string name="emoji_picker_category_objects">"Obiecte"</string>
|
||||
<string name="emoji_picker_category_people">"Fețe zâmbitoare & Oameni"</string>
|
||||
<string name="emoji_picker_category_places">"Călătorii & Locuri"</string>
|
||||
<string name="emoji_picker_category_symbols">"Simboluri"</string>
|
||||
<string name="error_failed_creating_the_permalink">"Crearea permalink-ului a eșuat"</string>
|
||||
<string name="error_failed_loading_messages">"Încărcarea mesajelor a eșuat"</string>
|
||||
<string name="error_no_compatible_app_found">"Nu a fost găsită nicio aplicație capabilă să gestioneze această acțiune."</string>
|
||||
<string name="error_some_messages_have_not_been_sent">"Unele mesaje nu au fost trimise"</string>
|
||||
<string name="error_unknown">"Ne pare rău, a apărut o eroare"</string>
|
||||
<string name="invite_friends_text">"Hei, vorbește cu mine pe %1$s: %2$s"</string>
|
||||
<string name="leave_room_alert_empty_subtitle">"Sunteți sigur că vreți să părăsiți această cameră? Sunteți singura persoană de aici. Dacă o părasiți, nimeni nu se va mai putea alătura în viitor, inclusiv dumneavoastra."</string>
|
||||
<string name="leave_room_alert_private_subtitle">"Sunteți sigur că vrei să părăsiți această cameră? Această cameră nu este publică și nu va veti putea alătura din nou fără o invitație."</string>
|
||||
<string name="leave_room_alert_subtitle">"Sunteți sigur că vreți să părăsiți camera?"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<plurals name="common_member_count">
|
||||
<item quantity="one">"%1$d membru"</item>
|
||||
<item quantity="few"></item>
|
||||
<item quantity="other">"%1$d membri"</item>
|
||||
</plurals>
|
||||
<plurals name="room_timeline_state_changes">
|
||||
<item quantity="one">"%1$d schimbare a camerii"</item>
|
||||
<item quantity="few"></item>
|
||||
<item quantity="other">"%1$d schimbări ale camerei"</item>
|
||||
</plurals>
|
||||
<string name="preference_rageshake">"Rageshake pentru a raporta erori"</string>
|
||||
<string name="rageshake_dialog_content">"Se pare că scuturați telefonul de frustrare. Doriți să deschdeți ecranul de raportare a unei erori?"</string>
|
||||
<string name="report_content_explanation">"Acest mesaj va fi raportat administratorilor homeserver-ului tau. Ei nu vor putea citi niciun mesaj criptat."</string>
|
||||
<string name="report_content_hint">"Motivul raportării acestui conținut"</string>
|
||||
<string name="room_timeline_beginning_of_room">"Acesta este începutul conversației %1$s."</string>
|
||||
<string name="room_timeline_beginning_of_room_no_name">"Acesta este începutul acestei conversații."</string>
|
||||
<string name="room_timeline_read_marker_title">"Nou"</string>
|
||||
<string name="screen_report_content_block_user">"Blocați utilizatorul"</string>
|
||||
<string name="screen_report_content_block_user_hint">"Confirmați că doriți să ascundeți toate mesajele curente și viitoare de la acest utilizator"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Blocați"</string>
|
||||
<string name="screen_room_member_details_block_alert_description">"Utilizatorii blocați nu vă vor putea trimite mesaje și toate mesajele lor vor fi ascunse. Puteți anula această acțiune oricând."</string>
|
||||
<string name="screen_room_member_details_block_user">"Blocați utilizatorul"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_action">"Deblocați"</string>
|
||||
<string name="screen_room_member_details_unblock_alert_description">"La deblocarea utilizatorului, veți putea vedea din nou toate mesajele de la acesta."</string>
|
||||
<string name="screen_room_member_details_unblock_user">"Deblocați utilizatorul"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"A apărut o eroare la încercarea începerii conversației"</string>
|
||||
<string name="screen_start_chat_unknown_profile">"Nu am putut valida ID-ul Matrix al acestui utilizator. Este posibil ca invitația să nu fi fost primită."</string>
|
||||
<string name="settings_rageshake">"Rageshake"</string>
|
||||
<string name="settings_rageshake_detection_threshold">"Prag de detecție"</string>
|
||||
<string name="settings_title_general">"General"</string>
|
||||
<string name="settings_version_number">"Versiunea: %1$s (%2$s)"</string>
|
||||
<string name="test_language_identifier">"ro"</string>
|
||||
</resources>
|
||||
@@ -38,6 +38,7 @@
|
||||
<string name="action_save">"Save"</string>
|
||||
<string name="action_search">"Search"</string>
|
||||
<string name="action_send">"Send"</string>
|
||||
<string name="action_share">"Share"</string>
|
||||
<string name="action_share_link">"Share link"</string>
|
||||
<string name="action_skip">"Skip"</string>
|
||||
<string name="action_start">"Start"</string>
|
||||
@@ -49,6 +50,7 @@
|
||||
<string name="common_audio">"Audio"</string>
|
||||
<string name="common_bubbles">"Bubbles"</string>
|
||||
<string name="common_creating_room">"Creating room…"</string>
|
||||
<string name="common_current_user_left_room">"Left room"</string>
|
||||
<string name="common_decryption_error">"Decryption error"</string>
|
||||
<string name="common_developer_options">"Developer options"</string>
|
||||
<string name="common_edited_suffix">"(edited)"</string>
|
||||
@@ -128,12 +130,6 @@
|
||||
<string name="room_timeline_beginning_of_room">"This is the beginning of %1$s."</string>
|
||||
<string name="room_timeline_beginning_of_room_no_name">"This is the beginning of this conversation."</string>
|
||||
<string name="room_timeline_read_marker_title">"New"</string>
|
||||
<string name="screen_dm_details_block_alert_action">"Block"</string>
|
||||
<string name="screen_dm_details_block_alert_description">"Blocked users will not be able to send you messages and all message by them will be hidden. You can reverse this action anytime."</string>
|
||||
<string name="screen_dm_details_block_user">"Block user"</string>
|
||||
<string name="screen_dm_details_unblock_alert_action">"Unblock"</string>
|
||||
<string name="screen_dm_details_unblock_alert_description">"On unblocking the user, you will be able to see all messages by them again."</string>
|
||||
<string name="screen_dm_details_unblock_user">"Unblock user"</string>
|
||||
<string name="screen_report_content_block_user">"Block user"</string>
|
||||
<string name="screen_report_content_block_user_hint">"Check if you want to hide all current and future messages from this user"</string>
|
||||
<string name="screen_room_member_details_block_alert_action">"Block"</string>
|
||||
@@ -143,8 +139,11 @@
|
||||
<string name="screen_room_member_details_unblock_alert_description">"On unblocking the user, you will be able to see all messages by them again."</string>
|
||||
<string name="screen_room_member_details_unblock_user">"Unblock user"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"An error occurred when trying to start a chat"</string>
|
||||
<string name="screen_start_chat_unknown_profile">"We can’t validate this user’s Matrix ID. The invite might not be received."</string>
|
||||
<string name="settings_rageshake">"Rageshake"</string>
|
||||
<string name="settings_rageshake_detection_threshold">"Detection threshold"</string>
|
||||
<string name="settings_title_general">"General"</string>
|
||||
<string name="settings_version_number">"Version: %1$s (%2$s)"</string>
|
||||
<string name="test_language_identifier">"en"</string>
|
||||
<string name="test_untranslated_default_language_identifier">"en"</string>
|
||||
</resources>
|
||||
@@ -26,6 +26,7 @@ import io.element.android.features.roomlist.impl.RoomListView
|
||||
import io.element.android.libraries.dateformatter.impl.DateFormatters
|
||||
import io.element.android.libraries.dateformatter.impl.DefaultLastMessageTimestampFormatter
|
||||
import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -47,7 +48,8 @@ class RoomListScreen(
|
||||
matrixClient,
|
||||
DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
|
||||
DefaultRoomLastMessageFormatter(context, matrixClient),
|
||||
sessionVerificationService
|
||||
sessionVerificationService,
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -2,12 +2,49 @@
|
||||
|
||||
Localazy is used to host the source strings and their translations.
|
||||
|
||||
<!--- TOC -->
|
||||
|
||||
* [Localazy project](#localazy-project)
|
||||
* [Key naming rules](#key-naming-rules)
|
||||
* [Special suffixes](#special-suffixes)
|
||||
* [Placeholders](#placeholders)
|
||||
* [CLI Installation](#cli-installation)
|
||||
* [Download translations](#download-translations)
|
||||
* [Add translations to a specific module](#add-translations-to-a-specific-module)
|
||||
|
||||
<!--- END -->
|
||||
|
||||
## Localazy project
|
||||
|
||||
To add new strings, or to translate existing strings, go the the Localazy project: [https://localazy.com/p/element](https://localazy.com/p/element).
|
||||
To add new strings, or to translate existing strings, go the the Localazy project: [https://localazy.com/p/element](https://localazy.com/p/element). Please follow the key naming rules (see below).
|
||||
|
||||
Never edit manually the files `localazy.xml` or `translations.xml`!.
|
||||
|
||||
### Key naming rules
|
||||
|
||||
For code clarity and in order to download strings to the correct module, here are some naming rules to follow as much as possible:
|
||||
|
||||
- Keys for common strings, i.e. strings that can be used at multiple places must start by `action_` if this is a verb, or `common_` if not;
|
||||
- Keys for common accessibility strings must start by `a11y_`. Example: `a11y_hide_password`;
|
||||
- Keys for strings used in a single screen must start with `screen_` followed by the screen name, followed by a free name. Example: `screen_onboarding_welcome_title`;
|
||||
- Keys can have `_title` or `_subtitle` suffixes. Example: `screen_onboarding_welcome_title`, `screen_change_server_subtitle`;
|
||||
- For dialogs, keys can have `_dialog_title`, `_dialog_content`, and `_dialog_submit` suffixes. Example: `screen_signout_confirmation_dialog_title`, `screen_signout_confirmation_dialog_content`, `screen_signout_confirmation_dialog_submit`;
|
||||
- `a11y_` pattern can be used for strings that are only used for accessibility. Example: `a11y_hide_password`, `screen_roomlist_a11y_create_message`;
|
||||
- Strings for error message can start by `error_`, or contain `_error_` if used in a specific screen only. Example: `error_some_messages_have_not_been_sent`, `screen_change_server_error_invalid_homeserver`.
|
||||
|
||||
*Note*: those rules applies for `strings` and for `plurals`.
|
||||
|
||||
#### Special suffixes
|
||||
|
||||
- if a key is suffixed by `_ios`, it will not be imported in the Android project;
|
||||
- if a key is suffixed by `_android`, it will not be imported in the iOS project.
|
||||
|
||||
So feel free to use those suffixes when necessary for instance when the string content is referring to something related to Android only, or iOS only.
|
||||
|
||||
#### Placeholders
|
||||
|
||||
Placeholders should have the form `%1$s`, `%1$d`, etc.. Please use numbered placeholders. Note that Localazy will take care of converting the placeholder to Android (-> `%1$s`) and iOS specific format (-> `%1$@`). Ideally add a comment on Localazy to explain with what the placeholder(s) will be replaced at runtime.
|
||||
|
||||
## CLI Installation
|
||||
|
||||
To install the Localazy client, follow the instructions from [here](https://localazy.com/docs/cli/installation).
|
||||
@@ -20,7 +57,13 @@ In the root folder of the project, run:
|
||||
./tools/localazy/downloadStrings.sh
|
||||
```
|
||||
|
||||
It will update all the `localazy.xml` and `translations.xml` resource files. In case of merge conflicts, just erase the files and download again using the script.
|
||||
It will update all the `localazy.xml` resource files. In case of merge conflicts, just erase the files and download again using the script.
|
||||
|
||||
To also include the translations, i.e. the `translations.xml` files, add `--all` argument:
|
||||
|
||||
```shell
|
||||
./tools/localazy/downloadStrings.sh --all
|
||||
```
|
||||
|
||||
## Add translations to a specific module
|
||||
|
||||
|
||||
@@ -18,12 +18,24 @@
|
||||
|
||||
set -e
|
||||
|
||||
echo "Generating the configuration file for localazy..."
|
||||
./tools/localazy/generateLocalazyConfig.py
|
||||
if [[ $1 == "--all" ]]; then
|
||||
echo "Note: I will update all the files."
|
||||
allFiles=1
|
||||
else
|
||||
echo "Note: I will update only the English files."
|
||||
allFiles=0
|
||||
fi
|
||||
|
||||
echo "Deleting all existing localazy.xml and translations.xml files..."
|
||||
echo "Generating the configuration file for localazy..."
|
||||
./tools/localazy/generateLocalazyConfig.py $allFiles
|
||||
|
||||
echo "Deleting all existing localazy.xml files..."
|
||||
find . -name 'localazy.xml' -delete
|
||||
find . -name 'translations.xml' -delete
|
||||
|
||||
if [[ $allFiles == 1 ]]; then
|
||||
echo "Deleting all existing translations.xml files..."
|
||||
find . -name 'translations.xml' -delete
|
||||
fi
|
||||
|
||||
echo "Importing the strings..."
|
||||
localazy download --config ./tools/localazy/localazy.json
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
# Read the config.json file
|
||||
with open('./tools/localazy/config.json', 'r') as f:
|
||||
config = json.load(f)
|
||||
|
||||
allFiles = sys.argv[1] == "1"
|
||||
|
||||
# Convert a module name to a path
|
||||
# Ex: ":features:verifysession:impl" => "features/verifysession/impl"
|
||||
@@ -18,6 +20,14 @@ regexToAlwaysExclude = [
|
||||
".*_ios"
|
||||
]
|
||||
|
||||
baseAction = {
|
||||
"type": "android",
|
||||
# Replacement done in all string values
|
||||
"replacements": {
|
||||
"...": "…"
|
||||
}
|
||||
}
|
||||
|
||||
# Store all regex specific to module, to eclude the corresponding keyx from the common string module
|
||||
allRegexToExcludeFromMainModule = []
|
||||
# All actions that will be serialized in the localazy config
|
||||
@@ -26,8 +36,7 @@ allActions = []
|
||||
# Iterating on the config
|
||||
for entry in config["modules"]:
|
||||
# Create action for the default language
|
||||
action = {
|
||||
"type": "android",
|
||||
action = baseAction | {
|
||||
"output": convertModuleToPath(entry["name"]) + "/src/main/res/values/localazy.xml",
|
||||
"includeKeys": list(map(lambda i: "REGEX:" + i, entry["includeRegex"])),
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, regexToAlwaysExclude)),
|
||||
@@ -35,24 +44,23 @@ for entry in config["modules"]:
|
||||
"equals: ${languageCode}, en"
|
||||
]
|
||||
}
|
||||
# Create action for the translations
|
||||
actionTranslation = {
|
||||
"type": "android",
|
||||
"output": convertModuleToPath(entry["name"]) + "/src/main/res/values-${langAndroidResNoScript}/translations.xml",
|
||||
"includeKeys": list(map(lambda i: "REGEX:" + i, entry["includeRegex"])),
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, regexToAlwaysExclude)),
|
||||
"conditions": [
|
||||
"!equals: ${languageCode}, en"
|
||||
]
|
||||
}
|
||||
# print(action)
|
||||
allRegexToExcludeFromMainModule.extend(entry["includeRegex"])
|
||||
allActions.append(action)
|
||||
allActions.append(actionTranslation)
|
||||
# Create action for the translations
|
||||
if allFiles:
|
||||
actionTranslation = baseAction | {
|
||||
"output": convertModuleToPath(entry["name"]) + "/src/main/res/values-${langAndroidResNoScript}/translations.xml",
|
||||
"includeKeys": list(map(lambda i: "REGEX:" + i, entry["includeRegex"])),
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, regexToAlwaysExclude)),
|
||||
"conditions": [
|
||||
"!equals: ${languageCode}, en"
|
||||
]
|
||||
}
|
||||
allActions.append(actionTranslation)
|
||||
allRegexToExcludeFromMainModule.extend(entry["includeRegex"])
|
||||
|
||||
# Append configuration for the main string module: default language
|
||||
mainAction = {
|
||||
"type": "android",
|
||||
mainAction = baseAction | {
|
||||
"output": "libraries/ui-strings/src/main/res/values/localazy.xml",
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, allRegexToExcludeFromMainModule + regexToAlwaysExclude)),
|
||||
"conditions": [
|
||||
@@ -62,16 +70,16 @@ mainAction = {
|
||||
# print(mainAction)
|
||||
allActions.append(mainAction)
|
||||
|
||||
# Append configuration for the main string module: translations
|
||||
mainActionTranslation = {
|
||||
"type": "android",
|
||||
"output": "libraries/ui-strings/src/main/res/values-${langAndroidResNoScript}/translations.xml",
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, allRegexToExcludeFromMainModule + regexToAlwaysExclude)),
|
||||
"conditions": [
|
||||
"!equals: ${languageCode}, en"
|
||||
]
|
||||
}
|
||||
allActions.append(mainActionTranslation)
|
||||
if allFiles:
|
||||
# Append configuration for the main string module: translations
|
||||
mainActionTranslation = baseAction | {
|
||||
"output": "libraries/ui-strings/src/main/res/values-${langAndroidResNoScript}/translations.xml",
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, allRegexToExcludeFromMainModule + regexToAlwaysExclude)),
|
||||
"conditions": [
|
||||
"!equals: ${languageCode}, en"
|
||||
]
|
||||
}
|
||||
allActions.append(mainActionTranslation)
|
||||
|
||||
# Generate the configuration for localazy
|
||||
result = {
|
||||
|
||||
Reference in New Issue
Block a user