diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b135aa5c9e..80e09ffdeb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ on: # Enrich gradle.properties for CI/CD env: - GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon jobs: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1e05533da1..93d63af5d3 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -7,7 +7,7 @@ on: - cron: "0 4 * * *" env: - GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon jobs: diff --git a/.github/workflows/nightly_er.yml b/.github/workflows/nightly_er.yml index e9981ad06a..7efa900b06 100644 --- a/.github/workflows/nightly_er.yml +++ b/.github/workflows/nightly_er.yml @@ -6,7 +6,7 @@ on: - cron: "0 4 * * *" env: - GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=1g" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon jobs: diff --git a/.github/workflows/sync-from-external-sources.yml b/.github/workflows/sync-from-external-sources.yml index 489ed1646e..ddb182f306 100644 --- a/.github/workflows/sync-from-external-sources.yml +++ b/.github/workflows/sync-from-external-sources.yml @@ -1,5 +1,6 @@ name: Sync Data From External Sources on: + workflow_dispatch: schedule: # At 00:00 on every Monday UTC - cron: '0 0 * * 1' @@ -80,4 +81,4 @@ jobs: *Note*: Change are coming from [this project](https://github.com/matrix-org/matrix-analytics-events) branch: sync-analytics-plan - base: develop \ No newline at end of file + base: develop diff --git a/.github/workflows/tests-rust.yml b/.github/workflows/tests-rust.yml index 6713f29baf..803b0a08ab 100644 --- a/.github/workflows/tests-rust.yml +++ b/.github/workflows/tests-rust.yml @@ -9,7 +9,7 @@ on: # Enrich gradle.properties for CI/CD env: - GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx5g -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx3g" -Dkotlin.incremental=false CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon jobs: diff --git a/CHANGES.md b/CHANGES.md index 53ddf8a4ef..6996863716 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,21 @@ +Changes in Element v1.6.6 (2023-10-05) +====================================== + +Bugfixes 🐛 +---------- + - Fixed JWT token for Jitsi openidtoken-jwt authentication ([#7758](https://github.com/vector-im/element-android/issues/7758)) + - Fix crash when max shortcuts count is exceeded ([#8644](https://github.com/vector-im/element-android/issues/8644)) + - Fix Login with QR code not working with rust crypto. ([#8653](https://github.com/vector-im/element-android/issues/8653)) + +Other changes +------------- + - Use 3PID capability to show / hide email UI in settings ([#8615](https://github.com/vector-im/element-android/issues/8615)) + - If an external account manager is configured on the server, use it to delete other sessions and hide the multi session deletion. ([#8616](https://github.com/vector-im/element-android/issues/8616)) + - Hide account deactivation UI for account managed externally. ([#8619](https://github.com/vector-im/element-android/issues/8619)) + - Fix import of SAS Emoji string translations. ([#8623](https://github.com/vector-im/element-android/issues/8623)) + - Open external account manager for delete other sessions using Chrome custom tabs. ([#8645](https://github.com/vector-im/element-android/issues/8645)) + + Changes in Element v1.6.5 (2023-07-25) ====================================== diff --git a/build.gradle b/build.gradle index edf07c097a..dae89f7aff 100644 --- a/build.gradle +++ b/build.gradle @@ -331,6 +331,10 @@ ext.initScreenshotTests = { project -> } } +tasks.withType(Test) { + maxHeapSize = "2g" +} + // Workaround to have KSP generated Kotlin code available in the IDE (for code completion) // Ref: https://github.com/airbnb/epoxy/releases/tag/5.0.0beta02 subprojects { project -> diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40106030.txt b/fastlane/metadata/android/cs-CZ/changelogs/40106030.txt new file mode 100644 index 0000000000..797d2af0ae --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40106030.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Element Android nyní používá Crypto Rust SDK. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40106050.txt b/fastlane/metadata/android/cs-CZ/changelogs/40106050.txt new file mode 100644 index 0000000000..786038aceb --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40106050.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: opravné vydání. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40106030.txt b/fastlane/metadata/android/de-DE/changelogs/40106030.txt new file mode 100644 index 0000000000..80ee810eec --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40106030.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Element Android nutzt nun das Crypto-Rust-SDK. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/de-DE/changelogs/40106050.txt b/fastlane/metadata/android/de-DE/changelogs/40106050.txt new file mode 100644 index 0000000000..080d868c88 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40106050.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Fehlerbehebungen. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/en-US/changelogs/40106060.txt b/fastlane/metadata/android/en-US/changelogs/40106060.txt new file mode 100644 index 0000000000..a92874476b --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40106060.txt @@ -0,0 +1,2 @@ +Main changes in this version: mainly bug fixes. +Full changelog: https://github.com/vector-im/element-android/releases \ No newline at end of file diff --git a/fastlane/metadata/android/fa/changelogs/40106030.txt b/fastlane/metadata/android/fa/changelogs/40106030.txt new file mode 100644 index 0000000000..1482b03042 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40106030.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: المنت اندروید اکنون از SDK راست Crypto استفاده می‌کند. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fa/changelogs/40106050.txt b/fastlane/metadata/android/fa/changelogs/40106050.txt new file mode 100644 index 0000000000..fb965624ac --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40106050.txt @@ -0,0 +1,2 @@ +تغغیرات عمده در این نگارش: ارائه تصحیحی. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40106030.txt b/fastlane/metadata/android/id/changelogs/40106030.txt new file mode 100644 index 0000000000..b69e7fc7b9 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40106030.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Element Android sekarang menggunakan SDK Kripto Rust. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40106050.txt b/fastlane/metadata/android/id/changelogs/40106050.txt new file mode 100644 index 0000000000..ab716d6f45 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40106050.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: rilis perbaikan. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105160.txt b/fastlane/metadata/android/pt-BR/changelogs/40105160.txt new file mode 100644 index 0000000000..0e5e1a9401 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105160.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Threads são agora habilitadas por padrão. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105180.txt b/fastlane/metadata/android/pt-BR/changelogs/40105180.txt new file mode 100644 index 0000000000..0e5e1a9401 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105180.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Threads são agora habilitadas por padrão. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105200.txt b/fastlane/metadata/android/pt-BR/changelogs/40105200.txt new file mode 100644 index 0000000000..d02800b55f --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105200.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Basicamente correção de bugs! +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105220.txt b/fastlane/metadata/android/pt-BR/changelogs/40105220.txt new file mode 100644 index 0000000000..bacba5f148 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105220.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Basicamente melhorias no recurso de transmissão de voz. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105240.txt b/fastlane/metadata/android/pt-BR/changelogs/40105240.txt new file mode 100644 index 0000000000..2e824d1a6e --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105240.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Basicamente correção de bugs, em especial a correção da mensagem não aparecer na linha do tempo. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105250.txt b/fastlane/metadata/android/pt-BR/changelogs/40105250.txt new file mode 100644 index 0000000000..2e824d1a6e --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105250.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Basicamente correção de bugs, em especial a correção da mensagem não aparecer na linha do tempo. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105260.txt b/fastlane/metadata/android/pt-BR/changelogs/40105260.txt new file mode 100644 index 0000000000..d48b592279 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105260.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Basicamente correção de bugs. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105280.txt b/fastlane/metadata/android/pt-BR/changelogs/40105280.txt new file mode 100644 index 0000000000..d48b592279 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105280.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Basicamente correção de bugs. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105300.txt b/fastlane/metadata/android/pt-BR/changelogs/40105300.txt new file mode 100644 index 0000000000..4dc17840a3 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105300.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: permalinks para salas, espaços, usuários e mensagens são agora exibidos como pílulas na linha do tempo. Também corrigimos alguns problemas com figurinhas personalizadas e o marcador de lido ficando travado no passado. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40105320.txt b/fastlane/metadata/android/pt-BR/changelogs/40105320.txt new file mode 100644 index 0000000000..d48b592279 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40105320.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Basicamente correção de bugs. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40106000.txt b/fastlane/metadata/android/pt-BR/changelogs/40106000.txt new file mode 100644 index 0000000000..f2fc40111f --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Element Android está agora usando o Crypto Rust SDK. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40106010.txt b/fastlane/metadata/android/pt-BR/changelogs/40106010.txt new file mode 100644 index 0000000000..f2fc40111f --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Element Android está agora usando o Crypto Rust SDK. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40106020.txt b/fastlane/metadata/android/pt-BR/changelogs/40106020.txt new file mode 100644 index 0000000000..f2fc40111f --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Element Android está agora usando o Crypto Rust SDK. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40106030.txt b/fastlane/metadata/android/sk/changelogs/40106030.txt new file mode 100644 index 0000000000..bb76d77ad5 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40106030.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Element Android teraz používa Crypto Rust SDK. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40106050.txt b/fastlane/metadata/android/sk/changelogs/40106050.txt new file mode 100644 index 0000000000..1131453ad1 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40106050.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: opravné vydanie. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sq/changelogs/40106030.txt b/fastlane/metadata/android/sq/changelogs/40106030.txt new file mode 100644 index 0000000000..862a7c9341 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40106030.txt @@ -0,0 +1,2 @@ +Ndryshime në këtë version: Element Android tanimë përdor Crypto Rust SDK. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sq/changelogs/40106050.txt b/fastlane/metadata/android/sq/changelogs/40106050.txt new file mode 100644 index 0000000000..cc67e3d075 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40106050.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: hedhje në qarkullim me ndreqje të ndryshme. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/uk/changelogs/40106030.txt b/fastlane/metadata/android/uk/changelogs/40106030.txt new file mode 100644 index 0000000000..dff9f740b9 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40106030.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Element для Android відтепер використовує Crypto Rust SDK. +Список усіх змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/uk/changelogs/40106050.txt b/fastlane/metadata/android/uk/changelogs/40106050.txt new file mode 100644 index 0000000000..9499991d27 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40106050.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: коригувальний випуск. +Список усіх змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40106030.txt b/fastlane/metadata/android/zh-TW/changelogs/40106030.txt new file mode 100644 index 0000000000..568991bf5b --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40106030.txt @@ -0,0 +1,2 @@ +此版本的主要變更:現在起,Element Android 使用 Crypto Rust SDK。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40106050.txt b/fastlane/metadata/android/zh-TW/changelogs/40106050.txt new file mode 100644 index 0000000000..77dbdb256c --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40106050.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:版本修正。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/library/ui-strings/src/main/res/values-az/strings.xml b/library/ui-strings/src/main/res/values-az/strings.xml index b8341cd2b4..a088420037 100644 --- a/library/ui-strings/src/main/res/values-az/strings.xml +++ b/library/ui-strings/src/main/res/values-az/strings.xml @@ -256,4 +256,39 @@ • IP literallarına uyğunlaşan serverlər qadağan edildi. • IP literallarına uyğunlaşan serverlərə icazə verilir. + Otaqdakı mesaj + Bağlantı + Bağlantı yarat + Anket + Otaq / Məkan + Bağlantını redaktə et + Mətn + Anket başa çatıb. + %1$s ekran adını %2$s olaraq dəyişdi + Daxili kod formatın işlət + Kod blokun dəyiş + Bu otaq üçün əsas ünvanı %1$s olaraq təyin etdiniz. + Mesaj %s + Bu otaq üçün ünvan kimi %2$s-nı sildiniz və %1$s əlavə etdiniz. + Giriş Nişanəniz + %1$s bu otaq üçün əsas ünvanı sildi. + Anket bitdi + %1$s bu otaq üçün əsas ünvanı %2$s olaraq təyin etdi. + Mesaj + %s-dan² mesaj + Giriş nişanəniz hesabınıza tam giriş imkanı verir.Bunu heç kimlə paylaşmayın. + + Bu otaq üçün alternativ %1$s ünvanın əlavə etdiniz. + Bu otaq üçün alternativ %1$s ünvanın əlavə etdiniz. + + %1$s bu otaq üçün alternativ ünvanları dəyişdi. + + %1$s bu otaq üçün %2$s alternativ ünvanın əlavə etdi. + %1$s bu otaq üçün %2$s alternativ ünvanın əlavə etdi. + + Bu otaq üçün alternativ ünvanları dəyişdiniz. + + %1$s bu otaq üçün %2$s alternativ ünvanın sildi. + %1$s bu otaq üçün %2$s alternativ ünvanın sildi. + \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-de/strings.xml b/library/ui-strings/src/main/res/values-de/strings.xml index 0871842a4d..5698cdf268 100644 --- a/library/ui-strings/src/main/res/values-de/strings.xml +++ b/library/ui-strings/src/main/res/values-de/strings.xml @@ -224,7 +224,7 @@ Du hast die Server-ACL für diesen Raum gesetzt. %s hat die Server-Zugriffssteuerungsliste (ACL) für diesen Raum gesetzt. Einstellungen - Akzeptiere + Akzeptieren Ablehnen Anruf beenden Ok @@ -263,7 +263,7 @@ Nur Matrix-Kontakte Keine Ergebnisse Räume - Sende Protokolle + Protokolle senden Absturzberichte übermitteln Bildschirmfoto übermitteln Problem melden @@ -692,7 +692,7 @@ Laute Benachrichtigungen einstellen Anrufbenachrichtigung einstellen Stumme Benachrichtigungen einstellen - Wähle LED-Farbe, Vibration, Ton … + LED-Farbe, Vibration, Ton auswählen … Stumm Bitte eine Passphrase eingeben Passphrase ist zu schwach @@ -712,7 +712,7 @@ Historie entschlüsseln Von Sicherung wiederherstellen Lösche Sicherung - Lösche Sicherung … + Sicherung löschen … Lösche Sicherung Präferenz der Benachrichtigungen nach Ereignis [%1$s] @@ -728,7 +728,7 @@ \nSichere deine Schlüssel, um sie nicht zu verlieren. Wiederherstellungsschlüssel aus Passphrase generieren. Dies kann mehrere Sekunden brauchen. Du verlierst möglicherweise den Zugang zu deinen Nachrichten, wenn du dich abmeldest oder das Gerät verlierst. - Rufe Sicherungsversion ab … + Sicherungsversion abrufen … Nutze deine Wiederherstellungs-Passphrase, um deinen verschlüsselten Nachrichtenverlauf lesen zu können nutze deinen Wiederherstellungsschlüssel Wenn du deine Wiederherstellungspassphrase nicht weist, kannst du %s. @@ -793,15 +793,15 @@ Sichere deine Schlüssel. Dies könnte einige Minuten dauern … Alle Schlüssel sind gesichert - Sichere einen Schlüssel … - Sichere %d Schlüssel … + Einen Schlüssel sichern … + %d Schlüssel sichern … Version Algorithmus Signatur - Berechne Wiederherstellungsschlüssel … - Lade Schlüssel herunter … - Importiere Schlüssel … + Wiederherstellungsschlüssel berechnen … + Schlüssel herunterladen … + Schlüssel importieren … Ignorieren Mit Single-Sign-On anmelden Nachricht mit Eingabetaste senden @@ -903,8 +903,8 @@ Versteckte Ereignisse in der Zeitleiste anzeigen Direktnachrichten Warten … - Vorschaubild wird verschlüsselt … - Verschlüssle Datei … + Vorschaubild verschlüsseln … + Datei verschlüsseln … (bearbeitet) Nachrichtenbearbeitung Keine Änderungen gefunden @@ -912,7 +912,7 @@ Sende eine neue Direktnachricht Das Raumverzeichnis anzeigen Link in die Zwischenablage kopiert - Erstelle Raum … + Raum erstellen … Bearbeitungsverlauf anzeigen E2E-Schlüssel aus der Datei \"%1$s\" importieren. Vielen Dank, der Vorschlag wurde erfolgreich gesendet @@ -1003,7 +1003,7 @@ Anhang senden Navigationsmenü öffnen Raumerstellungsmenü öffnen - Schließe das Raumerstellungsmenü … + Das Raumerstellungsmenü schließen … Erstelle eine neue Direktnachricht Erstelle einen neuen Raum Schließe Key-Backup-Einblendung @@ -1030,15 +1030,15 @@ Inhalt gemeldet Dieser Inhalt wurde gemeldet. \n -\nWenn du keine weiteren Inhalte dieser Person sehen möchtest, kannst sie ignorieren, um ihre Nachrichten auszublenden. +\nWenn du keine Inhalte mehr von dieser Person sehen möchtest, kannst du sie ignorieren, um ihre Nachrichten auszublenden. Als Spam gemeldet Dieser Inhalt wurde als Spam gemeldet. \n -\nWenn du keine weiteren Inhalte dieser Person sehen möchtest, kannst sie ignorieren, um ihre Nachrichten auszublenden. +\nWenn du keine Inhalte mehr von dieser Person sehen möchtest, kannst du sie ignorieren, um ihre Nachrichten auszublenden. Als unangebracht gemeldet Dieser Inhalt wurde als unangebracht gemeldet. \n -\nWenn du keine weiteren Inhalte dieser Person sehen möchtest, kannst sie ignorieren, um ihre Nachrichten auszublenden. +\nWenn du keine Inhalte mehr von dieser Person sehen möchtest, kannst du sie ignorieren, um ihre Nachrichten auszublenden. Nutzer ignorieren Alle Nachrichten (laut) Alle Nachrichten @@ -1524,8 +1524,8 @@ DATEIEN %1$s um %2$s Es gibt in diesem Raum keine Dateien - Füge zu Favoriten hinzu - Entferne von Favoriten + Zu Favoriten hinzufügen + Aus Favoriten entfernen Du hast keine Änderungen gemacht Du hast den Raum für alle, die den Link kennen, zugänglich gemacht. Du hast den Raumbeitritt auf Einladungen beschränkt. @@ -1622,9 +1622,9 @@ Versehentliche Anrufe verhindern Bitte um Bestätigung, bevor du einen Anruf tätigst Einrichten - Dir fehlt die Berechtigung in diesem Raum eine Konferenz zu starten - Beginne eine Videokonferenz - Beginne eine Audiokonferenz + Du bist nicht berechtigt, in diesem Raum ein Konferenzgespräch zu starten + Videokonferenz starten + Audiokonferenz starten Konferenzen nutzen die Jitsi-Sicherheits- und Berechtigungsrichtlinien. Alle im Raum Anwesenden können während der Konferenz beitreten. Du kannst dich nicht selbst anrufen Du kannst dich nicht selbst anrufen, warte bis Teilnehmer die Einladung annehmen @@ -1670,7 +1670,7 @@ Umfrage Reagierte mit: %s Der Link war fehlerhaft - Du bist nicht berechtigt, einen Anruf in diesem Raum zu beginnen + Du bist nicht berechtigt, in diesem Raum einen Anruf zu beginnen Ergebnis der Überprüfung Kontodaten vom Typ %1$s löschen\? \n @@ -1681,8 +1681,8 @@ Die Applikation wartet auf den PUSH Push testen Gebannte Nutzer filtern - Du bist nicht berechtigt einen Anruf zu beginnen - Du hast keine Berechtigung ein Konferenzgespräch zu starten + Du bist nicht berechtigt, einen Anruf zu beginnen + Du bist nicht berechtigt, ein Konferenzgespräch zu starten Details wie Raumnamen und Nachrichteninhalt zeigen. Inhalt in Benachrichtigungen anzeigen PIN-Code ist die einzige Möglichkeit ${app_name} zu entsperren. @@ -1729,11 +1729,11 @@ Nur die Anzahl ungelesener Nachrichten in der Benachrichtigung zeigen. Füge Bild hinzu per Der Raum ist noch nicht erstellt. Raumerstellung abbrechen\? - Zu niedrige Priorität hinzufügen + Zu niedriger Priorität hinzufügen Thema Änderungen verwerfen Es gibt ungespeicherte Änderungen. Änderungen verwerfen\? - Von niedrige Priorität entfernen + Aus niedriger Priorität entfernen Rotieren und Zuschneiden Raumeinstellungen Raumthema (optional) @@ -2026,7 +2026,7 @@ Die Datei ist zu groß. Video wird komprimiert (%d%%) - Komprimiere Bild … + Bild komprimieren … Als Standard festsetzen und nicht mehr fragen Jedes Mal fragen Gib den Namen des neuen Servers ein, den du erkunden möchtest. @@ -2128,9 +2128,9 @@ %d verpasste Sprachanrufe Heim-Server-API-Adresse - Um Sprachnachrichten zu senden, erlaube bitte Zugriff aufs Mikrofon. - Um fortzufahren, erlaube bitte in den Systemeinstellungen Zugriff auf die Kamera. - Für diese Aktion fehlen einige Berechtigungen, bitte erlaube diese in den Systemeinstellungen. + Um Sprachnachrichten zu senden, gewähre bitte den Zugriff aufs Mikrofon. + Um fortzufahren, gewähre bitte in den Systemeinstellungen den Zugriff auf die Kamera. + Für diese Aktion fehlen einige Berechtigungen, bitte gewähre diese in den Systemeinstellungen. Wische zum Abbrechen Spaces mit Zugriff auf Space-Mitgliedern Auffinden und Zugriff erlauben. @@ -2877,7 +2877,7 @@ %1$s beendete eine Sprachübertragung. Möchtest du die Übertragung wirklich beenden\? Dies wird die Übertragung beenden und die vollständige Aufnahme im Raum bereitstellen. Live-Übertragung beenden\? - Ja, beende + Ja, beenden Link setzen Link bearbeiten Link erstellen diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index fb5fd92f6b..4be2e46ce7 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -2958,4 +2958,12 @@ کاره به‌روز شد خروج به هر صورت نمی‌توان به کارساز خانگی رسید. اگر همچنان خارج شوید این افزاره از سیاههٔ افزاره‌هایتان پاک نخواهد شد و باید از کارخواهس دیگر برش دارید. + ناتوان در یافتن نمایه‌ها برای شناسه‌های ماتریکس سیاهه شده. می‌خواهید به هر حال دعوتشان کنید؟ +\n +\n%s + ناتوان در یافتن نمایه‌ها برای شناسه‌های ماتریکس سیاهه شده. می‌خواهید به هر حال گپی بیاغازید؟ +\n +\n%s + آغاز گپ به هر حال + دعوت به هر حال \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-lv/strings.xml b/library/ui-strings/src/main/res/values-lv/strings.xml index 4d7cb09b96..bf8d2054ed 100644 --- a/library/ui-strings/src/main/res/values-lv/strings.xml +++ b/library/ui-strings/src/main/res/values-lv/strings.xml @@ -659,7 +659,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Lūdzu, rakstiet savu ieteikumu zemāk. Ieteikumi Palīdzība un par lietotni - Drošība un konfidencialitāte + Drošība un privātums Vispārīgi Publiska Istabas iestatījumi @@ -1236,7 +1236,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Sākotnējā sinhronizācija: \nGaida servera atbildi… Pievienojiet speciālu cilni priekš nelasītiem paziņojumiem galvenajā ekrānā. - Ieslēgt pavilkšanas žestu, lai atbildētu uz ziņu + Laika joslā iespējot atbildēšanu pavelkot Labojumi netika atrasti Ziņu labojumi Rādīt pilnu vēsturi šifrētajās istabās @@ -1877,7 +1877,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Noklusējuma versija Istabu versijas 👓 Ziņu redaktors - Hronoloģija + Laika josla Šī sesija nevar kopīgot šo verifikāciju ar citām sesijām. \nVerifikācija tiks saglabāta lokāli un kopīgota kādā no nākamajām lietotnes versijām. ${app_name} saskārās ar problēmu, atveidojot notikuma ar id \'%1$s\' saturu @@ -1945,11 +1945,11 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Url: Sesijas attēlojamais nosaukums: Lietotnes attēlojamais nosaukums: - Iesūtīšanas atslēga: + Pašpiegādes atslēga: Lietotnes identifikators: - Nav reģistrētu Palaišanas vārtu - Nav iestatīti Palaišanas Noteikumi - Palaišanas Noteikumi + Nav norādītas pašpiegādes vārtejas + Nav norādīti pašpiegādes nosacījumi + Pašpiegādes nosacījumi Radīt jaunu Telpu Izskatās, ka mēģini izveidot savienojumu ar citu mājasserveri. Vai atteikties\? Paziņot mani priekš @@ -1988,9 +1988,9 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. \n%1$s Fona ierobežojumi ir izslēgti priekš ${app_name}. Šis tests jāveic, izmantojot mobilos datus (bez WIFI). \n%1$s - Neizdevās saņemt palaišanu. Iespējams, vajag pārielādēt lietotni. - Lietotne saņem Palaišanu - Lietotne gaida Palaišanu + Neizdevās saņemt pašpiegādi. Risinājums varētu būt atkārtota lietotnes uzstādīšana. + Lietotne saņem pašpiegādi + Lietotne gaida pašpiegādi Pārbaudīt pašpiegādi [%1$s] \nŠī kļūda ir ārpus ${app_name} kontroles. Tālrunī nav Google konta. Lūdzu, atveriet kontu pārvaldnieku un pievienojiet Google kontu. @@ -2054,8 +2054,8 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Atvērt aptauju Sniegt atgriezenisko saiti Piesist augšējā labajā stūrī, lai redzētu iespēju sniegt atgriezenisko saiti. - Tu beidzi balss pārraidi. - %1$s izbeidza balss pārraidi. + Tu beidzi balss apraidi. + %1$s izbeidza balss apraidi. Izmantot ierīci, kurā veikta pieteikšanās, lai nolasītu zemāk esošo kvadrātkodu: Nolasīt zemāk esošo kvadrātkodu ar ierīci, kurā ir notikusi atteikšanās. Pieteikties ar kvadrātkodu @@ -2132,7 +2132,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Rāda visus pavedienus, kuros ir notikusi iesaistīšanās Kopīgot ekrānu Izveidot tiešo ziņu tikai pēc pirmās ziņas - Izmēģināt bagātinātu teksta rakstīšanu (vienkārša teksta ievade būs drīzumā) + Izmēģināt bagātinātu teksta rakstīšanu (vienkārša teksta ievade gaidāma drīzumā) Nekā jauna. %1$s, %2$s un citi Visi pavedieni @@ -2200,7 +2200,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Pavedieni Beta %1$s un %2$s Palīdzēt uzlabot ${app_name} - Atskaņot kustīgos laikjoslas attēlus, tiklīdz tie ir redzami + Atskaņot kustīgos laika joslas attēlus, tiklīdz tie ir redzami ${app_name} ir nepieciešama atļauja, lai parādītu paziņojumus. \nLūgums piešķirt atļauju. @@ -2341,7 +2341,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Lūgums sazināties ar pārvaldītāju, lai atjaunotu šifrēšanu derīgā stāvoklī. Apstiprināt tālruņa numuru Šo saiti nevar atvērt: kopienas tika aizstātas ar vietām - Uzsāka balss pārraidi + Uzsāka balss apraidi Izlaist šo jautājumu Apliecina ar drošo atslēgu vai vārdkopu… Šifrēšana ir kļūdaini uzstādīta. @@ -2503,4 +2503,520 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Jāpārskata iestatījumi, lai iespējotu pašpiegādes paziņojumus Saglabāt atkopšanas atslēgu Uzstādīt + + %d ierakstu + %d ieraksts + %d ieraksti + + Aizsargāt piekļuvi + Iestatīt aizsardzību + Lai atiestatītu PIN, būs nepieciešams atkārtoti pieteikties un izveidot jaunu. + Neizdevās apstiprināt PIN, lūgums ievadīt jaunu. + Biometriskā autentificēšanās tika atspējota, jo nesen tika pievienots jauns biometriskās autentifikācijas veids. To var atkal iespējot iestatījumos. + Aizsargāt piekļuvi ar PIN un biometriju. + + Nepareizs kods, atlikuši %d mēģinājumu + Nepareizs kods, atlicis %d mēģinājums + Nepareizs kods, atlikuši %d mēģinājumi + + Pārāk daudz kļūdu, tādēļ tiki izrakstīts + Nevarēja iespējot biometrisko autentifikāciju. + Atvērt iestatījumus + Noklusējuma uzticamības līmenis + Ja ir vēlēšanas atiestatīt savu PIN, jāpiesit Aizmirsu PIN, lai atteiktos un atiesatītu. + Pieprasīt PIN pēc 2 minūtēm + Iepriekškonsultēšana + Nav satura + Nevar ierakstīt balss ziņu + Buferizācija… + Brīdinājuma uzticamības līmenis + ${app_name} pieprasa ievadīt piekļuves datus, lai veiktu šo darbību. + ir nenosūtīts melnraksts + Izpētīt istabas stāvokli + Uzticams uzticamības līmenis + Atzīmēts + Nosūtīt pielāgotu notikumu + Labot saturu + Nosūtīt pielāgotu stāvokļa notikumu + Trūkst ziņas veida + Stāvokļa notikums ir nosūtīts. + Notikuma saturs + Dažas vietas var būt paslēptas, jo tās ir privātas un ir nepieciešams uzaicinājums uz tām. + Jūtams izmēģinājuma gars\? +\nVietai ir iespējams pievienot esošas vietas. + Nevar atbildēt vai labot, kamēr tiek izmantota balss ziņa + Apturēt %1$s + %1$s (%2$s) + (%1$s) + Jaunināt + Atlikušas %1$d s + + %1$d notiekošu zvanu · + %1$d notiekošs zvans · + %1$d notiekoši zvani · + + Nav atzīmēts + Izstrādātāja rīki + Atklājamība (%s) + Pievienot esošas vietas + Pievienot vietu jebkurai sevis pārvaldītai vietai. + Piezīme: lietotne tiks pārsāknēta + Parādīt jaunāko lietotāja informāciju + Atskaņot balss ziņu + Apturēt balss ziņu + Balss ziņa (%1$s) + Tiešraide + Atsākt balss apraides ierakstu + Konsultējas ar %1$s + Slidināt, lai atceltu + Pārtraukt balss apraides ierakstu + Pārvirzīt + Paziņot ar skaņu + Dažas ziņas netika nosūtītas + %s uzaicina Tevi + Automātiski uzaicināt vietas vecākvienumu + Atvainojamies, atgadījās kļūda pievienošanās mēģinājuma laikā: %s + Ievietot atslēgu no datnes + Nosūtīt stāvokļa notikumu + Nepareizi veidots notikums + Atzīmēt kā neieteikto + Ierakstīt balss ziņu + Tiešraides apraide + Automātiski uzaicināt lietotājus + Aizņemts + Atjaunina istabu uz jaunu versiju + + Jau pievienojušies %d zināmu cilvēku + Jau pievienojies %d zināms cilvēks + Jau pievienojušies %d zināmi cilvēki + + Notikuma saturs + Šī istaba tiks jaunināta no %1$s uz %2$s. + Atzīmēt kā ieteikto + Rādīt saturu paziņojumos + Rādīt, piemēram, istabu nosaukumus un ziņas saturu. + Attēlot tikai neizlasīto ziņu skaitu vienkāršā paziņojumā. + Nevar atvērt istabu, no kuras esi izslēgts. + Pārvirzīt uz %1$s + Nepieciešama atkārtota autentificēšanās + Stāvokļa notikumi + Pašlaik šis aizstājvārds nav pieejams. +\nVēlāk jāmēģina vēlreiz vai jāvaicā istabas pārvaldītājam, lai pārbauda, vai Tev ir piekļuve. + Pašlaik netiek izmantots identitātes serveris. Lai varētu uzaicināt komandas biedrus un būtu tiem atklājams, jāiestata tāds zemāk. + Nebūs iespējams atkārtoti pievienoties bez uzaicinājuma. + Nekas netika atrasts + Automātiski ziņot par atšifrēšanas kļūdām. + Sistēma automātiski nosūtīts žurnāla ierakstus, kad notiks kļūda \"nav iespējams atšifrēt\" + Iespējot no ierīces atkarīgu biometriju, piemēram, pirkstu nospiedumus un sejas atpazīšanu. + PIN kods tiks pieprasīts pēc 2 minūšu ${app_name} neizmantošanas. + PIN kods tiek pieprasīts katrā ${app_name} atvēršanas reizē. + Notika kļūda zvana pārvirzīšanas laikā + Paziņot bez skaņas + Notikums ir nosūtīts. + Neizdevās + Tu esi vienīgais šīs vietas pārvaldītājs. Tās atstāšana nozīmē, ka neviens to nepārvaldīs. + Iespējot pavedienu ziņas + Meklē kādu, kurš nav %s\? + Ieteiktā + Istaba bez nosaukuma + Nepieciešams jauninājums + Jaunināt privāto istabu + Ir nepieciešama atļauja, lai jauninātu istabu + Apturēt ierakstīšanu + Ieraksta balss ziņu + Nevar uzsākt balss ziņu + %1$s, %2$s, %3$s + Atskaņot %1$s + Parādīt jaunāko profila informāciju (attēlu un attēlojamo vārdu) visām ziņām. + Lūgums paciesties, tas var aizņemt kādu laiku. + Istabas jaunināšana ir sarežģīta darbība un parasti ir ieteicama, kad istaba ir nepastāvīga kļūdu, trūkstošu iespēju vai drošības ievainojamību dēļ. +\nTas parasti tikai ietekmē to, kā istaba tiek apstrādāta serverī. + Jaunināt uz ieteicamo istabas versiju + Jāpiesit ierakstam, lai klausītos vai apturētu + Nevar uzsākt balss ziņu, jo pašreiz tiek ierakstīta tiešraides apraide. Lūgums to pārtraukt, lai varētu uzsākt balss ziņas ierakstīšanu + Apturēt balss apraides ierakstu + Nevar atskaņot šo balss ziņu + Ziņa nav nosūtīta kļūdas dēļ + Kopīgot ar tekstu + Iespējot biometriju + Pabeigt iestatīšanu + Pievienoties aizvietotājistabai + Nepaziņot + Pabeigt atklājamības izveidošanu. + Tu esi uzaicināts + Jaunināt publisko istabu + %1$d minūtes %2$d sekundes + Nespēj atskaņot %1$s + PIN kods ir vienīgais veids, kā atslēgt ${app_name}. + Uzaicināt e-pastā, atrast kontaktus un vēl… + Stāvokļa atslēga + Lietas šajā vietā + Atvērt ar + Attēlo aptaujas + Kopīgot atrašanās vietu tiešraidē + Aptaujas jautājums vai temats + Kopīgot šo atrašanās vietu + Sasaistīt šo e-pasta adresi ar kontu + + Pamatojoties uz %1$d balsojumiem + Pamatojoties uz %1$d balsojumu + Pamatojoties uz %1$d balsojumiem + + IZVEIDOT APTAUJU + Nav saņemti balsojumi + Noslēgt šo aptauju\? + Nevar uzsākt jaunu balss apraidi + Atskaņot vai atsākt balss apraidi + Ātri patīt 30 sekundes atpakaļ + Ātri patīt 30 sekundes uz priekšu + Kāds cits jau ieraksta balss apraidi. Jāgaida, līdz tā beigsies, lai varētu uzsākt jaunu. + Vai tiešām pārtraukt tiešraides apraidi\? Tas izbeigs apraidi, un istabā būs pieejams viss ieraksts. + Šis uzaicinājums uz šo vietu tika nosūtīts uz %s, kas nav saistīts ar Tavu kontu + Iespējot LaTeX matemātiku + Jautājums vai temats + Jautājums nevar būt tukšs + + Saņemti %1$d balsojumu. Jābalso, lai redzētu iznākumu + Saņemts %1$d balsojums. Jābalso, lai redzētu iznākumu + Saņemti %1$d balsojumi. Jābalso, lai redzētu iznākumu + + + Galīgais iznākums, pamatojoties uz %1$d balsojumiem + Galīgais iznākums, pamatojoties uz %1$d balsojumu + Galīgais iznākums, pamatojoties uz %1$d balsojumiem + + Aptauja noslēgta + Labot aptauju + Noslēdza aptauju. + Ielādēt vairāk aptauju + Kļūda aptauju izgūšanā. + Pietuvināt līdz pašreizējai atrašanās vietai + 15 minūtes + Atrašanās vietas tiešraide + Tu jau ieraksti balss apraidi. Lūgums pabeigt pašreizējo, lai uzsāktu jaunu. + Tas vairs neļaus cilvēkiem balsot, un tiks attēlots aptaujas galīgais iznākums. + Aptaujas veids + Balsotāji redz iznākumu, tiklīdz viņi ir nobalsojuši + Atrašanās vietas tiešraide iespējota + Atrašanās vietas tiešraide beidzās + Atjaunota pirms %1$s + Atšifrēšanas kļūdu dēļ daži balsojumi var netikt ieskaitīti + Kopīgot šo atrašanās vietu + Piespraust atlasīto atrašanās vietu kartē + Apskatīt atrašanās vietas tiešraidi + Atvērt kameru + Nosūtīt attēlus un video + Tiešraidē līdz %1$s + Karte + ${app_name} nevarēja piekļūt atrašanās vietai + Apturēt balss apraidi + Iznākums būs redzams, kad aptauja būs beigusies + Aizvērta aptauja + Atlicis %1$s + MSC3061: istabu atslēgu kopīgošana pagātnes ziņām + Saņemtais balsojums + Noņemt aptauju + 8 stundas + Noslēgt aptauju + Pārtraukt + Pārtraukt tiešraides apraidi\? + Izveidot aptauju + Šajā istabā nav noslēgto aptauju + 1 stundu + Neizdevās ielādēt karti + Iespējot atrašanās vietas tiešraides kopīgošanu + Noslēgt aptauju + Nav iespējams atšifrēt šo balss apraidi. + Lietotne ir jāpārsāknē, lai izmaiņas stātos spēkā. + Vai tiešām noņemt šo aptauju\? To pēc noņemšanas vairs nevarēs atgūt. + Šajā istabā nav notiekošu aptauju + Noslēgušās aptaujas + Kopīgot manu pašreizējo atrašanās vietu + Kopīgot atrašanās vietu tiešraidē + Nepieciešamas atbilstošas atļaujas, lai šajā istabā varētu kopīgot atrašanās vietas tiešraidi. + Atrašanās vieta + Kopīgot manu pašreizējo atrašanās vietu + Kopīgot atrašanās vietu tiešraidē + Nebija iespējams ielādēt karti +\nŠis mājasserveris var nebūt iestatīts, lai attēlotu kartes. + Kopīgot atrašanās vietu + Notiekošās aptaujas + + Iepriekšējās %1$d dienās nav noslēgto aptauju. +\nJāielādē vairāk aptauju, lai apskatītu iepriekšējo dienu aptaujas. + Iepriekšējā dienā nav noslēgto aptauju. +\nJāielādē vairāk aptauju, lai apskatītu iepriekšējo dienu aptaujas. + Iepriekšējās %1$d dienās nav noslēgto aptauju. +\nJāielādē vairāk aptauju, lai apskatītu iepriekšējo dienu aptaujas. + + ${app_name} nevarēja piekļūt atrašanās vietai. Lūgums vēlāk mēģināt vēlreiz. + Nav nepieciešamo atļauju, lai uzsāktu balss apraidi šajā istabā. Jāsazinās ar istabas pārvaldītāju, lai paaugstinātu atļaujas. + + Iepriekšējās %1$d dienās nav notiekošu aptauju. +\nJāielādē vairāk aptauju, lai redzētu iepriekšējo dienu aptaujas. + Iepriekšējā dienā nav notiekošu aptauju. +\nJāielādē vairāk aptauju, lai redzētu iepriekšējo dienu aptaujas. + Iepriekšējās %1$d dienās nav notiekošu aptauju. +\nJāielādē vairāk aptauju, lai redzētu iepriekšējo dienu aptaujas. + + Apskatīt aptauju laika joslā + Ielādē atrašanās vietas tiešraidi… + Nav iespējams atskaņot šo balss apraidi. + Kopīgot atrašanās vietu + ${app_name} atrašanās vietas tiešraide + Savienojuma kļūda - ierakstīšana apturēta + Notiek atrašanās vietas kopīgošana + Atlicis %1$s + Pagaidu īstenojums: atrašanās vietas ir paliekošas istabas vēsturē + Ikviens no %s varēs atrast šo istabu un pievienoties tai - nav nepieciešams pašrocīgi visus uzaicināt. To jebkurā laikā būs iespējams mainīt istabas iestatījumos. + Nav atļaujas kopīgot atrašanās vietas tiešraidi + Ikviens vecākvietā varēs atrast šo istabu un pievienoties tai - nav nepieciešams pašrocīgi visus uzaicināt. To jebkurā laikā ir iespējams mainīt istabas iestatījumos. + Lūgums ņemt vērā, ka jaunināšana izveidos jaunu istabas versiju. Visas pašreizējās ziņas paliks šajā arhivētajā istabā. + Rādīt ziņu burbuļus + Šis uzaicinājums uz šo istabu tika nosūtīts uz %s, kas nav saistīta ar Tavu kontu + %s iestatījumos, lai saņemtu uzaicinājumus tieši ${app_name}. + Kad uzaicina šifrētā istabā, kas kopīgo vēsturi, būs redzama šifrētā vēsture. + + %1$d balsojumu + %1$d balsojums + %1$d balsojumi + + Iznākums tiek atklāts tikai pēc aptaujas noslēgšanas + Aptaujas + Kamera + Galamērķis + Atteikties + + Atteikties no %1$d sesijām + Atteikties no %1$d sesijas + Atteikties no %1$d sesijām + + Parādīt IP adresi + Paslēpt IP adresi + Nosaukums + Sesijas nosaukums + Neapliecinātās sesijas + + Vēl %1$d + Vēl %1$d + Vēl %1$d + + Sesiju pārdēvēšana + Atteikties no šīs sesijas + Augšupielādēt datni + Izveidot aptauju + Balss apraide + Rādīt mazāk + Istabas paziņojums + ${app_name} ekrāna kopīgošana + Netika atrasts neviens cits veids bez sinhronizēšanas fonā. + Pašreizējais galamērķis: %s + Vārteja + Nezināms apliecinājuma stāvoklis + Apskatīt visas (%1$d) + Jāapliecina vai jāatsakās no neapliecinātām sesijām. + Gatavas drošai ziņapmaiņai + Nav gatavas drošai ziņapmaiņai + Vislabākajai drošībai jāatsakās no jebkuras neatpazīstamas vai vairs neizmantotas sesijas. + Jāapliecina savas sesijas paplašinātai drošajai ziņapmaiņai vai jāatsakās no tām, kas nav atpazīstamas vai vairs netiek izmantotas. + Informācija par lietotne, ierīci un darbībām. + Operētājsistēma + Apliecinātas sesijas + Notiek ekrāna kopīgošana + Automātiski apstiprināt Element zvanu logrīkus un piešķirt piekļuvi kamerai/mikrofonam + Atlase + Neapliecinātas + Lietotne + Neapliecināta sesija + Pieejamie veidi + Sesija + Apliecinātas sesijas netika atrastas. + Pārdēvēt sesiju + Izvēlēties, kā saņemt paziņojumus + Google pakalpojumi + + Noņemtas %d ziņu + Noņemta %d ziņa + Noņemtas %d ziņas + + Jāapliecina pašreizējā sesija paplašinātai drošajai ziņapmaiņai. + Atvērt kontaktus + Tālrunis + Sesijas izvērsums + Teksta formatēšana + Iekārta + Sesijas nosaukums + Atrašanās vieta + Veids + Uzlabo sava konta drošību ievērojot šos ieteikumus. + Pārlūks + Pieteikties ar kvadrātkodu + Apliecināt sesiju + Atlasīt + Kopīgot atrašanās vietu + Uzsākt balss apraidi + Kontakts + Paziņot visai istabai + Lietotāji + Sinhronizēšana fonā + Paziņojuma veids + Nevar atrast galamērķi. + Atrašanās vietas tiešraides kopīgošana + Citas sesijas + Tīmeklis + Darbvirsma + Šī sesija ir gatava drošai ziņapmaiņai. + Neapliecināta · Pēdējā darbība %1$s + + Neizmantota %1$d+ dienas (%2$s) + Neizmantota %1$d+ dienu (%2$s) + Neizmantota %1$d+ dienas (%2$s) + + Neapliecinātas sesijas + Pēdējā darbība + Versija + Lūgums ņemt vērā, ka sesiju nosaukumi ir redzami arī cilvēkiem, ar kuriem sazinies. + Pašreiz tiek izmantots %s. + Jāapliecina pašreizējā sesija, lai atklātu šīs sesijas apliecinājuma stāvokli. + Visas sesijas + Drošības ieteikumi + Pašreizējā sesija + Notīrīt atlasi + Nosūtīt uzlīmi + Attēlu bibliotēka + Uzlīmes + Pielikumi + Netika atrasts neviens cits veids bez Google Play pakalpojuma. + + Atrasti %d veidu. + Atrasts %d veids. + Atrasti %d veidi. + + Pašreizējā vārteja: %s + Nezināms ierīces veids + Apskatīt izvērsumu + Neizmantotas sesijas + Apliecinātas + Neizmantotas + Apliecinātas + Neizmantotas sesijas netika atrastas. + Atlasīt sesijas + Atteikties no visām pārējām sesijām + IP adrese + URL + Modelis + Neizmantotās sesijas + Neapliecinātās sesijas ir sesijas, kurās ir notikusi pieteikšanās ar Taviem datiem, bet nav starpapliecinātas. +\n +\nVajadzētu īpaši pārliecināties, ka šīs sesijas ir atpazīstamas, jo tās var norādīt uz nepilnvarotu konta izmantošanu. + Iespējot atrašanās vietas kopīgošanu + + Jāapsver atteikšanās no vecajām sesijām (%1$d dienu vai vairāk), kas vairs netiek izmantotas. + Jāapsver atteikšanās no vecajām sesijām (%1$d diena vai vairāk), kas vairs netiek izmantotas. + Jāapsver atteikšanās no vecajām sesijām (%1$d dienas vai vairāk), kas vairs netiek izmantotas. + + Iespējot Element zvanu atļauju īsceļus + Pēdējā darbība %1$s + Vislielākajai drošībai jāapliecina savas sesijas un jāatsakās no jebkuras neatpazītas vai neizmantotas sesijas. + Neapliecinātas + Apliecināta sesija + Pašreizējā sesija ir gatava drošai ziņapmaiņai. + Vislabākajai drošībai un uzticamībai jāapliecina šī sesija vai jāatsakās no tās. + + Neizmantotas %1$d dienu vai ilgāk + Neizmantotas %1$d dienu vai ilgāk + Neizmantotas %1$d dienas vai ilgāk + + Šī sesija nenodrošina šifrēšanu, tādēļ to nevar apliecināt. + Neizmantotas + Apliecināta · Pēdējā darbība %1$s + + Jāapsver atteikšanās no vecajām sesijām (%1$d dienu vai vairāk), kas vairs netiek izmantotas. + Jāapsver atteikšanās no vecajām sesijām (%1$d diena vai vairāk), kas vairs netiek izmantotas. + Jāapsver atteikšanās no vecajām sesijām (%1$d dienas vai vairāk), kas vairs netiek izmantotas. + + Neapliecināta · Pašreizējā sesija + Neapliecinātas sesijas netika atrastas. + Pielāgoti sesiju nosaukumi var palīdzēt vieglāk atpazīt savas ierīces. + Tu vari izmanto šo ierīci, lai pieteiktos tālruņa vai tīmekļa ierīcē ar kvadrātkodu. Ir divi veidi, kā to izdarīt: + Neizmantotās sesijas ir sesijas, kas kādu laiku nav izmantotas, bet tās turpina saņemt šifrēšanas atslēgas. +\n +\nNeizmantotas sesijas noņemšana uzlabo drošību un veiktspēju un ir vieglāk noteikt, vai jauna sesija ir aizdomīga. + Ziņa + Otrā ierīcē ir jāpiesakās. + Iestatīt saiti + Padara iespējamu ierakstīt un nosūtīt balss apraidi istabas laika joslā. + Šeit tiks parādītas nelasītās ziņas, kad tādas būs. + Apstiprināt + Ziņa %s + Nav nekā, par ko ziņot. + Jādodas uz Iestatījumi -> Drošība un privātums + Piesakies mobilajā ierīcē\? + Pielietot slīprakstu + nosūtīja video. + Sasaistīšana ar šo ierīci nav nodrošināta. + Jāatlasa \'Nolasīt kvadrātkodu\' + izveidoja aptauju. + Izveidots drošs savienojums + Neveiksmīgs savienojums + Savienojas ar ierīci + Piesakās + Pārslēgt numurētu sarakstu + Pielietot iekļautu kodu + Pārslēgt koda bloku + nosūtīja skaņas datni. + Piekļuves pilnvara sniedz pilnu piekļuvi kontam. To nevajag kopīgot ne ar vienu. + Laipni lūdzam jaunajā skatā! + Jāatlasa \'Parādīt kvadrātkodu\' + Jāsāk pieteikšanās skatā + Rādīt kvadrātkodu šajā ierīcē + Nav atbilstības\? + Jāmēģina vēlreiz + Pielietot pasvītrojumu + Iespējot jauno sesiju pārvaldnieku + Laipni lūdzam ${app_name}, +\n%s! + Pielietot treknrakstu + nosūtīja attēlu. + Pārslēgt vienkāršu sarakstu + Teksts + Iespējot klienta informācijas ierakstīšanu + Piekļūt vietām + Pieprasījums neizdevās. + Pārslēgt pilnekrānu + %s +\nizskatās mazliet tukša. + Sasaistīšana netika pabeigta nepieciešamajā laikā. + Jāatver lietotne otrā ierīcē + Jāsāk pieteikšanās skatā + Saite + Labot saiti + nosūtīja balss ziņu. + noslēdza aptauju. + Aptauja + Ziņa istabā + Noslēgtās aptaujas + Iegūsti labāku pārredzamību un pārraudzību pār visām savām sesijām! + Iespējot balss apraidi + Otrā ierīcē jau ir pieteikšanās. + Ievietot atkāpi + Noņemt atkāpi + Pārslēgt citātu + Izveidot saiti + Piekļuves pilnvara + Šis kvadrātkods ir nederīgs. + Pieteikšanās tika atcelta otrā ierīcē. + Jāatlasa \'Pieteikties ar kvadrātkodu\' + Pielietot pārsvītrojumu + Atbildē uz + nosūtīja datni. + nosūtīja uzlīmi. + Ziņa no %s + Istaba/vieta + Ierakstīt klienta nosaukumu, versiju un URL, lai sesiju pārvaldniekā vieglāk atpazītu sesijas. + Piekļūsti savām vietām (apakšējā labajā stūrī) ātrāk un vienkāršāk kā jebkad iepriekš! + Jāpārbauda ierīce, kurā esi pieteicies, tajā vajadzētu būt attēlotam zemāk redzamajam kodam. Jāapstiprina, ka zemāk esošais kods saskan ar to, kas ir ierīcē: + Pieprasījums tika atteikts otrā ierīcē. + Nolasīt kvadrātkodu + Lūgums nodrošināt, ka šī koda izcelsme ir zināma. Ar ierīču sasaistīšanu kādam tiks nodrošināta pilna piekļuve kontam. \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml index ee6431ea3f..c1ae3cde51 100644 --- a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml +++ b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml @@ -2909,4 +2909,53 @@ Terminar sessão ainda assim Verificação a partir de Chave ou Frase Segura… Até que este utilizador confie nesta sessão, as mensagens enviadas para e a partir dela são marcadas com avisos. + Mensagem na sala + Alternar lista numerada + Votações ativas + Ver votação na linha do tempo + Devido a erros de descriptografia, alguns votos podem não serem contados + A mensageria segura fora aprimorada com a atualização mais recente. Verifique novamente seu dispositivo. + Votação encerrada. + Votações anteriores + Alternar lista de marcadores + Sala/Espaço + Aguardando os usuários entrarem no ${app_name} + Assim que os usuários convidados entrarem no ${app_name}, vocês poderão conversar e a sala terá criptografia de ponta a ponta + Não há votação ativa nesta sala + Não há votações anteriores nesta sala + Votação encerrada + Prossiga apenas se você tem certeza que você perdeu todos os outros dispositivos e sua chave de segurança. + Criptografado por um dispositivo apagado + Remover recuo + Alternar aspas + Aplicar formatação de código em linha + Prosseguir + O pedido de verificação não foi encontrado. Ele pode ter sido cancelado ou tratado por outra sessão. + Recuar + Alternar bloco de código + terminou uma votação. + Votação + Token de acesso + Você não pode iniciar uma mensagem de voz porque está gravando uma transmissão ao vivo. Termine sua transmissão ao vivo para iniciar uma mensagem de voz + + Não há votação anterior para antes de ontem. +\nCarregue mais votações para ver as votações dos dias anteriores. + Não há votação anterior para os últimos %1$d dias. +\nCarregue mais votações para ver as votações dos dias anteriores. + + + Não há votação ativa para antes de ontem. +\nCarregue mais votações para ver as votações dos dias anteriores. + Não há votação ativa para os últimos %1$d dias. +\nCarregue mais votações para ver as votações dos dias anteriores. + + Carregar mais votações + Erro ao buscar votações. + Seu token de acesso fornece acesso completo à sua conta. Não o compartilhe com outras pessoais. + Mensagem de %s + A redefinição de suas chaves de verificação não pode ser desfeita. Após a redefinição, você não terá acesso às mensagens criptografadas antigas e todos os amigos que fizeram a verificação anteriormente verão avisos de segurança até que você faça a verificação novamente com eles. + Não foi possível iniciar a mensagem de voz + Exibindo votações + Mensagem + Mensagem em %s \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-ru/strings.xml b/library/ui-strings/src/main/res/values-ru/strings.xml index dad51116e5..bd1f8b7992 100644 --- a/library/ui-strings/src/main/res/values-ru/strings.xml +++ b/library/ui-strings/src/main/res/values-ru/strings.xml @@ -3060,4 +3060,5 @@ Блок кода Подпункт Пункт + Политика пользования \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-sq/strings.xml b/library/ui-strings/src/main/res/values-sq/strings.xml index f79d418453..171da1d9d9 100644 --- a/library/ui-strings/src/main/res/values-sq/strings.xml +++ b/library/ui-strings/src/main/res/values-sq/strings.xml @@ -2945,4 +2945,13 @@ Aplikacioni u përditësua Dil, sido qoftë S’kapet dot shërbyesi Home. Nëse keni dalë, sido qoftë, kjo pajisje s’do të fshihet te lista e pajisjeve tuaja, mund të doni ta hiqni duke përdorur klient tjetër. + S’arrihet të gjenden profile për ID-rat Matrix të radhitura më poshtë. Do të donit të fillohej një fjalosje, sido që të jetë\? +\n +\n%s + Aktivizo ndarje të drejtpërdrejtë me të tjerët + Fillo fjalosje, sido që të jetë + S’arrihet të gjenden profile për ID-rat Matrix të radhitura më poshtë. Do të donit të ftohen, sido qoftë\? +\n +\n%s + Ftoji, sido qoftë \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-sv/strings.xml b/library/ui-strings/src/main/res/values-sv/strings.xml index 3ec7b60778..7991793f85 100644 --- a/library/ui-strings/src/main/res/values-sv/strings.xml +++ b/library/ui-strings/src/main/res/values-sv/strings.xml @@ -2958,4 +2958,12 @@ App uppdaterad Kan inte nå hemservern. Om du ändå loggar ut kommer den här enheten inte att raderas från din enhetslista, du kanske vill ta bort den med en annan klient. Logga ut ändå + Kunde in hitta profiler för Matrix-ID:n nedan. Vill du starta en chatt ändå\? +\n +\n%s + Starta chatt ändå + Kunde inte hitta profiler för Matrix-ID:n nedan. Vill du bjuda in dem ändå\? +\n +\n%s + Bjud in ändå \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-tr/strings.xml b/library/ui-strings/src/main/res/values-tr/strings.xml index 1f0e5be153..470bd98935 100644 --- a/library/ui-strings/src/main/res/values-tr/strings.xml +++ b/library/ui-strings/src/main/res/values-tr/strings.xml @@ -1734,4 +1734,32 @@ Konuları Görüntüle Başlangıç eşitleme isteği Tüm Sohbetler - + Sohbet Başlat + %1$s bir ses yayınını sonlandırdı. + Bir sesli yayını sonlandırdınız. + Oda yarat + Odaları keşfedin + ${app_name}, aşağıdaki nedenden dolayı güncel olması için önbelleği temizlemelidir: +\n %s +\n +\n Bu eylemin uygulamayı yeniden başlatacağını ve biraz zaman alabileceğini unutmayın. + - Bazı kullanıcılar göz ardı edildi + %s çocuğu genişlet + dk. + Devre dışı bırak + sa. + Alanı Değiştir + Yine de oturumu kapat + + %1$d seçildi + %1$d seçildi + + %1$s görünen adını %2$s olarak değiştirdi + Ana sunucuya ulaşılamıyor. Yine de çıkış yaparsanız, bu cihaz, cihaz listenizden silinmez, başka bir istemci kullanarak kaldırmak isteyebilirsiniz. + + %d sunucu ACL\'si değişti + %d sunucu ACL değişikliği + + s. + %s çocuğu daralt + \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-uk/strings.xml b/library/ui-strings/src/main/res/values-uk/strings.xml index a621db40b6..49b3f2e2dd 100644 --- a/library/ui-strings/src/main/res/values-uk/strings.xml +++ b/library/ui-strings/src/main/res/values-uk/strings.xml @@ -57,7 +57,7 @@ Ви змінили назву кімнати на: %1$s Ви змінили аватар кімнати Ви змінили тему на: %1$s - Ви змінили показуване ім\'я з %1$s на %2$s + Ви змінили псевдонім з %1$s на %2$s Ви змінили свій аватар %1$s, %2$s, %3$s та %4$d інший @@ -85,7 +85,7 @@ Ви починаєте голосовий виклик. Ви починаєте відеовиклик. %1$s змінює аватар кімнати - Ви прибрали показуване ім\'я (%1$s) + Ви вилучили псевдонім (%1$s) Ви вилучили %1$s %1$s запрошує %2$s Ви відхилили запрошення @@ -137,7 +137,7 @@ Ви відповіли на виклик. Ви надіслали дані для налаштування виклику. %s надсилає дані для налаштування виклику. - Ви встановили собі показуване ім\'я %1$s + Ви налаштували псевдонімом %1$s Ви відкликали запрошення для %1$s Ви заблокували %1$s Ви заблокували %1$s @@ -268,7 +268,7 @@ Фільтр переліку користувачів Тут порожньо Аватар - Показуване ім\'я + Псевдонім Додати адресу е-пошти Додати номер телефону Екран системної інформації застосунку. @@ -276,7 +276,7 @@ Тон сповіщення Увімкнути сповіщення для цього облікового запису Увімкнути сповіщення для цього пристрою - Повідомлення, що містять моє показуване ім\'я + Повідомлення з моїм псевдонімом Повідомлення, що містять моє ім\'я користувача В особистих чатах У групових чатах @@ -495,7 +495,7 @@ Вийти з кімнати Встановити тему кімнати Вилучити користувача із вказаним ID - Змінити Ваш псевдонім + Змінити псевдонім Увімкнути/Вимкнути розмітку Markdown Для виправлення керування застосунками Matrix Створити @@ -816,7 +816,7 @@ Ваша тема Ваш ідентифікатор користувача URL-адреса аватара - Ваше показуване ім\'я + Ваш псевдонім Скасувати доступ для мене Відкрити у браузері Перезавантажити віджет @@ -1564,7 +1564,7 @@ Зашифровані групові повідомлення Групові повідомлення Моє користувацьке ім\'я - Моє показуване ім\'я + Мій псевдонім Повідомлення, які містять @room Коли кімнати оновлено Зашифровані повідомлення в групових бесідах @@ -2060,7 +2060,7 @@ Показує відомості про користувача Змінює ваш аватар лише у поточній кімнаті Змінює аватар поточної кімнати - Змінює ваше показуване ім\'я лише у поточній кімнаті + Змінює ваш псевдонім лише у поточній кімнаті Установлює назву кімнати Сервер ідентифікації не надав жодних правил Бажаєте поекспериментувати\? @@ -2408,7 +2408,7 @@ Відкрити камеру Ваша система автоматично надсилатиме журнали, коли виникне помилка неможливості розшифрування Автозвіт про помилки шифрування. - Замінити колір показуваного імені + Замінити колір псевдоніма Я вже маю обліковий запис Захищене спілкування. Ви контролюєте все. @@ -2517,8 +2517,8 @@ Час вказати ім’я Додати зображення профілю Ви можете змінити його пізніше - Показуване ім\'я - Виберіть показуване ім\'я + Псевдонім + Оберіть псевдонім Ваш обліковий запис %s створений Вітаємо! На головну @@ -2562,7 +2562,7 @@ \n \nЗауважте, що ця дія перезапустить застосунок, і це може тривати деякий час. Початковий запит синхронізації - Показувати найновіші дані профілю (аватар і показуване ім\'я) для всіх повідомлень. + Показувати найновіші дані профілю (аватар і псевдонім) для всіх повідомлень. Показувати найновіші дані користувача Зайнятий Резервна копія має дійсний підпис від цього користувача. diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index d7f2c07a08..a487fe22ce 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2554,4 +2554,6 @@ Phiên Thiết bị Hoạt động cuối %1$s + Tiếp tục + Bận \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml index 9abc3b25e4..30fba77195 100644 --- a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml @@ -654,7 +654,7 @@ 设置静音通知 选择LED颜色、震动、铃声…… 加密密钥管理 - 恢复已加密消息 + 已加密消息恢复 管理密钥备份 静音 请输入一个用户名。 diff --git a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml index 8c51b44395..e3593d61c7 100644 --- a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml @@ -748,7 +748,7 @@ 備份 除非您在登出前備份好金鑰,否則將無法再存取所有加密訊息。 您確定要登出嗎? - 還原加密訊息 + 加密訊息還原 請輸入使用者名稱。 開始使用金鑰備份 (進階) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 6b29e56d77..63fb13ead8 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -63,7 +63,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.6.5\"" + buildConfigField "String", "SDK_VERSION", "\"1.6.6\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" @@ -216,7 +216,7 @@ dependencies { implementation libs.google.phonenumber - rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.10") + rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.15") // rustCryptoApi project(":library:rustCrypto") testImplementation libs.tests.junit diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeShareKeysHistoryTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeShareKeysHistoryTest.kt index 700f912cf1..fc1b5bba93 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeShareKeysHistoryTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeShareKeysHistoryTest.kt @@ -28,6 +28,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.runners.MethodSorters +import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session @@ -196,6 +197,7 @@ class E2eeShareKeysHistoryTest : InstrumentedTest { @Test fun testNeedsRotationFromSharedToWorldReadable() { + Assume.assumeTrue("Test is flacky on legacy crypto", BuildConfig.FLAVOR == "rustCrypto") testRotationDueToVisibilityChange(RoomHistoryVisibility.SHARED, RoomHistoryVisibilityContent("world_readable")) } diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt index 7f4f4aee88..24591e8bd4 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt @@ -136,6 +136,13 @@ internal class SecretShareManager @Inject constructor( .w("handleSecretRequest() : malformed request norequestingDeviceId ") } + if (deviceId == credentials.deviceId) { + return Unit.also { + Timber.tag(loggerTag.value) + .v("handleSecretRequest() : Ignore request from self device") + } + } + val device = cryptoStore.getUserDevice(credentials.userId, deviceId) ?: return Unit.also { Timber.tag(loggerTag.value) @@ -254,6 +261,37 @@ internal class SecretShareManager @Inject constructor( } } + suspend fun requestMissingSecrets() { + // quick implementation for backward compatibility with rust, will request all secrets to all own devices + val secretNames = listOf(MASTER_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME) + + secretNames.forEach { secretName -> + val toDeviceContent = SecretShareRequest( + requestingDeviceId = credentials.deviceId, + secretName = secretName, + requestId = createUniqueTxnId() + ) + + val contentMap = MXUsersDevicesMap() + contentMap.setObject(credentials.userId, "*", toDeviceContent) + + val params = SendToDeviceTask.Params( + eventType = EventType.REQUEST_SECRET, + contentMap = contentMap + ) + try { + withContext(coroutineDispatchers.io) { + sendToDeviceTask.execute(params) + } + Timber.tag(loggerTag.value) + .d("Secret request sent for $secretName") + } catch (failure: Throwable) { + Timber.tag(loggerTag.value) + .w("Failed to request secret $secretName") + } + } + } + suspend fun onSecretSendReceived(toDevice: Event, handleGossip: ((name: String, value: String) -> Boolean)) { Timber.tag(loggerTag.value) .i("onSecretSend() from ${toDevice.senderId} : onSecretSendReceived ${toDevice.content?.get("sender_key")}") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt index 91f3c2a506..d5596ce56f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/rendezvous/Rendezvous.kt @@ -34,10 +34,6 @@ import org.matrix.android.sdk.api.rendezvous.model.SecureRendezvousChannelAlgori import org.matrix.android.sdk.api.rendezvous.transports.SimpleHttpRendezvousTransport import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME -import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME -import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME -import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber @@ -222,15 +218,10 @@ class Rendezvous( Timber.tag(TAG).i("No master key given by verifying device") } - // request secrets from the verifying device - Timber.tag(TAG).i("Requesting secrets from $verifyingDeviceId") + // request secrets from other sessions. + Timber.tag(TAG).i("Requesting secrets from other sessions") - session.sharedSecretStorageService().let { - it.requestSecret(MASTER_KEY_SSSS_NAME, verifyingDeviceId) - it.requestSecret(SELF_SIGNING_KEY_SSSS_NAME, verifyingDeviceId) - it.requestSecret(USER_SIGNING_KEY_SSSS_NAME, verifyingDeviceId) - it.requestSecret(KEYBACKUP_SECRET_SSSS_NAME, verifyingDeviceId) - } + session.sharedSecretStorageService().requestMissingSecrets() } else { Timber.tag(TAG).i("Not doing verification") } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 78672adb00..6b94452e39 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -85,6 +85,11 @@ data class HomeServerCapabilities( * External account management url for use with MSC3824 delegated OIDC, provided in Wellknown. */ val externalAccountManagementUrl: String? = null, + + /** + * Authentication issuer for use with MSC3824 delegated OIDC, provided in Wellknown. + */ + val authenticationIssuer: String? = null, ) { enum class RoomCapabilitySupport { @@ -141,6 +146,8 @@ data class HomeServerCapabilities( return cap?.preferred ?: cap?.support?.lastOrNull() } + val delegatedOidcAuthEnabled: Boolean = authenticationIssuer != null + companion object { const val MAX_UPLOAD_FILE_SIZE_UNKNOWN = -1L const val ROOM_CAP_KNOCK = "knock" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt index bdbbd3ea84..783665f9b8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt @@ -135,5 +135,11 @@ interface SharedSecretStorageService { fun checkShouldBeAbleToAccessSecrets(secretNames: List, keyId: String?): IntegrityResult + @Deprecated("Requesting custom secrets not yet support by rust stack, prefer requestMissingSecrets") suspend fun requestSecret(name: String, myOtherDeviceId: String) + + /** + * Request the missing local secrets to other sessions. + */ + suspend fun requestMissingSecrets() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt index bbef75a21d..e852c61185 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt @@ -298,7 +298,7 @@ internal class DefaultAuthenticationService @Inject constructor( } // If an m.login.sso flow is present that is flagged as being for MSC3824 OIDC compatibility then we only return that flow - val oidcCompatibilityFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.sso" && it.delegatedOidcCompatibilty == true } + val oidcCompatibilityFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.sso" && it.delegatedOidcCompatibility == true } val flows = if (oidcCompatibilityFlow != null) listOf(oidcCompatibilityFlow) else loginFlowResponse.flows val supportsGetLoginTokenFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.token" && it.getLoginToken == true } != null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt index ea749a56b8..2e52740ed4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt @@ -51,7 +51,7 @@ internal data class LoginFlow( * See [MSC3824](https://github.com/matrix-org/matrix-spec-proposals/pull/3824) */ @Json(name = "org.matrix.msc3824.delegated_oidc_compatibility") - val delegatedOidcCompatibilty: Boolean? = null, + val delegatedOidcCompatibility: Boolean? = null, /** * Whether a login flow of type m.login.token could accept a token issued using /login/get_token. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index ddb048a912..05b9e14b82 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -385,7 +385,12 @@ internal class DefaultSharedSecretStorageService @Inject constructor( return IntegrityResult.Success(keyInfo.content.passphrase != null) } + @Deprecated("Requesting custom secrets not yet support by rust stack, prefer requestMissingSecrets") override suspend fun requestSecret(name: String, myOtherDeviceId: String) { secretShareManager.requestSecretTo(myOtherDeviceId, name) } + + override suspend fun requestMissingSecrets() { + secretShareManager.requestMissingSecrets() + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index bca189134b..4376323df4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -69,6 +69,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo049 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo050 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo051 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo052 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo053 import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration import javax.inject.Inject @@ -77,7 +78,7 @@ internal class RealmSessionStoreMigration @Inject constructor( private val normalizer: Normalizer ) : MatrixRealmMigration( dbName = "Session", - schemaVersion = 52L, + schemaVersion = 53L, ) { /** * Forces all RealmSessionStoreMigration instances to be equal. @@ -139,5 +140,6 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 50) MigrateSessionTo050(realm).perform() if (oldVersion < 51) MigrateSessionTo051(realm).perform() if (oldVersion < 52) MigrateSessionTo052(realm).perform() + if (oldVersion < 53) MigrateSessionTo053(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt index b566cf7cb6..f5cf88e2c1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt @@ -49,6 +49,7 @@ internal object HomeServerCapabilitiesMapper { canRemotelyTogglePushNotificationsOfDevices = entity.canRemotelyTogglePushNotificationsOfDevices, canRedactRelatedEvents = entity.canRedactEventWithRelations, externalAccountManagementUrl = entity.externalAccountManagementUrl, + authenticationIssuer = entity.authenticationIssuer, ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo053.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo053.kt new file mode 100644 index 0000000000..32fac1ad4b --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo053.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.database.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields +import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +internal class MigrateSessionTo053(realm: DynamicRealm) : RealmMigrator(realm, 53) { + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("HomeServerCapabilitiesEntity") + ?.addField(HomeServerCapabilitiesEntityFields.AUTHENTICATION_ISSUER, String::class.java) + ?.forceRefreshOfHomeServerCapabilities() + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt index 35a5c654de..79aaf6d4ce 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt @@ -36,6 +36,7 @@ internal open class HomeServerCapabilitiesEntity( var canRemotelyTogglePushNotificationsOfDevices: Boolean = false, var canRedactEventWithRelations: Boolean = false, var externalAccountManagementUrl: String? = null, + var authenticationIssuer: String? = null, ) : RealmObject() { companion object diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 71f6ebd6e3..b973de9fd3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -165,6 +165,7 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( Timber.v("Extracted integration config : $config") realm.insertOrUpdate(config) } + homeServerCapabilitiesEntity.authenticationIssuer = getWellknownResult.wellKnown.unstableDelegatedAuthConfig?.issuer homeServerCapabilitiesEntity.externalAccountManagementUrl = getWellknownResult.wellKnown.unstableDelegatedAuthConfig?.accountManagementUrl } diff --git a/matrix-sdk-android/src/main/res/values-ar/strings_sas.xml b/matrix-sdk-android/src/main/res/values-ar/strings_sas.xml index 423a8332bf..7e09da1779 100644 --- a/matrix-sdk-android/src/main/res/values-ar/strings_sas.xml +++ b/matrix-sdk-android/src/main/res/values-ar/strings_sas.xml @@ -1,19 +1,19 @@ - كَلب + كلب هِرَّة أَسَد حِصَان - حِصَانٌ بِقَرن + حصان وحيد القرن خِنزِير فِيل أَرنَب باندَا دِيك - بِطريق + بطريق سُلحفاة - سَمَكَة + سَمَكة أُخطُبُوط فَرَاشَة زَهرَة diff --git a/matrix-sdk-android/src/main/res/values-cs/strings_sas.xml b/matrix-sdk-android/src/main/res/values-cs/strings_sas.xml index 1ef9d56f60..1c63273e7a 100644 --- a/matrix-sdk-android/src/main/res/values-cs/strings_sas.xml +++ b/matrix-sdk-android/src/main/res/values-cs/strings_sas.xml @@ -48,7 +48,7 @@ Sponka Nůžky Zámek - Klíč + Klíč ke dveřím Kladivo Telefon Vlajka diff --git a/matrix-sdk-android/src/main/res/values-es/strings_sas.xml b/matrix-sdk-android/src/main/res/values-es/strings_sas.xml index b5f062cb62..04ef234d98 100644 --- a/matrix-sdk-android/src/main/res/values-es/strings_sas.xml +++ b/matrix-sdk-android/src/main/res/values-es/strings_sas.xml @@ -50,7 +50,7 @@ Candado Llave Martillo - Telefono + Teléfono Bandera Tren Bicicleta diff --git a/matrix-sdk-android/src/main/res/values-fa/strings_sas.xml b/matrix-sdk-android/src/main/res/values-fa/strings_sas.xml new file mode 100644 index 0000000000..d1c5e96c47 --- /dev/null +++ b/matrix-sdk-android/src/main/res/values-fa/strings_sas.xml @@ -0,0 +1,68 @@ + + + + سگ + گربه + شیر + اسب + تک شاخ + خوک + فیل + خرگوش + پاندا + خروس + پنگوئن + لاک‌پشت + ماهی + اختاپوس + پروانه + گل + درخت + کاکتوس + قارچ + زمین + ماه + ابر + آتش + موز + سیب + توت فرنگی + ذرت + پیتزا + کیک + قلب + خنده + ربات + کلاه + عینک + آچار + بابا نوئل + لایک + چتر + ساعت شنی + ساعت + هدیه + لامپ + کتاب + مداد + گیره کاغذ + قیچی + قفل + کلید + چکش + تلفن + پرچم + قطار + دوچرخه + هواپیما + موشک + جام + توپ + گیتار + شیپور + زنگ + لنگر + هدفون + پوشه + سنجاق + diff --git a/matrix-sdk-android/src/main/res/values-id/strings_sas.xml b/matrix-sdk-android/src/main/res/values-id/strings_sas.xml new file mode 100644 index 0000000000..73270815e7 --- /dev/null +++ b/matrix-sdk-android/src/main/res/values-id/strings_sas.xml @@ -0,0 +1,68 @@ + + + + Anjing + Kucing + Singa + Kuda + Unicorn + Babi + Gajah + Kelinci + Panda + Ayam + Penguin + Kura-Kura + Ikan + Gurita + Kupu-Kupu + Bunga + Pohon + Kaktus + Jamur + Bola Dunia + Bulan + Awan + Api + Pisang + Apel + Stroberi + Jagung + Pizza + Kue + Hati + Senyuman + Robot + Topi + Kacamata + Kunci Bengkel + Santa + Jempol + Payung + Jam Pasir + Jam + Kado + Bohlam Lampu + Buku + Pensil + Klip Kertas + Gunting + Gembok + Kunci + Palu + Telepon + Bendera + Kereta Api + Sepeda + Pesawat + Roket + Piala + Bola + Gitar + Terompet + Lonceng + Jangkar + Headphone + Map + Pin + diff --git a/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml b/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml index 12f90e316d..562577bef5 100644 --- a/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml +++ b/matrix-sdk-android/src/main/res/values-ja/strings_sas.xml @@ -32,7 +32,7 @@ ケーキ ハート スマイル - ロボと + ロボット 帽子 めがね スパナ @@ -63,6 +63,6 @@ ベル いかり ヘッドホン - フォルダ + フォルダー ピン diff --git a/matrix-sdk-android/src/main/res/values-pt/strings_sas.xml b/matrix-sdk-android/src/main/res/values-pt/strings_sas.xml new file mode 100644 index 0000000000..d3108551cc --- /dev/null +++ b/matrix-sdk-android/src/main/res/values-pt/strings_sas.xml @@ -0,0 +1,68 @@ + + + + Cão + Gato + Leão + Cavalo + Unicórnio + Porco + Elefante + Coelho + Panda + Galo + Pinguim + Tartaruga + Peixe + Polvo + Borboleta + Flor + Árvore + Cato + Cogumelo + Globo + Lua + Nuvem + Fogo + Banana + Maçã + Morango + Milho + Piza + Bolo + Coração + Sorriso + Robô + Chapéu + Óculos + Chave inglesa + Pai Natal + Polegar para cima + Guarda-chuva + Ampulheta + Relógio + Presente + Lâmpada + Livro + Lápis + Clipe + Tesoura + Cadeado + Chave + Martelo + Telefone + Bandeira + Comboio + Bicicleta + Avião + Foguetão + Troféu + Bola + Guitarra + Trompete + Sino + Âncora + Fones + Pasta + Pionés + diff --git a/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml b/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml index 72fd9cc2a3..ea9af66443 100644 --- a/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml +++ b/matrix-sdk-android/src/main/res/values-sk/strings_sas.xml @@ -1,66 +1,66 @@ - Hlava psa - Hlava mačky - Hlava leva + Pes + Mačka + Lev Kôň - Hlava jednorožca - Hlava prasaťa + Jednorožec + Prasa Slon - Hlava zajaca - Hlava pandy + Zajac + Panda Kohút Tučniak Korytnačka Ryba Chobotnica Motýľ - Tulipán - Listnatý strom + Kvet + Strom Kaktus Huba Zemeguľa - Polmesiac + Mesiac Oblak Oheň Banán - Červené jablko + Jablko Jahoda - Kukuričný klas + Kukurica Pizza - Narodeninová torta - červené srdce - Škeriaca sa tvár + Torta + Srdce + Smajlík Robot - Cilinder + Klobúk Okuliare - Francúzsky kľúč - Santa Claus + Vidlicový kľúč + Mikuláš Palec nahor Dáždnik Presýpacie hodiny Budík - Zabalený darček + Darček Žiarovka - Zatvorená kniha + Kniha Ceruzka - Sponka na papier + Kancelárska sponka Nožnice - Zatvorená zámka + Zámka Kľúč Kladivo Telefón - Kockovaná zástava - Rušeň + Zástava + Vlak Bicykel Lietadlo Raketa Trofej - Futbal + Lopta Gitara Trúbka - Zvon + Zvonec Kotva Slúchadlá Fascikel diff --git a/matrix-sdk-android/src/main/res/values-sq/strings_sas.xml b/matrix-sdk-android/src/main/res/values-sq/strings_sas.xml new file mode 100644 index 0000000000..309cec8c9e --- /dev/null +++ b/matrix-sdk-android/src/main/res/values-sq/strings_sas.xml @@ -0,0 +1,67 @@ + + + + Qen + Mace + Luan + Kalë + Njëbrirësh + Derr + Elefant + Lepur + Panda + Këndes + Pinguin + Breshkë + Peshk + Oktapod + Flutur + Lule + Pemë + Kaktus + Kërpudhë + Rruzull + Hënë + Re + Zjarr + Banane + Mollë + Luleshtrydhe + Misër + Picë + Tortë + Zemër + Emotikon + Robot + Kapë + Syze + Çelës + Babagjyshi i Vitit të Ri + Ombrellë + Klepsidër + Sahat + Dhuratë + Llambë + Libër + Laps + Kapëse + Gërshërë + Dry + Çelës + Çekiç + Telefon + Flamur + Tren + Biçikletë + Avion + Raketë + Trofe + Top + Kitarë + Trombë + Kambanë + Spirancë + Kufje + Dosje + Karficë + diff --git a/matrix-sdk-android/src/main/res/values-vi/strings_sas.xml b/matrix-sdk-android/src/main/res/values-vi/strings_sas.xml new file mode 100644 index 0000000000..8ad1a46121 --- /dev/null +++ b/matrix-sdk-android/src/main/res/values-vi/strings_sas.xml @@ -0,0 +1,68 @@ + + + + Chó + Mèo + Sư tử + Ngựa + Kỳ lân + Heo + Voi + Thỏ + Gấu trúc + Gà trống + Chim cánh cụt + Rùa + + Bạch tuộc + Bướm + Hoa + Cây + Xương rồng + Nấm + Địa cầu + Mặt trăng + Mây + Lửa + Chuối + Táo + Dâu tây + Bắp + Pizza + Bánh + Tim + Mặt cười + Rô-bô + + Kính mắt + Cờ-lê + ông già Nô-en + Thích + Cái ô + Đồng hồ cát + Đồng hồ + Quà tặng + Bóng đèn tròn + Sách + Viết chì + Kẹp giấy + Cái kéo + Ổ khóa + Chìa khóa + Búa + Điện thoại + Lá cờ + Xe lửa + Xe đạp + Máy bay + Tên lửa + Cúp + Banh + Ghi-ta + Kèn + Chuông + Mỏ neo + Tai nghe + Thư mục + Ghim + diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt index 3686ab445d..4646d74c9a 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt @@ -76,6 +76,7 @@ import org.matrix.rustcomponents.sdk.crypto.DeviceLists import org.matrix.rustcomponents.sdk.crypto.EncryptionSettings import org.matrix.rustcomponents.sdk.crypto.KeyRequestPair import org.matrix.rustcomponents.sdk.crypto.KeysImportResult +import org.matrix.rustcomponents.sdk.crypto.LocalTrust import org.matrix.rustcomponents.sdk.crypto.Logger import org.matrix.rustcomponents.sdk.crypto.MegolmV1BackupKey import org.matrix.rustcomponents.sdk.crypto.Request @@ -869,6 +870,11 @@ internal class OlmMachine @Inject constructor( } } + suspend fun requestMissingSecretsFromOtherSessions(): Boolean { + return withContext(coroutineDispatchers.io) { + inner.queryMissingSecretsFromOtherSessions() + } + } @Throws(CryptoStoreException::class) suspend fun enableBackupV1(key: String, version: String) { return withContext(coroutineDispatchers.computation) { @@ -934,4 +940,11 @@ internal class OlmMachine @Inject constructor( inner.verifyBackup(serializedAuthData) } } + + @Throws(CryptoStoreException::class) + suspend fun setDeviceLocalTrust(userId: String, deviceId: String, trusted: Boolean) { + withContext(coroutineDispatchers.io) { + inner.setLocalTrust(userId, deviceId, if (trusted) LocalTrust.VERIFIED else LocalTrust.UNSET) + } + } } diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt index 57f81ef592..d5069fe010 100755 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/RustCryptoService.kt @@ -31,6 +31,7 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.crypto.MXCryptoConfig +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.logger.LoggerTag @@ -536,7 +537,8 @@ internal class RustCryptoService @Inject constructor( } override suspend fun setDeviceVerification(trustLevel: DeviceTrustLevel, userId: String, deviceId: String) { - TODO("Not yet implemented") + Timber.w("Rust stack only support API to set local trust") + olmMachine.setDeviceLocalTrust(userId, deviceId, trustLevel.isLocallyVerified().orFalse()) } /** diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt index b4fab22677..ba46776663 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/SecretShareManager.kt @@ -16,15 +16,29 @@ package org.matrix.android.sdk.internal.crypto -import org.matrix.android.sdk.BuildConfig +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.internal.crypto.network.OutgoingRequestsProcessor +import org.matrix.rustcomponents.sdk.crypto.Request import timber.log.Timber import javax.inject.Inject +import javax.inject.Provider -internal class SecretShareManager @Inject constructor() { +internal class SecretShareManager @Inject constructor( + private val olmMachine: Provider, + private val outgoingRequestsProcessor: OutgoingRequestsProcessor) { suspend fun requestSecretTo(deviceId: String, secretName: String) { - // nop in rust? - if (BuildConfig.DEBUG) TODO("requestSecretTo Not implemented in Rust") - Timber.e("SecretShareManager Not supported in rust $deviceId, $secretName") + Timber.w("SecretShareManager requesting custom secrets not supported $deviceId, $secretName") + // rust stack only support requesting secrets defined in the spec (not custom secret yet) + requestMissingSecrets() + } + + suspend fun requestMissingSecrets() { + this.olmMachine.get().requestMissingSecretsFromOtherSessions() + + // immediately send the requests + outgoingRequestsProcessor.processOutgoingRequests(this.olmMachine.get()) { + it is Request.ToDevice && it.eventType == EventType.REQUEST_SECRET + } } } diff --git a/tools/import_sas_strings.py b/tools/import_sas_strings.py index faf4ed7080..cd642fd0d1 100755 --- a/tools/import_sas_strings.py +++ b/tools/import_sas_strings.py @@ -35,7 +35,7 @@ if args.verbose: print("Argument:") print(args) -base_url = "https://raw.githubusercontent.com/matrix-org/matrix-doc/master/data-definitions/sas-emoji.json" +base_url = "https://raw.githubusercontent.com/matrix-org/matrix-spec/main/data-definitions/sas-emoji.json" print("Downloading " + base_url + "…") diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml index dbe30f2267..467b32bacd 100644 --- a/tools/lint/lint.xml +++ b/tools/lint/lint.xml @@ -17,7 +17,7 @@ - + diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 36f1979531..9aff3eaa84 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 5 +ext.versionPatch = 6 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' diff --git a/vector/build.gradle b/vector/build.gradle index eef4e333cf..e45d23a11e 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -277,6 +277,7 @@ dependencies { runtimeOnly(libs.jsonwebtoken.jjwtOrgjson) { exclude group: 'org.json', module: 'json' //provided by Android natively } + testImplementation(libs.jsonwebtoken.jjwtOrgjson) implementation 'commons-codec:commons-codec:1.15' // MapTiler diff --git a/vector/src/main/java/im/vector/app/features/call/conference/jwt/JitsiJWTFactory.kt b/vector/src/main/java/im/vector/app/features/call/conference/jwt/JitsiJWTFactory.kt index 8809606e6e..a6dd0831c7 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/jwt/JitsiJWTFactory.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/jwt/JitsiJWTFactory.kt @@ -19,8 +19,11 @@ package im.vector.app.features.call.conference.jwt import im.vector.app.core.utils.ensureProtocol import io.jsonwebtoken.Jwts import io.jsonwebtoken.SignatureAlgorithm +import io.jsonwebtoken.io.Encoders import io.jsonwebtoken.security.Keys import org.matrix.android.sdk.api.session.openid.OpenIdToken +import javax.crypto.Mac +import javax.crypto.spec.SecretKeySpec import javax.inject.Inject class JitsiJWTFactory @Inject constructor() { @@ -37,7 +40,12 @@ class JitsiJWTFactory @Inject constructor() { userDisplayName: String ): String { // The secret key here is irrelevant, we're only using the JWT to transport data to Prosody in the Jitsi stack. - val key = Keys.secretKeyFor(SignatureAlgorithm.HS256) + // In the PR https://github.com/jitsi/luajwtjitsi/pull/3 the function `luajwtjitsi.decode` was removed and + // we cannot use random secret keys anymore. But the JWT library `jjwt` doesn't accept the hardcoded key `notused` + // from the module `prosody-mod-auth-matrix-user-verification` since it's too short and thus insecure. So, we + // create a new token using a random key and then re-sign the token manually with the 'weak' key. + val signatureAlgorithm = SignatureAlgorithm.HS256 + val key = Keys.secretKeyFor(signatureAlgorithm) val context = mapOf( "matrix" to mapOf( "token" to openIdToken.accessToken, @@ -52,7 +60,8 @@ class JitsiJWTFactory @Inject constructor() { // As per Jitsi token auth, `iss` needs to be set to something agreed between // JWT generating side and Prosody config. Since we have no configuration for // the widgets, we can't set one anywhere. Using the Jitsi domain here probably makes sense. - return Jwts.builder() + val token = Jwts.builder() + .setHeaderParam("typ", "JWT") .setIssuer(jitsiServerDomain) .setSubject(jitsiServerDomain) .setAudience(jitsiServerDomain.ensureProtocol()) @@ -61,5 +70,11 @@ class JitsiJWTFactory @Inject constructor() { .claim("context", context) .signWith(key) .compact() + // Re-sign token with the hardcoded key + val toSign = token.substring(0, token.lastIndexOf('.')) + val mac = Mac.getInstance(signatureAlgorithm.jcaName) + mac.init(SecretKeySpec("notused".toByteArray(), mac.algorithm)) + val prosodySignature = Encoders.BASE64URL.encode(mac.doFinal(toSign.toByteArray())) + return "$toSign.$prosodySignature" } } diff --git a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt index 3a72907467..d83c65ad5e 100644 --- a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt +++ b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt @@ -139,19 +139,19 @@ class ShortcutsHandler @Inject constructor( } private fun createShortcuts(rooms: List) { - if (hasPinCode.get()) { - // No shortcut in this case (privacy) - ShortcutManagerCompat.removeAllDynamicShortcuts(context) - } else { - val shortcuts = rooms - .take(maxShortcutCountPerActivity) - .mapIndexed { index, room -> - shortcutCreator.create(room, index) - } + ShortcutManagerCompat.removeAllDynamicShortcuts(context) - shortcuts.forEach { shortcut -> - ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) - } + // No shortcut in this case (privacy) + if (hasPinCode.get()) return + + val shortcuts = rooms + .take(maxShortcutCountPerActivity) + .mapIndexed { index, room -> + shortcutCreator.create(room, index) + } + + shortcuts.forEach { shortcut -> + ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) } } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/VectorUncaughtExceptionHandler.kt b/vector/src/main/java/im/vector/app/features/rageshake/VectorUncaughtExceptionHandler.kt index d3174631e8..6d6ecd9edc 100644 --- a/vector/src/main/java/im/vector/app/features/rageshake/VectorUncaughtExceptionHandler.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/VectorUncaughtExceptionHandler.kt @@ -20,6 +20,7 @@ import android.content.SharedPreferences import android.os.Build import androidx.core.content.edit import im.vector.app.core.di.DefaultPreferences +import im.vector.app.core.resources.AppNameProvider import im.vector.app.core.resources.VersionCodeProvider import im.vector.app.features.version.VersionProvider import org.matrix.android.sdk.api.Matrix @@ -36,6 +37,7 @@ class VectorUncaughtExceptionHandler @Inject constructor( private val bugReporter: BugReporter, private val versionProvider: VersionProvider, private val versionCodeProvider: VersionCodeProvider, + private val appNameProvider: AppNameProvider, ) : Thread.UncaughtExceptionHandler { // key to save the crash status @@ -67,12 +69,12 @@ class VectorUncaughtExceptionHandler @Inject constructor( putBoolean(PREFS_CRASH_KEY, true) } val b = StringBuilder() - val appName = "Element" // TODO Matrix.getApplicationName() + val appName = appNameProvider.getAppName() - b.append(appName + " Build : " + versionCodeProvider.getVersionCode() + "\n") + b.append("$appName Build : ${versionCodeProvider.getVersionCode()}\n") b.append("$appName Version : ${versionProvider.getVersion(longFormat = true)}\n") b.append("SDK Version : ${Matrix.getSdkVersion()}\n") - b.append("Phone : " + Build.MODEL.trim() + " (" + Build.VERSION.INCREMENTAL + " " + Build.VERSION.RELEASE + " " + Build.VERSION.CODENAME + ")\n") + b.append("Phone : ${Build.MODEL.trim()} (${Build.VERSION.INCREMENTAL} ${Build.VERSION.RELEASE} ${Build.VERSION.CODENAME})\n") b.append("Memory statuses \n") diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt index dceb92f6e2..a883d22334 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt @@ -45,10 +45,11 @@ import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.platform.SimpleTextWatcher import im.vector.app.core.preference.UserAvatarPreference import im.vector.app.core.preference.VectorPreference +import im.vector.app.core.preference.VectorPreferenceCategory import im.vector.app.core.preference.VectorSwitchPreference import im.vector.app.core.utils.TextUtils import im.vector.app.core.utils.getSizeOfFiles -import im.vector.app.core.utils.openUrlInExternalBrowser +import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.core.utils.toast import im.vector.app.databinding.DialogChangePasswordBinding import im.vector.app.features.MainActivity @@ -101,12 +102,18 @@ class VectorSettingsGeneralFragment : private val mPasswordPreference by lazy { findPreference(VectorPreferences.SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY)!! } + private val mManage3pidsPreference by lazy { + findPreference(VectorPreferences.SETTINGS_EMAILS_AND_PHONE_NUMBERS_PREFERENCE_KEY)!! + } private val mIdentityServerPreference by lazy { findPreference(VectorPreferences.SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY)!! } private val mExternalAccountManagementPreference by lazy { findPreference(VectorPreferences.SETTINGS_EXTERNAL_ACCOUNT_MANAGEMENT_KEY)!! } + private val mDeactivateAccountCategory by lazy { + findPreference("SETTINGS_DEACTIVATE_ACCOUNT_CATEGORY_KEY")!! + } // Local contacts private val mContactSettingsCategory by lazy { @@ -197,6 +204,10 @@ class VectorSettingsGeneralFragment : mPasswordPreference.isVisible = false } + // Manage 3Pid + // Hide the preference if 3pids can not be updated + mManage3pidsPreference.isVisible = homeServerCapabilities.canChange3pid + val openDiscoveryScreenPreferenceClickListener = Preference.OnPreferenceClickListener { (requireActivity() as VectorSettingsActivity).navigateTo( DiscoverySettingsFragment::class.java, @@ -214,7 +225,7 @@ class VectorSettingsGeneralFragment : // Hide the preference if no URL is given by server if (homeServerCapabilities.externalAccountManagementUrl != null) { mExternalAccountManagementPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrlInExternalBrowser(it.context, homeServerCapabilities.externalAccountManagementUrl) + openUrlInChromeCustomTab(it.context, null, homeServerCapabilities.externalAccountManagementUrl!!) true } @@ -315,6 +326,8 @@ class VectorSettingsGeneralFragment : false } + // Account deactivation is visible only if account is not managed by an external URL. + mDeactivateAccountCategory.isVisible = homeServerCapabilities.delegatedOidcAuthEnabled.not() } private suspend fun getCacheSize(): Long = withContext(Dispatchers.IO) { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt index c97f353110..de9671e360 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt @@ -50,4 +50,6 @@ sealed class DevicesViewEvents : VectorViewEvents { data class ShowManuallyVerify(val cryptoDeviceInfo: CryptoDeviceInfo) : DevicesViewEvents() object PromptResetSecrets : DevicesViewEvents() + + data class OpenBrowser(val url: String) : DevicesViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 526a6006e1..5a1e602808 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -346,6 +346,20 @@ class DevicesViewModel @AssistedInject constructor( private fun handleDelete(action: DevicesAction.Delete) { val deviceId = action.deviceId + val accountManagementUrl = session.homeServerCapabilitiesService().getHomeServerCapabilities().externalAccountManagementUrl + if (accountManagementUrl != null) { + // Open external browser to delete this session + _viewEvents.post( + DevicesViewEvents.OpenBrowser( + url = accountManagementUrl.removeSuffix("/") + "?action=session_end&device_id=$deviceId" + ) + ) + } else { + doDelete(deviceId) + } + } + + private fun doDelete(deviceId: String) { setState { copy( request = Loading() diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt index 5e2f0b21f2..9cb314b2b7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt @@ -35,6 +35,7 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.DialogBaseEditTextBinding import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.auth.ReAuthActivity @@ -95,6 +96,9 @@ class VectorSettingsDevicesFragment : is DevicesViewEvents.PromptResetSecrets -> { navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET) } + is DevicesViewEvents.OpenBrowser -> { + openUrlInChromeCustomTab(requireContext(), null, it.url) + } } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewModel.kt index f2e6b25f32..43530cb17c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewModel.kt @@ -35,12 +35,13 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth import timber.log.Timber class DevicesViewModel @AssistedInject constructor( @Assisted initialState: DevicesViewState, - activeSessionHolder: ActiveSessionHolder, + private val activeSessionHolder: ActiveSessionHolder, private val getCurrentSessionCrossSigningInfoUseCase: GetCurrentSessionCrossSigningInfoUseCase, private val getDeviceFullInfoListUseCase: GetDeviceFullInfoListUseCase, private val refreshDevicesOnCryptoDevicesChangeUseCase: RefreshDevicesOnCryptoDevicesChangeUseCase, @@ -69,6 +70,19 @@ class DevicesViewModel @AssistedInject constructor( refreshDeviceList() refreshIpAddressVisibility() observePreferences() + initDelegatedOidcAuthEnabled() + } + + private fun initDelegatedOidcAuthEnabled() { + setState { + copy( + delegatedOidcAuthEnabled = activeSessionHolder.getSafeActiveSession() + ?.homeServerCapabilitiesService() + ?.getHomeServerCapabilities() + ?.delegatedOidcAuthEnabled + .orFalse() + ) + } } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewState.kt index 75d0f132bb..6d6baa9d5f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/DevicesViewState.kt @@ -26,6 +26,7 @@ data class DevicesViewState( val devices: Async = Uninitialized, val isLoading: Boolean = false, val isShowingIpAddress: Boolean = false, + val delegatedOidcAuthEnabled: Boolean = false, ) : MavericksState data class DeviceFullInfoList( diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt index ec21970f94..bf90120b96 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt @@ -290,8 +290,8 @@ class VectorSettingsDevicesFragment : val unverifiedSessionsCount = deviceFullInfoList?.unverifiedSessionsCount ?: 0 renderSecurityRecommendations(inactiveSessionsCount, unverifiedSessionsCount) - renderCurrentSessionView(currentDeviceInfo, hasOtherDevices = otherDevices?.isNotEmpty().orFalse()) - renderOtherSessionsView(otherDevices, state.isShowingIpAddress) + renderCurrentSessionView(currentDeviceInfo, hasOtherDevices = otherDevices?.isNotEmpty().orFalse(), state) + renderOtherSessionsView(otherDevices, state) } else { hideSecurityRecommendations() hideCurrentSessionView() @@ -347,13 +347,16 @@ class VectorSettingsDevicesFragment : hideInactiveSessionsRecommendation() } - private fun renderOtherSessionsView(otherDevices: List?, isShowingIpAddress: Boolean) { + private fun renderOtherSessionsView(otherDevices: List?, state: DevicesViewState) { + val isShowingIpAddress = state.isShowingIpAddress if (otherDevices.isNullOrEmpty()) { hideOtherSessionsView() } else { views.deviceListHeaderOtherSessions.isVisible = true val colorDestructive = colorProvider.getColorFromAttribute(R.attr.colorError) val multiSignoutItem = views.deviceListHeaderOtherSessions.menu.findItem(R.id.otherSessionsHeaderMultiSignout) + // Hide multi signout if the homeserver delegates the account management + multiSignoutItem.isVisible = state.delegatedOidcAuthEnabled.not() val nbDevices = otherDevices.size multiSignoutItem.title = stringProvider.getQuantityString(R.plurals.device_manager_other_sessions_multi_signout_all, nbDevices, nbDevices) multiSignoutItem.setTextColor(colorDestructive) @@ -377,23 +380,24 @@ class VectorSettingsDevicesFragment : views.deviceListOtherSessions.isVisible = false } - private fun renderCurrentSessionView(currentDeviceInfo: DeviceFullInfo?, hasOtherDevices: Boolean) { + private fun renderCurrentSessionView(currentDeviceInfo: DeviceFullInfo?, hasOtherDevices: Boolean, state: DevicesViewState) { currentDeviceInfo?.let { - renderCurrentSessionHeaderView(hasOtherDevices) + renderCurrentSessionHeaderView(hasOtherDevices, state) renderCurrentSessionListView(it) } ?: run { hideCurrentSessionView() } } - private fun renderCurrentSessionHeaderView(hasOtherDevices: Boolean) { + private fun renderCurrentSessionHeaderView(hasOtherDevices: Boolean, state: DevicesViewState) { views.deviceListHeaderCurrentSession.isVisible = true val colorDestructive = colorProvider.getColorFromAttribute(R.attr.colorError) val signoutSessionItem = views.deviceListHeaderCurrentSession.menu.findItem(R.id.currentSessionHeaderSignout) signoutSessionItem.setTextColor(colorDestructive) val signoutOtherSessionsItem = views.deviceListHeaderCurrentSession.menu.findItem(R.id.currentSessionHeaderSignoutOtherSessions) signoutOtherSessionsItem.setTextColor(colorDestructive) - signoutOtherSessionsItem.isVisible = hasOtherDevices + // Hide signout other sessions if the homeserver delegates the account management + signoutOtherSessionsItem.isVisible = hasOtherDevices && state.delegatedOidcAuthEnabled.not() } private fun renderCurrentSessionListView(currentDeviceInfo: DeviceFullInfo) { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt index cee90986cd..a5897be58c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt @@ -103,10 +103,15 @@ class OtherSessionsFragment : val nbDevices = viewState.devices()?.size ?: 0 stringProvider.getQuantityString(R.plurals.device_manager_other_sessions_multi_signout_all, nbDevices, nbDevices) } - multiSignoutItem.isVisible = if (viewState.isSelectModeEnabled) { - viewState.devices.invoke()?.any { it.isSelected }.orFalse() + multiSignoutItem.isVisible = if (viewState.delegatedOidcAuthEnabled) { + // Hide multi signout if the homeserver delegates the account management + false } else { - viewState.devices.invoke()?.isNotEmpty().orFalse() + if (viewState.isSelectModeEnabled) { + viewState.devices.invoke()?.any { it.isSelected }.orFalse() + } else { + viewState.devices.invoke()?.isNotEmpty().orFalse() + } } val showAsActionFlag = if (viewState.isSelectModeEnabled) MenuItem.SHOW_AS_ACTION_IF_ROOM else MenuItem.SHOW_AS_ACTION_NEVER multiSignoutItem.setShowAsAction(showAsActionFlag or MenuItem.SHOW_AS_ACTION_WITH_TEXT) @@ -308,7 +313,10 @@ class OtherSessionsFragment : ) ) views.otherSessionsNotFoundTextView.text = getString(R.string.device_manager_other_sessions_no_inactive_sessions_found) - updateSecurityLearnMoreButton(R.string.device_manager_learn_more_sessions_inactive_title, R.string.device_manager_learn_more_sessions_inactive) + updateSecurityLearnMoreButton( + R.string.device_manager_learn_more_sessions_inactive_title, + R.string.device_manager_learn_more_sessions_inactive + ) } DeviceManagerFilterType.ALL_SESSIONS -> { /* NOOP. View is not visible */ } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt index a5282e7ba2..fd463a933c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt @@ -36,12 +36,13 @@ import im.vector.app.features.settings.devices.v2.signout.SignoutSessionsReAuthN import im.vector.app.features.settings.devices.v2.signout.SignoutSessionsUseCase import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth import timber.log.Timber class OtherSessionsViewModel @AssistedInject constructor( @Assisted private val initialState: OtherSessionsViewState, - activeSessionHolder: ActiveSessionHolder, + private val activeSessionHolder: ActiveSessionHolder, private val getDeviceFullInfoListUseCase: GetDeviceFullInfoListUseCase, private val signoutSessionsUseCase: SignoutSessionsUseCase, private val pendingAuthHandler: PendingAuthHandler, @@ -65,6 +66,19 @@ class OtherSessionsViewModel @AssistedInject constructor( observeDevices(initialState.currentFilter) refreshIpAddressVisibility() observePreferences() + initDelegatedOidcAuthEnabled() + } + + private fun initDelegatedOidcAuthEnabled() { + setState { + copy( + delegatedOidcAuthEnabled = activeSessionHolder.getSafeActiveSession() + ?.homeServerCapabilitiesService() + ?.getHomeServerCapabilities() + ?.delegatedOidcAuthEnabled + .orFalse() + ) + } } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt index f4dd3640ee..dcff652768 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt @@ -29,6 +29,7 @@ data class OtherSessionsViewState( val isSelectModeEnabled: Boolean = false, val isLoading: Boolean = false, val isShowingIpAddress: Boolean = false, + val delegatedOidcAuthEnabled: Boolean = false, ) : MavericksState { constructor(args: OtherSessionsArgs) : this(excludeCurrentDevice = args.excludeCurrentDevice) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index 399f99201b..7b10939072 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -39,6 +39,7 @@ import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.DrawableProvider import im.vector.app.core.resources.StringProvider +import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentSessionOverviewBinding import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.crypto.recover.SetupMode @@ -135,10 +136,19 @@ class SessionOverviewFragment : activity?.let { SignOutUiWorker(it).perform() } } - private fun confirmSignoutOtherSession() { - activity?.let { - buildConfirmSignoutDialogUseCase.execute(it, this::signoutSession) - .show() + private fun confirmSignoutOtherSession() = withState(viewModel) { state -> + if (state.externalAccountManagementUrl != null) { + // Manage in external account manager + openUrlInChromeCustomTab( + requireContext(), + null, + state.externalAccountManagementUrl.removeSuffix("/") + "?action=session_end&device_id=${state.deviceId}" + ) + } else { + activity?.let { + buildConfirmSignoutDialogUseCase.execute(it, this::signoutSession) + .show() + } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt index 55866cb8c4..80db4717f0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt @@ -75,6 +75,18 @@ class SessionOverviewViewModel @AssistedInject constructor( observeNotificationsStatus(initialState.deviceId) refreshIpAddressVisibility() observePreferences() + initExternalAccountManagementUrl() + } + + private fun initExternalAccountManagementUrl() { + setState { + copy( + externalAccountManagementUrl = activeSessionHolder.getSafeActiveSession() + ?.homeServerCapabilitiesService() + ?.getHomeServerCapabilities() + ?.externalAccountManagementUrl + ) + } } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt index 0f66605f98..f6a1307a5f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt @@ -29,6 +29,7 @@ data class SessionOverviewViewState( val isLoading: Boolean = false, val notificationsStatus: NotificationsStatus = NotificationsStatus.NOT_SUPPORTED, val isShowingIpAddress: Boolean = false, + val externalAccountManagementUrl: String? = null, ) : MavericksState { constructor(args: SessionOverviewArgs) : this( deviceId = args.deviceId diff --git a/vector/src/main/res/xml/vector_settings_general.xml b/vector/src/main/res/xml/vector_settings_general.xml index 8600dbc1be..90c75f0e74 100644 --- a/vector/src/main/res/xml/vector_settings_general.xml +++ b/vector/src/main/res/xml/vector_settings_general.xml @@ -113,7 +113,9 @@ - + { + return parseTokenPart(token.split(".")[0], stringToString) + } + + private fun parseTokenBody(token: String): Map { + return parseTokenPart(token.split(".")[1], stringToAny) + } + + private fun parseMatrixData(token: String): Map<*, *> { + return (parseTokenBody(token)["context"] as Map<*, *>)["matrix"] as Map<*, *> + } + + private fun parseUserData(token: String): Map<*, *> { + return (parseTokenBody(token)["context"] as Map<*, *>)["user"] as Map<*, *> + } + + private fun parseTokenPart(value: String, type: ParameterizedType): T { + val decoded = String(base64Decoder.decode(value)) + val adapter: JsonAdapter = moshi.adapter(type) + return adapter.fromJson(decoded)!! + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt index 1dc36de709..9d46cc0c28 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSharedSecretStorageService.kt @@ -75,10 +75,15 @@ class FakeSharedSecretStorageService : SharedSecretStorageService by mockk() { override fun checkShouldBeAbleToAccessSecrets(secretNames: List, keyId: String?) = integrityResult + @Deprecated("Requesting custom secrets not yet support by rust stack, prefer requestMissingSecrets") override suspend fun requestSecret(name: String, myOtherDeviceId: String) { TODO("Not yet implemented") } + override suspend fun requestMissingSecrets() { + TODO("Not yet implemented") + } + fun givenIsRecoverySetupReturns(isRecoverySetup: Boolean) { every { isRecoverySetup() } returns isRecoverySetup }