diff --git a/CHANGES.md b/CHANGES.md index 5f829a2e3b..ece2a87304 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,18 @@ +Changes in Element v1.1.16 (2021-08-09) +======================================= + +Features ✨ +---------- + - Spaces - Support Restricted Room via room capabilities API ([#3509](https://github.com/vector-im/element-android/issues/3509)) + - Spaces | Support restricted room access in room settings ([#3665](https://github.com/vector-im/element-android/issues/3665)) + +Bugfixes 🐛 +---------- + - Fix crash when opening Troubleshoot Notifications ([#3778](https://github.com/vector-im/element-android/issues/3778)) + - Fix error when sending encrypted message if someone in the room logs out. ([#3792](https://github.com/vector-im/element-android/issues/3792)) + - Voice Message - Amplitude update java.util.ConcurrentModificationException ([#3796](https://github.com/vector-im/element-android/issues/3796)) + + Changes in Element v1.1.15 (2021-07-30) ======================================= diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40101130.txt b/fastlane/metadata/android/cs-CZ/changelogs/40101130.txt new file mode 100644 index 0000000000..1ea00cbbb9 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: aktualizace hlavně kvůli stabilitě a opravám chyb +Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40101140.txt b/fastlane/metadata/android/cs-CZ/changelogs/40101140.txt new file mode 100644 index 0000000000..09f0da7763 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: oprava chyby ohledně šifrovaných zpráv +Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/de-DE/changelogs/40101140.txt b/fastlane/metadata/android/de-DE/changelogs/40101140.txt new file mode 100644 index 0000000000..75732a5364 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Hauptänderung dieser Version: Beheben eines Problems mit verschlüsselten Nachrichten. +Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/en-US/changelogs/40101160.txt b/fastlane/metadata/android/en-US/changelogs/40101160.txt new file mode 100644 index 0000000000..54b6cbee97 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40101160.txt @@ -0,0 +1,2 @@ +Main changes in this version: Fix error when sending encrypted message if someone in the room logs out. +Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.1.16 \ No newline at end of file diff --git a/fastlane/metadata/android/et/changelogs/40101130.txt b/fastlane/metadata/android/et/changelogs/40101130.txt new file mode 100644 index 0000000000..4305a66770 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: üldiste vigade parandus. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/et/changelogs/40101140.txt b/fastlane/metadata/android/et/changelogs/40101140.txt new file mode 100644 index 0000000000..5e16cad97b --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: krüptitud sõnumitega seotud vigade parandus +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/hu-HU/changelogs/40101130.txt b/fastlane/metadata/android/hu-HU/changelogs/40101130.txt new file mode 100644 index 0000000000..c90cefeeda --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Fő változás ebben a verzióban: leginkább hibajavító és stabilitást növelő frissítés +Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/hu-HU/changelogs/40101140.txt b/fastlane/metadata/android/hu-HU/changelogs/40101140.txt new file mode 100644 index 0000000000..55d57c4515 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Fő változás ebben a verzióban: titkosított üzenetekkel kapcsolatos hibajavítás +Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/id/changelogs/40100100.txt b/fastlane/metadata/android/id/changelogs/40100100.txt new file mode 100644 index 0000000000..96a8f506b3 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100100.txt @@ -0,0 +1,2 @@ +Versi baru ini terutama berisi perbaikan bug dan peningkatan. Mengirim pesan sekarang jauh lebih cepat. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.10 diff --git a/fastlane/metadata/android/id/changelogs/40100110.txt b/fastlane/metadata/android/id/changelogs/40100110.txt new file mode 100644 index 0000000000..9f86005d8b --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100110.txt @@ -0,0 +1,2 @@ +Versi baru ini terutama berisi antarmuka pengguna dan peningkatan pengalaman pengguna. Sekarang Anda dapat mengundang teman, dan membuat sebuah DM sangat cepat dengan memindai kode QR. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.11 diff --git a/fastlane/metadata/android/id/changelogs/40100120.txt b/fastlane/metadata/android/id/changelogs/40100120.txt new file mode 100644 index 0000000000..3067b6367d --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100120.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Pratinjau URL, keyboard Emoji baru, kemampuan pengaturan ruangan baru, dan salju untuk Natal! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.12 diff --git a/fastlane/metadata/android/id/changelogs/40100130.txt b/fastlane/metadata/android/id/changelogs/40100130.txt new file mode 100644 index 0000000000..df52988b6c --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100130.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Pratinjau URL, keyboard Emoji baru, kemampuan pengaturan ruangan baru, dan salju untuk Natal! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.13 diff --git a/fastlane/metadata/android/id/changelogs/40100140.txt b/fastlane/metadata/android/id/changelogs/40100140.txt new file mode 100644 index 0000000000..5243adc1a8 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100140.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Edit izin ruangan, tema cahaya/gelap otomatis, dan banyak perbaikan bug. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.14 diff --git a/fastlane/metadata/android/id/changelogs/40100150.txt b/fastlane/metadata/android/id/changelogs/40100150.txt new file mode 100644 index 0000000000..54c307b9b6 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100150.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Dukungan login sosial. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.15 diff --git a/fastlane/metadata/android/id/changelogs/40100160.txt b/fastlane/metadata/android/id/changelogs/40100160.txt new file mode 100644 index 0000000000..3e357db352 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100160.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Dukungan login sosial. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.15 dan https://github.com/vector-im/element-android/releases/tag/v1.0.16 diff --git a/fastlane/metadata/android/id/changelogs/40100170.txt b/fastlane/metadata/android/id/changelogs/40100170.txt new file mode 100644 index 0000000000..77f638a7fd --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40100170.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: perbaikan bug! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.0.17 diff --git a/fastlane/metadata/android/id/changelogs/40101000.txt b/fastlane/metadata/android/id/changelogs/40101000.txt new file mode 100644 index 0000000000..acfe661354 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101000.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: perbaikan VoIP (panggilan audio dan video dalam DM) dan perbaikan bug! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.0 diff --git a/fastlane/metadata/android/id/changelogs/40101010.txt b/fastlane/metadata/android/id/changelogs/40101010.txt new file mode 100644 index 0000000000..a9903a90bd --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101010.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: peningkatan kinerja dan perbaikan bug! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.1 diff --git a/fastlane/metadata/android/id/changelogs/40101020.txt b/fastlane/metadata/android/id/changelogs/40101020.txt new file mode 100644 index 0000000000..d654bda4fe --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101020.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: peningkatan kinerja dan perbaikan bug! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.2 diff --git a/fastlane/metadata/android/id/changelogs/40101030.txt b/fastlane/metadata/android/id/changelogs/40101030.txt new file mode 100644 index 0000000000..283c201b2f --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101030.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: peningkatan kinerja dan perbaikan bug! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.3 diff --git a/fastlane/metadata/android/id/changelogs/40101040.txt b/fastlane/metadata/android/id/changelogs/40101040.txt new file mode 100644 index 0000000000..fdb94db53d --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101040.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: peningkatan kinerja dan perbaikan bug! +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.4 diff --git a/fastlane/metadata/android/id/changelogs/40101050.txt b/fastlane/metadata/android/id/changelogs/40101050.txt new file mode 100644 index 0000000000..856530c703 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101050.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: perbaikan hot-fix untuk 1.1.4 +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.5 diff --git a/fastlane/metadata/android/id/changelogs/40101060.txt b/fastlane/metadata/android/id/changelogs/40101060.txt new file mode 100644 index 0000000000..1810ecc3aa --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101060.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: perbaikan hot-fix untuk 1.1.5 +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.6 diff --git a/fastlane/metadata/android/id/changelogs/40101070.txt b/fastlane/metadata/android/id/changelogs/40101070.txt new file mode 100644 index 0000000000..0087d51703 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101070.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: dukungan beta untuk Spaces. Kompres video sebelum mengirim. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.7 diff --git a/fastlane/metadata/android/id/changelogs/40101080.txt b/fastlane/metadata/android/id/changelogs/40101080.txt new file mode 100644 index 0000000000..cb98796449 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101080.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: perbaikan untuk Spaces. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.8 diff --git a/fastlane/metadata/android/id/changelogs/40101090.txt b/fastlane/metadata/android/id/changelogs/40101090.txt new file mode 100644 index 0000000000..f6f535fe64 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101090.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: menambahkan dukungan untuk jaringan gitter.im. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.9 diff --git a/fastlane/metadata/android/id/changelogs/40101100.txt b/fastlane/metadata/android/id/changelogs/40101100.txt new file mode 100644 index 0000000000..121d84ca50 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101100.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: pembaruan tema dan gaya dan fitur-fitur baru untuk Spaces. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.10 diff --git a/fastlane/metadata/android/id/changelogs/40101110.txt b/fastlane/metadata/android/id/changelogs/40101110.txt new file mode 100644 index 0000000000..63c97253c4 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101110.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: pembaruan tema dan gaya dan fitur baru untuk spaces (perbaikan bug untuk 1.1.10) +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.11 diff --git a/fastlane/metadata/android/id/changelogs/40101120.txt b/fastlane/metadata/android/id/changelogs/40101120.txt new file mode 100644 index 0000000000..b8f23c530b --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101120.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: pembaruan tema dan gaya dan perbaiki crash setelah panggilan video +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.12 diff --git a/fastlane/metadata/android/id/changelogs/40101130.txt b/fastlane/metadata/android/id/changelogs/40101130.txt new file mode 100644 index 0000000000..51c532725b --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: terutama pembaruan stabilitas dan perbaikan bug. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/id/changelogs/40101140.txt b/fastlane/metadata/android/id/changelogs/40101140.txt new file mode 100644 index 0000000000..af1e203dde --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: memperbaiki masalah tentang pesan terenkripsi. +Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/id/full_description.txt b/fastlane/metadata/android/id/full_description.txt new file mode 100644 index 0000000000..0a18b8d64a --- /dev/null +++ b/fastlane/metadata/android/id/full_description.txt @@ -0,0 +1,39 @@ +Element adalah perpesanan yang aman dan aplikasi kolaborasi tim produktivitas yang ideal untuk obrolan grup saat bekerja jarak jauh. Aplikasi obrolan ini menggunakan enkripsi ujung-ke-ujung untuk memberikan konferensi video, berbagi file, dan panggilan suara. + +Fitur Element termasuk: +- Alat komunikasi online yang canggih +- Pesan terenkripsi sepenuhnya untuk memungkinkan komunikasi perusahaan yang lebih aman, bahkan untuk pekerja jarak jauh +- Obrolan terdesentralisasi berdasarkan framework sumber-terbuka Matrix +- Berbagi file dengan aman dengan data terenkripsi saat mengelola proyek +- Obrolan video dengan VoIP dan berbagi layar +- Integrasi yang mudah dengan alat kolaborasi online favorit Anda, alat manajemen proyek, layanan VoIP dan aplikasi perpesanan tim lainnya + +Element benar-benar berbeda dari aplikasi perpesanan dan kolaborasi lainnya. Ini beroperasi pada Matrix, jaringan terbuka untuk pengiriman pesan yang aman dan komunikasi terdesentralisasi. Ini memungkinkan hosting sendiri untuk memberi pengguna kepemilikan maksimum dan kontrol data dan pesan mereka. + +Pesan privasi dan terenkripsi +Element melindungi Anda dari iklan yang tidak diinginkan, data penambangan dan taman berdinding. Ini juga mengamankan semua data Anda, komunikasi video dan suara satu-ke-satu melalui enkripsi ujung-ke-ujung dan verifikasi perangkat yang di-cross-signed. + +Element memberi Anda kendali atas privasi Anda sambil memungkinkan Anda untuk berkomunikasi dengan aman dengan siapa pun di jaringan Matrix, atau alat kolaborasi bisnis lainnya dengan mengintegrasikan dengan aplikasi seperti Slack. + +Element dapat dihost sendiri +Untuk memungkinkan lebih banyak kendali atas data dan percakapan sensitif Anda, Element bisa dihost sendiri atau Anda dapat memilih host berbasis Matrix - standar untuk komunikasi terdesentralisasi sumber-terbuka. Element memberi Anda privasi, kepatuhan keamanan, dan fleksibilitas integrasi. + +Miliki data Anda +Anda memutuskan di mana menyimpan data dan pesan Anda. Tanpa risiko penambangan data atau akses dari pihak ketiga. + +Element menempatkan Anda dalam kendali dengan cara yang berbeda: +1. Dapatkan akun gratis pada server publik matrix.org yang dihost oleh pengembang Matrix, atau memilih dari ribuan server publik yang dihost oleh sukarelawan +2. Host sendiri akun Anda dengan menjalankan server pada infrastruktur IT Anda sendiri +3. Daftar untuk akun di server khusus dengan hanya berlangganan platform hosting Element Matrix Services + +Pesan terbuka dan kolaborasi +Anda dapat mengobrol dengan siapa saja di jaringan Matrix, apakah mereka menggunakan Element, aplikasi Matrix lain atau bahkan jika mereka menggunakan aplikasi perpesanan yang berbeda. + +Sangat aman +Enkripsi ujung-ke-ujung beneran (hanya mereka yang dalam percakapan dapat mendekripsi pesan), dan verifikasi perangkat yang di-cross-signed. + +Komunikasi dan integrasi lengkap +Perpesanan, panggilan suara dan video, berbagi file, berbagi layar dan banyak integrasi, bot dan widget. Buat ruangan, komunitas, tetap terhubung dan selesaikan hal-hal. + +Ambil di mana Anda tinggalkan +Tetap terhubung di mana pun Anda berada dengan riwayat pesan yang sepenuhnya disinkronkan di semua perangkat Anda dan di web di https://app.element.io diff --git a/fastlane/metadata/android/id/short_description.txt b/fastlane/metadata/android/id/short_description.txt new file mode 100644 index 0000000000..e6c3a2f7a9 --- /dev/null +++ b/fastlane/metadata/android/id/short_description.txt @@ -0,0 +1 @@ +Perpesanan grup - pesan terenkripsi, panggilan grup dan video diff --git a/fastlane/metadata/android/id/title.txt b/fastlane/metadata/android/id/title.txt new file mode 100644 index 0000000000..aec5dc9351 --- /dev/null +++ b/fastlane/metadata/android/id/title.txt @@ -0,0 +1 @@ +Element - Perpesanan Aman diff --git a/fastlane/metadata/android/it-IT/changelogs/40101130.txt b/fastlane/metadata/android/it-IT/changelogs/40101130.txt new file mode 100644 index 0000000000..2c7fc1a614 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: aggiornamento di stabilità e correzione errori. +Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/it-IT/changelogs/40101140.txt b/fastlane/metadata/android/it-IT/changelogs/40101140.txt new file mode 100644 index 0000000000..30921e31c6 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: corretto un problema con i messaggi cifrati. +Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/pt-BR/changelogs/40101130.txt b/fastlane/metadata/android/pt-BR/changelogs/40101130.txt new file mode 100644 index 0000000000..cadd1619d6 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: principalmente atualização de estabilidade e consertos de bug. +Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/pt-BR/changelogs/40101140.txt b/fastlane/metadata/android/pt-BR/changelogs/40101140.txt new file mode 100644 index 0000000000..2d33d46e3a --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: consertar um problema sobre mensagens encriptadas. +Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101040.txt b/fastlane/metadata/android/ru-RU/changelogs/40101040.txt new file mode 100644 index 0000000000..0fa9e956c0 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101040.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: улучшение и исправления ошибок! +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.4 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101050.txt b/fastlane/metadata/android/ru-RU/changelogs/40101050.txt new file mode 100644 index 0000000000..c40bcab325 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101050.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: исправление для 1.1.4 +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.5 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101060.txt b/fastlane/metadata/android/ru-RU/changelogs/40101060.txt new file mode 100644 index 0000000000..44be6599ec --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101060.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: исправление для 1.1.5 +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.6 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101070.txt b/fastlane/metadata/android/ru-RU/changelogs/40101070.txt new file mode 100644 index 0000000000..4a400e8dc6 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101070.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: бета-поддержка Пространств. Сжатие видео перед отправкой. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.7 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101080.txt b/fastlane/metadata/android/ru-RU/changelogs/40101080.txt new file mode 100644 index 0000000000..a695b9301d --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101080.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: Усовершенствованы Пространства! +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.8 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101090.txt b/fastlane/metadata/android/ru-RU/changelogs/40101090.txt new file mode 100644 index 0000000000..5233f3985b --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101090.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: добавлена поддержка сети gitter.im. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.9 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101100.txt b/fastlane/metadata/android/ru-RU/changelogs/40101100.txt new file mode 100644 index 0000000000..fa3e77adcd --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101100.txt @@ -0,0 +1,2 @@ +Основные изменения этой версии: обновлен внешний вид и новые возможности для пространств +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.10 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101110.txt b/fastlane/metadata/android/ru-RU/changelogs/40101110.txt new file mode 100644 index 0000000000..b5dcad40e2 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101110.txt @@ -0,0 +1,2 @@ +Основные изменения этой версии: обновлен внешний вид и новые возможности для пространств (bugfix для 1.1.10) +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.11 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101120.txt b/fastlane/metadata/android/ru-RU/changelogs/40101120.txt new file mode 100644 index 0000000000..b76827916d --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101120.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: обновление темы и стиля и исправления сбоев после видеовызова +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.12 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101130.txt b/fastlane/metadata/android/ru-RU/changelogs/40101130.txt new file mode 100644 index 0000000000..c1ed9005aa --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: улучшение стабильности и исправления ошибок. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101140.txt b/fastlane/metadata/android/ru-RU/changelogs/40101140.txt new file mode 100644 index 0000000000..1c8c7cb356 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Основные изменения в этой версии: исправление проблемы с зашифрованными сообщениями. +Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/ru-RU/full_description.txt b/fastlane/metadata/android/ru-RU/full_description.txt index 2ac7f9be54..3d21b20a90 100644 --- a/fastlane/metadata/android/ru-RU/full_description.txt +++ b/fastlane/metadata/android/ru-RU/full_description.txt @@ -1,30 +1,39 @@ -Element - это новый тип приложения для обмена сообщениями и совместной работы, которое: +Element - это одновременно безопасный мессенджер и приложение для совместной работы, которое идеально подходит для групповых чатов при удаленной работе. Это приложение для чатов использует сквозное шифрование для обеспечения мощных видеоконференций, обмена файлами и голосовых звонков. -1. Позволяет вам контролировать вашу конфиденциальность -2. Позволяет общаться с кем угодно в сети Matrix и даже за ее пределами за счет интеграции с такими приложениями, как Slack -3. Защищает вас от рекламы, данных и огороженных стеной садов -4. Обеспечивает безопасность с помощью сквозного шифрования с перекрестной подписью для проверки других пользователей +Особенности Element включают: +- Передовые средства онлайн-общения +- Полностью зашифрованные сообщения, обеспечивающие безопасное корпоративное общение даже для удаленных работников +- Децентрализованный чат на базе платформы Matrix с открытым исходным кодом +- Безопасный обмен файлами с зашифрованными данными при управлении проектами +- Видеочаты с VoIP и совместным использованием экрана +- Простая интеграция с вашими любимыми инструментами для совместной работы в Интернете, средствами управления проектами, VoIP-сервисами и другими приложениями для обмена сообщениями в команде. -Element полностью отличается от других приложений для обмена сообщениями и совместной работы, потому что он децентрализован и имеет открытый исходный код. +Element полностью отличается от других приложений для обмена сообщениями и совместной работы. Он работает на базе Matrix, открытой сети для безопасного обмена сообщениями и децентрализованного общения. Он позволяет самостоятельно размещать свои данные и сообщения, предоставляя пользователям максимальный контроль над ними. -Element позволяет вам самостоятельно размещать или выбирать хост-узел, чтобы у вас была конфиденциальность, право собственности и контроль над своими данными и разговорами. Он предоставляет вам доступ к открытой сети, поэтому вы не ограничены общением исключительно с пользователями Element. И он очень надежен и безопаснен. +Приватность и зашифрованный обмен сообщениями. +Element защищает вас от нежелательной рекламы, сбора данных и "садов". Он также защищает все ваши данные, видео- и голосовую связь один на один благодаря сквозному шифрованию и перекрестной проверке устройств. -Element может делать все это, потому что он работает на Matrix - стандарте открытого, децентрализованного общения. +Element дает вам контроль над вашей конфиденциальностью, позволяя безопасно общаться с любым человеком в сети Matrix или с другими инструментами совместной работы благодаря интеграции с такими приложениями, как Slack. -Element предоставляет вам полный контроль, позволяя выбрать поставщиков услуг, обслуживающих серверы с вашими беседами. Вы свободны выбрать любой способ размещения прямо из приложения Element: +Element может быть размещен самостоятельно. +Чтобы обеспечить больший контроль над конфиденциальными данными и разговорами, Element может быть размещен самостоятельно или вы можете выбрать любой хост на базе Matrix - стандарт децентрализованного общения с открытым исходным кодом. Element обеспечивает конфиденциальность, соответствие требованиям безопасности и гибкость интеграции. -1. Получить бесплатную учетную запись на общедоступном сервере matrix.org, размещенном разработчиками Matrix, или выберите один из тысяч общедоступных серверов, размещенных волонтерами. -2. Разместить свою учетную запись на собственном сервере -3. Зарегистрироваться на индивидуальном сервере, просто подписавшись на услуги платформы Element Matrix Services +Владение своими данными. +Вы сами решаете, где хранить свои данные и сообщения. Без риска добычи данных или доступа третьих лиц. -Почему выбирают Element? +Element дает вам возможность контролировать ситуацию различными способами: +1. Получить бесплатный аккаунт на публичном сервере matrix.org, размещенном разработчиками Matrix, или выбрать один из тысяч публичных серверов, размещенных добровольцами. +2. Самостоятельно разместить свою учетную запись, запустив сервер на собственной IT-инфраструктуре. +3. Зарегистрировать учетную запись на пользовательском сервере, просто подписавшись на хостинг-платформу Element Matrix Services. -СОБСТВЕННЫЕ ДАННЫЕ: Вы решаете, где хранить свои данные и сообщения. Вы владеете ими и контролируете их, а не какая-то мегакорпорация, что собирает ваши данные и предоставляет сторонним лицам доступ к ним. +Открытый обмен сообщениями и сотрудничество. +Вы можете общаться с любым человеком в сети Matrix, независимо от того, использует ли он Element, другое приложение Matrix или даже если он использует другое приложение для обмена сообщениями. -ОТКРЫТОЕ ОБЩЕНИЕ И СОТРУДНИЧЕСТВО: Вы можете общаться с кем угодно в сети Matrix, независимо от того, используют ли они приложение Element или другое приложение Matrix, и даже если они используют другую систему обмена сообщениями, такую как Slack, IRC или XMPP. +Супербезопасно +Настоящее сквозное шифрование (только участники разговора могут расшифровывать сообщения) и проверка устройств с перекрестной подписью. -СУПЕР-БЕЗОПАСНОСТЬ: Настоящее сквозное шифрование (только участники разговора могут расшифровывать сообщения) и перекрестная подпись для проверки устройств участников разговора. +Полная коммуникация и интеграция. +Обмен сообщениями, голосовые и видеозвонки, совместное использование файлов, совместное использование экрана и целый ряд интеграций, ботов и виджетов. Создавайте комнаты, сообщества, оставайтесь на связи и выполняйте задачи. -ПОЛНАЯ КОММУНИКАЦИЯ: Обмен сообщениями, голосовые и видеозвонки, совместное использование файлов, совместное использование экрана и целый ряд интеграций, ботов и виджетов. Создавайте комнаты, сообщества, оставайтесь на связи и добивайтесь результатов. - -ВЫ ВЕЗДЕ: Оставайтесь на связи, где бы вы ни находились, благодаря полностью синхронизированной истории сообщений на всех ваших устройствах и в Интернете по адресу https://app.element.io. +Восстанавливайте связь с того места, где остановились. +Оставайтесь на связи, где бы вы ни находились, с полностью синхронизированной историей сообщений на всех ваших устройствах и в Интернете по адресу https://app.element.io diff --git a/fastlane/metadata/android/ru-RU/short_description.txt b/fastlane/metadata/android/ru-RU/short_description.txt index 64452ed22d..8f7566d208 100644 --- a/fastlane/metadata/android/ru-RU/short_description.txt +++ b/fastlane/metadata/android/ru-RU/short_description.txt @@ -1 +1 @@ -Защищённый децентрализованный чат и звонки. Держите ваши данные в безопасности. +Групповой мессенджер - зашифрованные сообщения, групповые беседы и видеовызовы diff --git a/fastlane/metadata/android/ru-RU/title.txt b/fastlane/metadata/android/ru-RU/title.txt index 00e488e69f..b7b25082a4 100644 --- a/fastlane/metadata/android/ru-RU/title.txt +++ b/fastlane/metadata/android/ru-RU/title.txt @@ -1 +1 @@ -Element (ранее Riot.im) +Element - Безопасный мессенджер diff --git a/fastlane/metadata/android/uk/changelogs/40101120.txt b/fastlane/metadata/android/uk/changelogs/40101120.txt new file mode 100644 index 0000000000..f738d32b83 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40101120.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: оновлення теми та стилю та виправлення збоїв після відеовиклику +Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.12 diff --git a/fastlane/metadata/android/uk/changelogs/40101130.txt b/fastlane/metadata/android/uk/changelogs/40101130.txt new file mode 100644 index 0000000000..fd6dcb9e97 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40101130.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: в поліпшення стабільності та виправлення помилок. +Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/uk/changelogs/40101140.txt b/fastlane/metadata/android/uk/changelogs/40101140.txt new file mode 100644 index 0000000000..f2040a29d8 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40101140.txt @@ -0,0 +1,2 @@ +Основні зміни у цій версії: виправлення проблеми із зашифрованими повідомленнями. +Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.14 diff --git a/fastlane/metadata/android/zh-TW/changelogs/40101130.txt b/fastlane/metadata/android/zh-TW/changelogs/40101130.txt new file mode 100644 index 0000000000..88f439281f --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40101130.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:主要是穩定性與臭蟲修復更新。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.13 diff --git a/fastlane/metadata/android/zh-TW/changelogs/40101140.txt b/fastlane/metadata/android/zh-TW/changelogs/40101140.txt new file mode 100644 index 0000000000..3eb5aa35ed --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40101140.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:修復關於加密訊息的問題。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.14 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 10c2db4535..b49236c338 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 @@ -40,7 +40,63 @@ data class HomeServerCapabilities( */ val roomVersions: RoomVersionCapabilities? = null ) { + + enum class RoomCapabilitySupport { + SUPPORTED, + SUPPORTED_UNSTABLE, + UNSUPPORTED, + UNKNOWN + } + + /** + * Check if a feature is supported by the homeserver. + * @return + * UNKNOWN if the server does not implement room caps + * UNSUPPORTED if this feature is not supported + * SUPPORTED if this feature is supported by a stable version + * SUPPORTED_UNSTABLE if this feature is supported by an unstable version + * (unstable version should only be used for dev/experimental purpose) + */ + fun isFeatureSupported(feature: String): RoomCapabilitySupport { + if (roomVersions?.capabilities == null) return RoomCapabilitySupport.UNKNOWN + val info = roomVersions.capabilities[feature] ?: return RoomCapabilitySupport.UNSUPPORTED + + val preferred = info.preferred ?: info.support.lastOrNull() + val versionCap = roomVersions.supportedVersion.firstOrNull { it.version == preferred } + + return when { + versionCap == null -> { + RoomCapabilitySupport.UNKNOWN + } + versionCap.status == RoomVersionStatus.STABLE -> { + RoomCapabilitySupport.SUPPORTED + } + else -> { + RoomCapabilitySupport.SUPPORTED_UNSTABLE + } + } + } + fun isFeatureSupported(feature: String, byRoomVersion: String): Boolean { + if (roomVersions?.capabilities == null) return false + val info = roomVersions.capabilities[feature] ?: return false + + return info.preferred == byRoomVersion || info.support.contains(byRoomVersion) + } + + /** + * Use this method to know if you should force a version when creating + * a room that requires this feature. + * You can also use #isFeatureSupported prior to this call to check if the + * feature is supported and report some feedback to user. + */ + fun versionOverrideForFeature(feature: String) : String? { + val cap = roomVersions?.capabilities?.get(feature) + return cap?.preferred ?: cap?.support?.lastOrNull() + } + companion object { const val MAX_UPLOAD_FILE_SIZE_UNKNOWN = -1L + const val ROOM_CAP_KNOCK = "knock" + const val ROOM_CAP_RESTRICTED = "restricted" } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/RoomVersionModel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/RoomVersionModel.kt index 7798b4cc63..9f8e9aa1d1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/RoomVersionModel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/RoomVersionModel.kt @@ -18,7 +18,9 @@ package org.matrix.android.sdk.api.session.homeserver data class RoomVersionCapabilities( val defaultRoomVersion: String, - val supportedVersion: List + val supportedVersion: List, + // Keys are capabilities defined per spec, as for now knock or restricted + val capabilities: Map? ) data class RoomVersionInfo( @@ -26,6 +28,11 @@ data class RoomVersionInfo( val status: RoomVersionStatus ) +data class RoomCapabilitySupport( + val preferred: String?, + val support: List +) + enum class RoomVersionStatus { STABLE, UNSTABLE diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt index c46d7d0fd2..5667906000 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt @@ -22,7 +22,6 @@ import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility -import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM open class CreateRoomParams { @@ -162,7 +161,7 @@ open class CreateRoomParams { var roomVersion: String? = null - var joinRuleRestricted: List? = null + var featurePreset: RoomFeaturePreset? = null companion object { private const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt new file mode 100644 index 0000000000..f5f722d783 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2020 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.api.session.room.model.create + +import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities +import org.matrix.android.sdk.api.session.room.model.GuestAccess +import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent + +interface RoomFeaturePreset { + + fun updateRoomParams(params: CreateRoomParams) + + fun setupInitialStates(): List? +} + +class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, val restrictedList: List) : RoomFeaturePreset { + + override fun updateRoomParams(params: CreateRoomParams) { + params.historyVisibility = params.historyVisibility ?: RoomHistoryVisibility.SHARED + params.guestAccess = params.guestAccess ?: GuestAccess.Forbidden + params.roomVersion = homeServerCapabilities.versionOverrideForFeature(HomeServerCapabilities.ROOM_CAP_RESTRICTED) + } + + override fun setupInitialStates(): List? { + return listOf( + Event( + type = EventType.STATE_ROOM_JOIN_RULES, + stateKey = "", + content = RoomJoinRulesContent( + _joinRules = RoomJoinRules.RESTRICTED.value, + allowList = restrictedList + ).toContent() + ) + ) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt index e614ea91d6..4d3f95233d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt @@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.Optional @@ -53,7 +54,7 @@ interface StateService { /** * Update the join rule and/or the guest access */ - suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?) + suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, allowList: List? = null) /** * Update the avatar of the room @@ -91,4 +92,8 @@ interface StateService { * @param eventTypes Set of eventType to observe. If empty, all state events will be observed */ fun getStateEventsLive(eventTypes: Set, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData> + + suspend fun setJoinRulePublic() + suspend fun setJoinRuleInviteOnly() + suspend fun setJoinRuleRestricted(allowList: List) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index ffa090b76a..4744785f8e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -289,12 +289,12 @@ internal class RealmCryptoStore @Inject constructor( val devicesToDelete = ArrayList() userEntity.devices.iterator().forEach { deviceInfoEntity -> if (deviceInfoEntity.deviceId !in deviceIds) { - Timber.d("Remove device ${deviceInfoEntity.deviceId} of user $userId") devicesToDelete.add(deviceInfoEntity) } } while (devicesToDelete.isNotEmpty()) { val device = devicesToDelete.removeAt(0) + Timber.d("Remove device ${device.deviceId} of user $userId") device.deleteOnCascade() } // Then update existing devices or add new one 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 2575cdef26..8b6d263f8c 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 @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.database.mapper import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities +import org.matrix.android.sdk.api.session.homeserver.RoomCapabilitySupport import org.matrix.android.sdk.api.session.homeserver.RoomVersionCapabilities import org.matrix.android.sdk.api.session.homeserver.RoomVersionInfo import org.matrix.android.sdk.api.session.homeserver.RoomVersionStatus @@ -45,19 +46,28 @@ internal object HomeServerCapabilitiesMapper { roomVersionsJson ?: return null return tryOrNull { - MoshiProvider.providesMoshi().adapter(RoomVersions::class.java).fromJson(roomVersionsJson)?.let { + MoshiProvider.providesMoshi().adapter(RoomVersions::class.java).fromJson(roomVersionsJson)?.let { roomVersions -> RoomVersionCapabilities( - defaultRoomVersion = it.default ?: DefaultRoomVersionService.DEFAULT_ROOM_VERSION, - supportedVersion = it.available.entries.map { entry -> - RoomVersionInfo( - version = entry.key, - status = if (entry.value == "stable") { - RoomVersionStatus.STABLE - } else { - RoomVersionStatus.UNSTABLE - } - ) - } + defaultRoomVersion = roomVersions.default ?: DefaultRoomVersionService.DEFAULT_ROOM_VERSION, + supportedVersion = roomVersions.available?.entries?.map { entry -> + RoomVersionInfo(entry.key, RoomVersionStatus.STABLE + .takeIf { entry.value == "stable" } + ?: RoomVersionStatus.UNSTABLE) + }.orEmpty(), + capabilities = roomVersions.roomCapabilities?.entries?.mapNotNull { entry -> + (entry.value as? Map<*, *>)?.let { + val preferred = it["preferred"] as? String ?: return@mapNotNull null + val support = (it["support"] as? List<*>)?.filterIsInstance() + entry.key to RoomCapabilitySupport(preferred, support.orEmpty()) + } + }?.toMap() + // Just for debug purpose +// ?: mapOf( +// HomeServerCapabilities.ROOM_CAP_RESTRICTED to RoomCapabilitySupport( +// preferred = null, +// support = listOf("org.matrix.msc3083") +// ) +// ) ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt index c4bc09a233..1fe4f9d90a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetCapabilitiesResult.kt @@ -70,7 +70,22 @@ internal data class RoomVersions( * Required. A detailed description of the room versions the server supports. */ @Json(name = "available") - val available: JsonDict + val available: JsonDict? = null, + + /** + * "room_capabilities": { + * "knock" : { + * "preferred": "7", + * "support" : ["7"] + * }, + * "restricted" : { + * "preferred": "9", + * "support" : ["8", "9"] + * } + * } + */ + @Json(name = "room_capabilities") + val roomCapabilities: JsonDict? = null ) // The spec says: If not present, the client should assume that password changes are possible via the API diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt index 82565d8118..21f55bbc42 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt @@ -17,17 +17,24 @@ package org.matrix.android.sdk.internal.session.permalinks import org.matrix.android.sdk.api.MatrixPatterns.getDomain +import org.matrix.android.sdk.api.query.QueryStringValue +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent +import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.room.RoomGetter +import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource import java.net.URLEncoder import javax.inject.Inject import javax.inject.Provider internal class ViaParameterFinder @Inject constructor( @UserId private val userId: String, - private val roomGetterProvider: Provider + private val roomGetterProvider: Provider, + private val stateEventDataSource: StateEventDataSource ) { fun computeViaParams(roomId: String, max: Int): List { @@ -70,4 +77,28 @@ internal class ViaParameterFinder @Inject constructor( .orEmpty() .toSet() } + + fun computeViaParamsForRestricted(roomId: String, max: Int): List { + val userThatCanInvite = roomGetterProvider.get().getRoom(roomId) + ?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) }) + ?.map { it.userId } + ?.filter { userCanInvite(userId, roomId) } + .orEmpty() + .toSet() + + return userThatCanInvite.map { it.getDomain() } + .groupBy { it } + .mapValues { it.value.size } + .toMutableMap() + .let { map -> map.keys.sortedByDescending { map[it] } } + .take(max) + } + + fun userCanInvite(userId: String, roomId: String): Boolean { + val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) + ?.content?.toModel() + ?.let { PowerLevelsHelper(it) } + + return powerLevelsHelper?.isUserAbleToInvite(userId) ?: false + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt index 2c04759b22..9bb3899f2f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt @@ -17,16 +17,10 @@ package org.matrix.android.sdk.internal.session.room.create import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.identity.IdentityServiceError import org.matrix.android.sdk.api.session.identity.toMedium -import org.matrix.android.sdk.api.session.room.model.GuestAccess -import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility -import org.matrix.android.sdk.api.session.room.model.RoomJoinRules -import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.util.MimeTypes import org.matrix.android.sdk.internal.crypto.DeviceListManager @@ -45,7 +39,6 @@ import javax.inject.Inject internal class CreateRoomBodyBuilder @Inject constructor( private val ensureIdentityTokenTask: EnsureIdentityTokenTask, - private val crossSigningService: CrossSigningService, private val deviceListManager: DeviceListManager, private val identityStore: IdentityStore, private val fileUploader: FileUploader, @@ -76,19 +69,18 @@ internal class CreateRoomBodyBuilder @Inject constructor( } } - if (params.joinRuleRestricted != null) { - params.roomVersion = "org.matrix.msc3083" - params.historyVisibility = params.historyVisibility ?: RoomHistoryVisibility.SHARED - params.guestAccess = params.guestAccess ?: GuestAccess.Forbidden - } - val initialStates = (listOfNotNull( - buildEncryptionWithAlgorithmEvent(params), - buildHistoryVisibilityEvent(params), - buildAvatarEvent(params), - buildGuestAccess(params), - buildJoinRulesRestricted(params) - ) - + buildCustomInitialStates(params)) + params.featurePreset?.updateRoomParams(params) + + val initialStates = ( + listOfNotNull( + buildEncryptionWithAlgorithmEvent(params), + buildHistoryVisibilityEvent(params), + buildAvatarEvent(params), + buildGuestAccess(params) + ) + + params.featurePreset?.setupInitialStates().orEmpty() + + buildCustomInitialStates(params) + ) .takeIf { it.isNotEmpty() } return CreateRoomBody( @@ -158,20 +150,6 @@ internal class CreateRoomBodyBuilder @Inject constructor( } } - private fun buildJoinRulesRestricted(params: CreateRoomParams): Event? { - return params.joinRuleRestricted - ?.let { allowList -> - Event( - type = EventType.STATE_ROOM_JOIN_RULES, - stateKey = "", - content = RoomJoinRulesContent( - _joinRules = RoomJoinRules.RESTRICTED.value, - allowList = allowList - ).toContent() - ) - } - } - /** * Add the crypto algorithm to the room creation parameters. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt index ff2afb5d61..7eed22f65f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt @@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.session.room.state import android.net.Uri import androidx.lifecycle.LiveData import dagger.assisted.Assisted -import dagger.assisted.AssistedInject import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType @@ -29,17 +29,20 @@ import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent import org.matrix.android.sdk.api.session.room.state.StateService import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.MimeTypes import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.session.content.FileUploader -import java.lang.UnsupportedOperationException +import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String, private val stateEventDataSource: StateEventDataSource, private val sendStateTask: SendStateTask, - private val fileUploader: FileUploader + private val fileUploader: FileUploader, + private val viaParameterFinder: ViaParameterFinder ) : StateService { @AssistedFactory @@ -126,12 +129,19 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private ) } - override suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?) { + override suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, allowList: List?) { if (joinRules != null) { - if (joinRules == RoomJoinRules.RESTRICTED) throw UnsupportedOperationException("No yet supported") + val body = if (joinRules == RoomJoinRules.RESTRICTED) { + RoomJoinRulesContent( + _joinRules = RoomJoinRules.RESTRICTED.value, + allowList = allowList + ).toContent() + } else { + mapOf("join_rule" to joinRules) + } sendStateEvent( eventType = EventType.STATE_ROOM_JOIN_RULES, - body = mapOf("join_rule" to joinRules), + body = body, stateKey = null ) } @@ -160,4 +170,20 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private stateKey = null ) } + + override suspend fun setJoinRulePublic() { + updateJoinRule(RoomJoinRules.PUBLIC, null) + } + + override suspend fun setJoinRuleInviteOnly() { + updateJoinRule(RoomJoinRules.INVITE, null) + } + + override suspend fun setJoinRuleRestricted(allowList: List) { + // we need to compute correct via parameters and check if PL are correct + val allowEntries = allowList.map { spaceId -> + RoomJoinRulesAllowEntry(spaceId, viaParameterFinder.computeViaParamsForRestricted(spaceId, 3)) + } + updateJoinRule(RoomJoinRules.RESTRICTED, null, allowEntries) + } } diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt index 70eea6c26e..391140b9f3 100644 --- a/tools/check/forbidden_strings_in_code.txt +++ b/tools/check/forbidden_strings_in_code.txt @@ -162,7 +162,7 @@ Formatter\.formatShortFileSize===1 # android\.text\.TextUtils ### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt -enum class===103 +enum class===105 ### Do not import temporary legacy classes import org.matrix.android.sdk.internal.legacy.riot===3 diff --git a/vector/build.gradle b/vector/build.gradle index de641f1799..a6adafefe1 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -14,7 +14,7 @@ kapt { // Note: 2 digits max for each value ext.versionMajor = 1 ext.versionMinor = 1 -ext.versionPatch = 15 +ext.versionPatch = 16 ext.scVersion = 39 diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 1ae30450b0..af8b5a888a 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -225,6 +225,7 @@ + diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 0a931868b1..cce0c2a66f 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -108,6 +108,8 @@ import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment import im.vector.app.features.roomprofile.members.RoomMemberListFragment import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment import im.vector.app.features.roomprofile.settings.RoomSettingsFragment +import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleChooseRestrictedFragment +import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleFragment import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment @@ -804,4 +806,14 @@ interface FragmentModule { @IntoMap @FragmentKey(SpaceManageRoomsFragment::class) fun bindSpaceManageRoomsFragment(fragment: SpaceManageRoomsFragment): Fragment + + @Binds + @IntoMap + @FragmentKey(RoomJoinRuleFragment::class) + fun bindRoomJoinRuleFragment(fragment: RoomJoinRuleFragment): Fragment + + @Binds + @IntoMap + @FragmentKey(RoomJoinRuleChooseRestrictedFragment::class) + fun bindRoomJoinRuleChooseRestrictedFragment(fragment: RoomJoinRuleChooseRestrictedFragment): Fragment } diff --git a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt index 2a2c8908b0..2ec330efe6 100644 --- a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt +++ b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt @@ -77,6 +77,7 @@ import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet import im.vector.app.features.roomprofile.RoomProfileActivity import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet +import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet import im.vector.app.features.settings.VectorSettingsActivity import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet @@ -169,6 +170,7 @@ interface ScreenComponent { fun inject(activity: SpaceCreationActivity) fun inject(activity: SpaceExploreActivity) fun inject(activity: SpaceManageActivity) + fun inject(activity: RoomJoinRuleActivity) /* ========================================================================================== * BottomSheets diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt index 0f8f202a7d..6826ae6afd 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageRecorderView.kt @@ -328,11 +328,11 @@ class VoiceMessageRecorderView @JvmOverloads constructor( } } - private fun renderRecordingWaveform(amplitudeList: List) { - views.voicePlaybackWaveform.apply { - post { - amplitudeList.forEach { amplitude -> - update(amplitude) + private fun renderRecordingWaveform(amplitudeList: Array) { + post { + views.voicePlaybackWaveform.apply { + amplitudeList.iterator().forEach { + update(it) } } } @@ -409,7 +409,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor( scaleX = 1f scaleY = 1f translationX = 0f - translationY = 0f + translationY = 0f } isCancelled?.let { callback?.onVoiceRecordingEnded(it) @@ -514,7 +514,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor( override fun onUpdate(state: VoiceMessagePlaybackTracker.Listener.State) { when (state) { is VoiceMessagePlaybackTracker.Listener.State.Recording -> { - renderRecordingWaveform(state.amplitudeList) + renderRecordingWaveform(state.amplitudeList.toTypedArray()) } is VoiceMessagePlaybackTracker.Listener.State.Playing -> { views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt index 6e0aabb0f2..2fa210a748 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomBottomSheet.kt @@ -40,10 +40,17 @@ class MigrateRoomBottomSheet : VectorBaseBottomSheetDialogFragment(), MigrateRoomViewModel.Factory { + enum class MigrationReason { + MANUAL, + FOR_RESTRICTED + } + @Parcelize data class Args( val roomId: String, - val newVersion: String + val newVersion: String, + val reason: MigrationReason = MigrationReason.MANUAL, + val customDescription: CharSequence? = null ) : Parcelable @Inject @@ -62,11 +69,22 @@ class MigrateRoomBottomSheet : override fun invalidate() = withState(viewModel) { state -> views.headerText.setText(if (state.isPublic) R.string.upgrade_public_room else R.string.upgrade_private_room) - views.upgradeFromTo.text = getString(R.string.upgrade_public_room_from_to, state.currentVersion, state.newVersion) - views.autoInviteSwitch.isVisible = !state.isPublic && state.otherMemberCount > 0 + if (state.migrationReason == MigrationReason.MANUAL) { + views.descriptionText.text = getString(R.string.upgrade_room_warning) + views.upgradeFromTo.text = getString(R.string.upgrade_public_room_from_to, state.currentVersion, state.newVersion) + } else if (state.migrationReason == MigrationReason.FOR_RESTRICTED) { + views.descriptionText.setTextOrHide(state.customDescription) + views.upgradeFromTo.text = getString(R.string.upgrade_room_for_restricted_note) + } - views.autoUpdateParent.isVisible = state.knownParents.isNotEmpty() + if (state.autoMigrateMembersAndParents) { + views.autoUpdateParent.isVisible = false + views.autoInviteSwitch.isVisible = false + } else { + views.autoInviteSwitch.isVisible = !state.isPublic && state.otherMemberCount > 0 + views.autoUpdateParent.isVisible = state.knownParents.isNotEmpty() + } when (state.upgradingStatus) { is Loading -> { @@ -143,9 +161,12 @@ class MigrateRoomBottomSheet : const val REQUEST_KEY = "MigrateRoomBottomSheetRequest" const val BUNDLE_KEY_REPLACEMENT_ROOM = "BUNDLE_KEY_REPLACEMENT_ROOM" - fun newInstance(roomId: String, newVersion: String): MigrateRoomBottomSheet { + fun newInstance(roomId: String, newVersion: String, + reason: MigrationReason = MigrationReason.MANUAL, + customDescription: CharSequence? = null + ): MigrateRoomBottomSheet { return MigrateRoomBottomSheet().apply { - setArguments(Args(roomId, newVersion)) + setArguments(Args(roomId, newVersion, reason, customDescription)) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewModel.kt index 231bb319f0..3dc5d0e3ba 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewModel.kt @@ -90,11 +90,23 @@ class MigrateRoomViewModel @AssistedInject constructor( copy(upgradingStatus = Loading()) } session.coroutineScope.launch { + val userToInvite = if (state.autoMigrateMembersAndParents) { + summary?.otherMemberIds?.takeIf { !state.isPublic } + } else { + summary?.otherMemberIds?.takeIf { state.shouldIssueInvites } + }.orEmpty() + + val parentSpaceToUpdate = if (state.autoMigrateMembersAndParents) { + summary?.flattenParentIds + } else { + summary?.flattenParentIds?.takeIf { state.shouldUpdateKnownParents } + }.orEmpty() + val result = upgradeRoomViewModelTask.execute(UpgradeRoomViewModelTask.Params( roomId = state.roomId, newVersion = state.newVersion, - userIdsToAutoInvite = summary?.otherMemberIds?.takeIf { state.shouldIssueInvites } ?: emptyList(), - parentSpaceToUpdate = summary?.flattenParentIds?.takeIf { state.shouldUpdateKnownParents } ?: emptyList(), + userIdsToAutoInvite = userToInvite, + parentSpaceToUpdate = parentSpaceToUpdate, progressReporter = { indeterminate, progress, total -> setState { copy( diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewState.kt index e3936de42f..e3ea98682b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/upgrade/MigrateRoomViewState.kt @@ -23,6 +23,7 @@ import com.airbnb.mvrx.Uninitialized data class MigrateRoomViewState( val roomId: String, val newVersion: String, + val customDescription: CharSequence? = null, val currentVersion: String? = null, val isPublic: Boolean = false, val shouldIssueInvites: Boolean = false, @@ -32,10 +33,15 @@ data class MigrateRoomViewState( val upgradingStatus: Async = Uninitialized, val upgradingProgress: Int = 0, val upgradingProgressTotal: Int = 0, - val upgradingProgressIndeterminate: Boolean = true + val upgradingProgressIndeterminate: Boolean = true, + val migrationReason: MigrateRoomBottomSheet.MigrationReason = MigrateRoomBottomSheet.MigrationReason.MANUAL, + val autoMigrateMembersAndParents: Boolean = false ) : MvRxState { constructor(args: MigrateRoomBottomSheet.Args) : this( roomId = args.roomId, - newVersion = args.newVersion + newVersion = args.newVersion, + migrationReason = args.reason, + autoMigrateMembersAndParents = args.reason == MigrateRoomBottomSheet.MigrationReason.FOR_RESTRICTED, + customDescription = args.customDescription ) } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomAction.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomAction.kt index b50c56e1db..a44a0206aa 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomAction.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomAction.kt @@ -18,12 +18,13 @@ package im.vector.app.features.roomdirectory.createroom import android.net.Uri import im.vector.app.core.platform.VectorViewModelAction +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules sealed class CreateRoomAction : VectorViewModelAction { data class SetAvatar(val imageUri: Uri?) : CreateRoomAction() data class SetName(val name: String) : CreateRoomAction() data class SetTopic(val topic: String) : CreateRoomAction() - data class SetIsPublic(val isPublic: Boolean) : CreateRoomAction() + data class SetVisibility(val rule: RoomJoinRules) : CreateRoomAction() data class SetRoomAliasLocalPart(val aliasLocalPart: String) : CreateRoomAction() data class SetIsEncrypted(val isEncrypted: Boolean) : CreateRoomAction() diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt index d7fc324f52..cc133e86f7 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt @@ -21,6 +21,7 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import im.vector.app.R import im.vector.app.core.epoxy.dividerItem +import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.settingsSectionTitleItem import im.vector.app.features.form.formAdvancedToggleItem @@ -30,6 +31,7 @@ import im.vector.app.features.form.formSubmitButtonItem import im.vector.app.features.form.formSwitchItem import im.vector.app.features.settings.VectorPreferences import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import javax.inject.Inject class CreateRoomController @Inject constructor( @@ -92,24 +94,56 @@ class CreateRoomController @Inject constructor( settingsSectionTitleItem { id("settingsSection") titleResId(R.string.create_room_settings_section) + id("visibility") + titleResId(R.string.room_settings_room_access_title) } - formSwitchItem { - id("public") - enabled(enableFormElement) - title(host.stringProvider.getString(R.string.create_room_public_title)) - summary(host.stringProvider.getString(R.string.create_room_public_description)) - switchChecked(viewState.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public) - - listener { value -> - host.listener?.setIsPublic(value) + when (viewState.roomJoinRules) { + RoomJoinRules.INVITE -> { + buildProfileAction( + id = "joinRule", + title = stringProvider.getString(R.string.room_settings_room_access_private_title), + subtitle = stringProvider.getString(R.string.room_settings_room_access_private_description), + divider = false, + editable = true, + action = { host.listener?.selectVisibility() } + ) + } + RoomJoinRules.PUBLIC -> { + buildProfileAction( + id = "joinRule", + title = stringProvider.getString(R.string.room_settings_room_access_public_title), + subtitle = stringProvider.getString(R.string.room_settings_room_access_public_description), + divider = false, + editable = true, + action = { host.listener?.selectVisibility() } + ) + } + RoomJoinRules.RESTRICTED -> { + buildProfileAction( + id = "joinRule", + title = stringProvider.getString(R.string.room_settings_room_access_restricted_title), + subtitle = stringProvider.getString(R.string.room_create_member_of_space_name_can_join, viewState.parentSpaceSummary?.displayName), + divider = false, + editable = true, + action = { host.listener?.selectVisibility() } + ) + } + else -> { + // not yet supported } } - if (viewState.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public) { + + settingsSectionTitleItem { + id("settingsSection") + titleResId(R.string.create_room_settings_section) + } + + if (viewState.roomJoinRules == RoomJoinRules.PUBLIC) { // Room alias for public room formEditTextItem { id("alias") enabled(enableFormElement) - value(viewState.roomVisibilityType.aliasLocalPart) + value(viewState.aliasLocalPart) suffixText(":" + viewState.homeServerName) prefixText("#") hint(host.stringProvider.getString(R.string.room_alias_address_hint)) @@ -144,9 +178,9 @@ class CreateRoomController @Inject constructor( } } } - dividerItem { - id("divider1") - } +// dividerItem { +// id("divider1") +// } formAdvancedToggleItem { id("showAdvanced") title(host.stringProvider.getString(if (viewState.showAdvanced) R.string.hide_advanced else R.string.show_advanced)) @@ -177,7 +211,7 @@ class CreateRoomController @Inject constructor( fun onAvatarChange() fun onNameChange(newName: String) fun onTopicChange(newTopic: String) - fun setIsPublic(isPublic: Boolean) + fun selectVisibility() fun setAliasLocalPart(aliasLocalPart: String) fun setIsEncrypted(isEncrypted: Boolean) fun toggleShowAdvanced() diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt index cb71d6cd7b..fdc2bd8562 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt @@ -40,9 +40,12 @@ import im.vector.app.core.resources.ColorProvider import im.vector.app.databinding.FragmentCreateRoomBinding import im.vector.app.features.roomdirectory.RoomDirectorySharedAction import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel +import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet +import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleSharedActionViewModel +import im.vector.app.features.roomprofile.settings.joinrule.toOption import kotlinx.parcelize.Parcelize - import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import javax.inject.Inject @Parcelize @@ -64,6 +67,8 @@ class CreateRoomFragment @Inject constructor( private val viewModel: CreateRoomViewModel by fragmentViewModel() private val args: CreateRoomArgs by args() + private lateinit var roomJoinRuleSharedActionViewModel: RoomJoinRuleSharedActionViewModel + private val galleryOrCameraDialogHelper = GalleryOrCameraDialogHelper(this, colorProvider) override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentCreateRoomBinding { @@ -74,6 +79,7 @@ class CreateRoomFragment @Inject constructor( super.onViewCreated(view, savedInstanceState) vectorBaseActivity.setSupportActionBar(views.createRoomToolbar) sharedActionViewModel = activityViewModelProvider.get(RoomDirectorySharedActionViewModel::class.java) + setupRoomJoinRuleSharedActionViewModel() setupWaitingView() setupRecyclerView() views.createRoomClose.debouncedClicks { @@ -87,6 +93,16 @@ class CreateRoomFragment @Inject constructor( } } + private fun setupRoomJoinRuleSharedActionViewModel() { + roomJoinRuleSharedActionViewModel = activityViewModelProvider.get(RoomJoinRuleSharedActionViewModel::class.java) + roomJoinRuleSharedActionViewModel + .observe() + .subscribe { action -> + viewModel.handle(CreateRoomAction.SetVisibility(action.roomJoinRule)) + } + .disposeOnDestroyView() + } + override fun showFailure(throwable: Throwable) { // Note: RoomAliasError are displayed directly in the form if (throwable !is CreateRoomFailure.AliasError) { @@ -130,9 +146,19 @@ class CreateRoomFragment @Inject constructor( viewModel.handle(CreateRoomAction.SetTopic(newTopic)) } - override fun setIsPublic(isPublic: Boolean) { - viewModel.handle(CreateRoomAction.SetIsPublic(isPublic)) + override fun selectVisibility() = withState(viewModel) { state -> + + val allowed = if (state.supportsRestricted) { + listOf(RoomJoinRules.INVITE, RoomJoinRules.PUBLIC, RoomJoinRules.RESTRICTED) + } else { + listOf(RoomJoinRules.INVITE, RoomJoinRules.PUBLIC) + } + RoomJoinRuleBottomSheet.newInstance(state.roomJoinRules, allowed.map { it.toOption(false) }) + .show(childFragmentManager, "RoomJoinRuleBottomSheet") } +// override fun setIsPublic(isPublic: Boolean) { +// viewModel.handle(CreateRoomAction.SetIsPublic(isPublic)) +// } override fun setAliasLocalPart(aliasLocalPart: String) { viewModel.handle(CreateRoomAction.SetRoomAliasLocalPart(aliasLocalPart)) diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt index ff62136267..f40829e4b7 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt @@ -32,22 +32,28 @@ import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.raw.wellknown.getElementWellknown import im.vector.app.features.raw.wellknown.isE2EByDefault +import im.vector.app.features.settings.VectorPreferences import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixPatterns.getDomain import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.raw.RawService import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.api.session.room.alias.RoomAliasError import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset +import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset import timber.log.Timber class CreateRoomViewModel @AssistedInject constructor(@Assisted private val initialState: CreateRoomViewState, private val session: Session, - private val rawService: RawService + private val rawService: RawService, + private val vectorPreferences: VectorPreferences ) : VectorViewModel(initialState) { @AssistedFactory @@ -58,6 +64,27 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init init { initHomeServerName() initAdminE2eByDefault() + + val restrictedSupport = session.getHomeServerCapabilities().isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED) + val createRestricted = when (restrictedSupport) { + HomeServerCapabilities.RoomCapabilitySupport.SUPPORTED -> true + HomeServerCapabilities.RoomCapabilitySupport.SUPPORTED_UNSTABLE -> vectorPreferences.labsUseExperimentalRestricted() + else -> false + } + + val defaultJoinRules = if (initialState.parentSpaceId != null && createRestricted) { + RoomJoinRules.RESTRICTED + } else { + RoomJoinRules.INVITE + } + + setState { + copy( + supportsRestricted = createRestricted, + roomJoinRules = defaultJoinRules, + parentSpaceSummary = initialState.parentSpaceId?.let { session.getRoomSummary(it) } + ) + } } private fun initHomeServerName() { @@ -80,7 +107,7 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init setState { copy( - isEncrypted = roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Private && adminE2EByDefault, + isEncrypted = RoomJoinRules.INVITE == roomJoinRules && adminE2EByDefault, hsAdminHasDisabledE2E = !adminE2EByDefault ) } @@ -102,7 +129,7 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init is CreateRoomAction.SetAvatar -> setAvatar(action) is CreateRoomAction.SetName -> setName(action) is CreateRoomAction.SetTopic -> setTopic(action) - is CreateRoomAction.SetIsPublic -> setIsPublic(action) + is CreateRoomAction.SetVisibility -> setVisibility(action) is CreateRoomAction.SetRoomAliasLocalPart -> setRoomAliasLocalPart(action) is CreateRoomAction.SetIsEncrypted -> setIsEncrypted(action) is CreateRoomAction.Create -> doCreateRoom() @@ -149,35 +176,45 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init private fun setTopic(action: CreateRoomAction.SetTopic) = setState { copy(roomTopic = action.topic) } - private fun setIsPublic(action: CreateRoomAction.SetIsPublic) = setState { - if (action.isPublic) { - copy( - roomVisibilityType = CreateRoomViewState.RoomVisibilityType.Public(""), - // Reset any error in the form about alias - asyncCreateRoomRequest = Uninitialized, - isEncrypted = false - ) - } else { - copy( - roomVisibilityType = CreateRoomViewState.RoomVisibilityType.Private, - isEncrypted = adminE2EByDefault - ) + private fun setVisibility(action: CreateRoomAction.SetVisibility) = setState { + when (action.rule) { + RoomJoinRules.PUBLIC -> { + copy( + roomJoinRules = RoomJoinRules.PUBLIC, + // Reset any error in the form about alias + asyncCreateRoomRequest = Uninitialized, + isEncrypted = false + ) + } + RoomJoinRules.RESTRICTED -> { + copy( + roomJoinRules = RoomJoinRules.RESTRICTED, + // Reset any error in the form about alias + asyncCreateRoomRequest = Uninitialized, + isEncrypted = adminE2EByDefault + ) + } +// RoomJoinRules.INVITE, +// RoomJoinRules.KNOCK, +// RoomJoinRules.PRIVATE, + else -> { + // default to invite + copy( + roomJoinRules = RoomJoinRules.INVITE, + isEncrypted = adminE2EByDefault + ) + } } } private fun setRoomAliasLocalPart(action: CreateRoomAction.SetRoomAliasLocalPart) { - withState { state -> - if (state.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public) { - setState { - copy( - roomVisibilityType = CreateRoomViewState.RoomVisibilityType.Public(action.aliasLocalPart), - // Reset any error in the form about alias - asyncCreateRoomRequest = Uninitialized - ) - } - } + setState { + copy( + aliasLocalPart = action.aliasLocalPart, + // Reset any error in the form about alias + asyncCreateRoomRequest = Uninitialized + ) } - // Else ignore } private fun setIsEncrypted(action: CreateRoomAction.SetIsEncrypted) = setState { copy(isEncrypted = action.isEncrypted) } @@ -187,8 +224,7 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init return@withState } - if (state.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public - && state.roomVisibilityType.aliasLocalPart.isBlank()) { + if (state.roomJoinRules == RoomJoinRules.PUBLIC && state.aliasLocalPart.isNullOrBlank()) { // we require an alias for public rooms setState { copy(asyncCreateRoomRequest = Fail(CreateRoomFailure.AliasError(RoomAliasError.AliasIsBlank))) @@ -205,15 +241,30 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init name = state.roomName.takeIf { it.isNotBlank() } topic = state.roomTopic.takeIf { it.isNotBlank() } avatarUri = state.avatarUri - when (state.roomVisibilityType) { - is CreateRoomViewState.RoomVisibilityType.Public -> { + when (state.roomJoinRules) { + RoomJoinRules.PUBLIC -> { // Directory visibility visibility = RoomDirectoryVisibility.PUBLIC // Preset preset = CreateRoomPreset.PRESET_PUBLIC_CHAT - roomAliasName = state.roomVisibilityType.aliasLocalPart + roomAliasName = state.aliasLocalPart } - is CreateRoomViewState.RoomVisibilityType.Private -> { + RoomJoinRules.RESTRICTED -> { + state.parentSpaceId?.let { + featurePreset = RestrictedRoomPreset( + session.getHomeServerCapabilities(), + listOf(RoomJoinRulesAllowEntry( + state.parentSpaceId, + listOf(state.homeServerName) + )) + ) + } + } +// RoomJoinRules.KNOCK -> +// RoomJoinRules.PRIVATE -> +// RoomJoinRules.INVITE + else -> { + // by default create invite only // Directory visibility visibility = RoomDirectoryVisibility.PRIVATE // Preset diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewState.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewState.kt index f060e998ad..06742ea690 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewState.kt @@ -20,20 +20,24 @@ import android.net.Uri import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized -import org.matrix.android.sdk.api.extensions.orTrue +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomSummary data class CreateRoomViewState( val avatarUri: Uri? = null, val roomName: String = "", val roomTopic: String = "", - val roomVisibilityType: RoomVisibilityType = RoomVisibilityType.Private, + val roomJoinRules: RoomJoinRules = RoomJoinRules.INVITE, val isEncrypted: Boolean = false, val showAdvanced: Boolean = false, val disableFederation: Boolean = false, val homeServerName: String = "", val hsAdminHasDisabledE2E: Boolean = false, val asyncCreateRoomRequest: Async = Uninitialized, - val parentSpaceId: String? + val parentSpaceId: String?, + val parentSpaceSummary: RoomSummary? = null, + val supportsRestricted: Boolean = false, + val aliasLocalPart: String? = null ) : MvRxState { constructor(args: CreateRoomArgs) : this( @@ -47,10 +51,5 @@ data class CreateRoomViewState( fun isEmpty() = avatarUri == null && roomName.isEmpty() && roomTopic.isEmpty() - && (roomVisibilityType as? RoomVisibilityType.Public)?.aliasLocalPart?.isEmpty().orTrue() - - sealed class RoomVisibilityType { - object Private : RoomVisibilityType() - data class Public(val aliasLocalPart: String) : RoomVisibilityType() - } + && aliasLocalPart.isNullOrEmpty() } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt index 7dec6eaee7..b7821c056c 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt @@ -44,7 +44,7 @@ import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilitySharedActionViewModel -import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet +import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleSharedActionViewModel import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.util.toMatrixItem @@ -179,10 +179,8 @@ class RoomSettingsFragment @Inject constructor( .show(childFragmentManager, "RoomHistoryVisibilityBottomSheet") } - override fun onJoinRuleClicked() = withState(viewModel) { state -> - val currentJoinRule = state.newRoomJoinRules.newJoinRules ?: state.currentRoomJoinRules - RoomJoinRuleBottomSheet.newInstance(currentJoinRule) - .show(childFragmentManager, "RoomJoinRuleBottomSheet") + override fun onJoinRuleClicked() { + startActivity(RoomJoinRuleActivity.newIntent(requireContext(), roomProfileArgs.roomId)) } override fun onToggleGuestAccess() = withState(viewModel) { state -> diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt index 0a9c32e4c2..1265e7e5ee 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt @@ -27,6 +27,7 @@ import dagger.assisted.AssistedInject import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.powerlevel.PowerLevelsObservableFactory +import im.vector.app.features.settings.VectorPreferences import io.reactivex.Completable import io.reactivex.Observable import org.matrix.android.sdk.api.extensions.tryOrNull @@ -34,6 +35,7 @@ import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent @@ -44,6 +46,7 @@ import org.matrix.android.sdk.rx.rx import org.matrix.android.sdk.rx.unwrap class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: RoomSettingsViewState, + private val vectorPreferences: VectorPreferences, private val session: Session) : VectorViewModel(initialState) { @@ -73,6 +76,24 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: observeGuestAccess() observeRoomAvatar() observeState() + + val homeServerCapabilities = session.getHomeServerCapabilities() + val canUseRestricted = homeServerCapabilities + .isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED, room.getRoomVersion()) + + val restrictedSupport = homeServerCapabilities.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED) + val couldUpgradeToRestricted = when (restrictedSupport) { + HomeServerCapabilities.RoomCapabilitySupport.SUPPORTED -> true + HomeServerCapabilities.RoomCapabilitySupport.SUPPORTED_UNSTABLE -> vectorPreferences.labsUseExperimentalRestricted() + else -> false + } + + setState { + copy( + supportsRestricted = canUseRestricted, + canUpgradeToRestricted = couldUpgradeToRestricted + ) + } } private fun observeState() { @@ -247,8 +268,8 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: val summary = state.roomSummary.invoke() when (val avatarAction = state.avatarAction) { - RoomSettingsViewState.AvatarAction.None -> Unit - RoomSettingsViewState.AvatarAction.DeleteAvatar -> { + RoomSettingsViewState.AvatarAction.None -> Unit + RoomSettingsViewState.AvatarAction.DeleteAvatar -> { operationList.add(room.rx().deleteAvatar()) } is RoomSettingsViewState.AvatarAction.UpdateAvatar -> { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt index e220687878..403836b268 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewState.kt @@ -43,7 +43,9 @@ data class RoomSettingsViewState( val newHistoryVisibility: RoomHistoryVisibility? = null, val newRoomJoinRules: NewJoinRule = NewJoinRule(), val showSaveAction: Boolean = false, - val actionPermissions: ActionPermissions = ActionPermissions() + val actionPermissions: ActionPermissions = ActionPermissions(), + val supportsRestricted: Boolean = false, + val canUpgradeToRestricted: Boolean = false ) : MvRxState { constructor(args: RoomProfileArgs) : this(roomId = args.roomId) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleActivity.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleActivity.kt new file mode 100644 index 0000000000..21c39ad49d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleActivity.kt @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.roomprofile.settings.joinrule + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.core.view.isVisible +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MvRx +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.viewModel +import com.airbnb.mvrx.withState +import im.vector.app.R +import im.vector.app.core.di.ScreenComponent +import im.vector.app.core.error.ErrorFormatter +import im.vector.app.core.extensions.addFragment +import im.vector.app.core.extensions.commitTransaction +import im.vector.app.core.extensions.toMvRxBundle +import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.utils.toast +import im.vector.app.databinding.ActivitySimpleBinding +import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet +import im.vector.app.features.roomprofile.RoomProfileArgs +import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedActions +import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedEvents +import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState +import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel +import javax.inject.Inject + +class RoomJoinRuleActivity : VectorBaseActivity(), + RoomJoinRuleChooseRestrictedViewModel.Factory { + + override fun getBinding() = ActivitySimpleBinding.inflate(layoutInflater) + + private lateinit var roomProfileArgs: RoomProfileArgs + + @Inject + lateinit var allowListViewModelFactory: RoomJoinRuleChooseRestrictedViewModel.Factory + + @Inject + lateinit var errorFormatter: ErrorFormatter + + val viewModel: RoomJoinRuleChooseRestrictedViewModel by viewModel() + + override fun create(initialState: RoomJoinRuleChooseRestrictedState) = allowListViewModelFactory.create(initialState) + + override fun injectWith(injector: ScreenComponent) { + injector.inject(this) + } + + override fun initUiAndData() { + roomProfileArgs = intent?.extras?.getParcelable(MvRx.KEY_ARG) ?: return + if (isFirstCreation()) { + addFragment( + R.id.simpleFragmentContainer, + RoomJoinRuleFragment::class.java, + roomProfileArgs + ) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + viewModel.selectSubscribe(this, RoomJoinRuleChooseRestrictedState::updatingStatus) { + when (it) { + Uninitialized -> { + // nop + } + is Loading -> { + views.simpleActivityWaitingView.isVisible = true + } + is Success -> { + withState(viewModel) { state -> + if (state.didSwitchToReplacementRoom) { + // we should navigate to new room + navigator.openRoom(this, state.roomId, null, true) + } + finish() + } + } + is Fail -> { + views.simpleActivityWaitingView.isVisible = false + toast(errorFormatter.toHumanReadable(it.error)) + } + } + } + + viewModel.observeViewEvents { + when (it) { + RoomJoinRuleChooseRestrictedEvents.NavigateToChooseRestricted -> navigateToChooseRestricted() + is RoomJoinRuleChooseRestrictedEvents.NavigateToUpgradeRoom -> navigateToUpgradeRoom(it) + } + } + + supportFragmentManager.setFragmentResultListener(MigrateRoomBottomSheet.REQUEST_KEY, this) { _, bundle -> + bundle.getString(MigrateRoomBottomSheet.BUNDLE_KEY_REPLACEMENT_ROOM)?.let { replacementRoomId -> + viewModel.handle(RoomJoinRuleChooseRestrictedActions.SwitchToRoomAfterMigration(replacementRoomId)) + } + } + } + + private fun navigateToUpgradeRoom(events: RoomJoinRuleChooseRestrictedEvents.NavigateToUpgradeRoom) { + MigrateRoomBottomSheet.newInstance( + events.roomId, + events.toVersion, + MigrateRoomBottomSheet.MigrationReason.FOR_RESTRICTED, + events.description + ).show(supportFragmentManager, "migrate") + } + + private fun navigateToChooseRestricted() { + supportFragmentManager.commitTransaction { + setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out) + val tag = RoomJoinRuleChooseRestrictedFragment::class.simpleName + replace(R.id.simpleFragmentContainer, + RoomJoinRuleChooseRestrictedFragment::class.java, + this@RoomJoinRuleActivity.roomProfileArgs.toMvRxBundle(), + tag + ).addToBackStack(tag) + } + } + + companion object { + + fun newIntent(context: Context, roomId: String): Intent { + val roomProfileArgs = RoomProfileArgs(roomId) + return Intent(context, RoomJoinRuleActivity::class.java).apply { + putExtra(MvRx.KEY_ARG, roomProfileArgs) + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt new file mode 100644 index 0000000000..7adfc594b7 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.roomprofile.settings.joinrule + +import com.airbnb.epoxy.TypedEpoxyController +import im.vector.app.R +import im.vector.app.core.resources.ColorProvider +import im.vector.app.core.resources.StringProvider +import im.vector.app.core.ui.list.ItemStyle +import im.vector.app.core.ui.list.genericButtonItem +import im.vector.app.core.ui.list.genericFooterItem +import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import timber.log.Timber +import javax.inject.Inject + +class RoomJoinRuleAdvancedController @Inject constructor( + private val stringProvider: StringProvider, + private val colorProvider: ColorProvider, + private val avatarRenderer: AvatarRenderer +) : TypedEpoxyController() { + + interface InteractionListener { + fun didSelectRule(rules: RoomJoinRules) + } + + var interactionListener: InteractionListener? = null + + override fun buildModels(state: RoomJoinRuleChooseRestrictedState?) { + state ?: return + val choices = state.choices ?: return + + val host = this + + genericFooterItem { + id("header") + text(host.stringProvider.getString(R.string.room_settings_room_access_title)) + centered(false) + style(ItemStyle.TITLE) + textColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary)) + } + + genericFooterItem { + id("desc") + text(host.stringProvider.getString(R.string.decide_who_can_find_and_join)) + centered(false) + } + + // invite only + RoomJoinRuleRadioAction( + roomJoinRule = RoomJoinRules.INVITE, + description = stringProvider.getString(R.string.room_settings_room_access_private_description), + title = stringProvider.getString(R.string.room_settings_room_access_private_invite_only_title), + isSelected = state.currentRoomJoinRules == RoomJoinRules.INVITE + ).toRadioBottomSheetItem().let { + it.listener { + interactionListener?.didSelectRule(RoomJoinRules.INVITE) +// listener?.didSelectAction(action) + } + add(it) + } + + if (choices.firstOrNull { it.rule == RoomJoinRules.RESTRICTED } != null) { + val restrictedRule = choices.first { it.rule == RoomJoinRules.RESTRICTED } + Timber.w("##@@ ${state.updatedAllowList}") + spaceJoinRuleItem { + id("restricted") + avatarRenderer(host.avatarRenderer) + needUpgrade(restrictedRule.needUpgrade) + selected(state.currentRoomJoinRules == RoomJoinRules.RESTRICTED) + restrictedList(state.updatedAllowList) + listener { host.interactionListener?.didSelectRule(RoomJoinRules.RESTRICTED) } + } + } + + // Public + RoomJoinRuleRadioAction( + roomJoinRule = RoomJoinRules.PUBLIC, + description = stringProvider.getString(R.string.room_settings_room_access_public_description), + title = stringProvider.getString(R.string.room_settings_room_access_public_title), + isSelected = state.currentRoomJoinRules == RoomJoinRules.PUBLIC + ).toRadioBottomSheetItem().let { + it.listener { + interactionListener?.didSelectRule(RoomJoinRules.PUBLIC) + } + add(it) + } + + genericButtonItem { + id("save") + text("") + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleBottomSheet.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleBottomSheet.kt index d2e338d077..f4c7eecf8f 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleBottomSheet.kt @@ -28,9 +28,18 @@ import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import javax.inject.Inject +@Parcelize +data class JoinRulesOptionSupport( + val rule: RoomJoinRules, + val needUpgrade: Boolean = false +) : Parcelable + +fun RoomJoinRules.toOption(needUpgrade: Boolean) = JoinRulesOptionSupport(this, needUpgrade) + @Parcelize data class RoomJoinRuleBottomSheetArgs( - val currentRoomJoinRule: RoomJoinRules + val currentRoomJoinRule: RoomJoinRules, + val allowedJoinedRules: List ) : Parcelable class RoomJoinRuleBottomSheet : BottomSheetGeneric() { @@ -61,9 +70,15 @@ class RoomJoinRuleBottomSheet : BottomSheetGeneric = listOf( + RoomJoinRules.INVITE, RoomJoinRules.PUBLIC + ).map { it.toOption(true) } + ): RoomJoinRuleBottomSheet { return RoomJoinRuleBottomSheet().apply { - setArguments(RoomJoinRuleBottomSheetArgs(currentRoomJoinRule)) + setArguments( + RoomJoinRuleBottomSheetArgs(currentRoomJoinRule, allowedJoinedRules) + ) } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt index a438e8deee..edeb6e1099 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleController.kt @@ -51,7 +51,7 @@ class RoomJoinRuleController @Inject constructor( description = stringProvider.getString(R.string.room_settings_room_access_restricted_description), title = span { +stringProvider.getString(R.string.room_settings_room_access_restricted_title) - + " " + +" " image( drawableProvider.getDrawable(R.drawable.ic_beta_pill)!!, "bottom" @@ -59,6 +59,6 @@ class RoomJoinRuleController @Inject constructor( }, isSelected = state.currentRoomJoinRule == RoomJoinRules.RESTRICTED ) - ) + ).filter { state.allowedJoinedRules.map { it.rule }.contains(it.roomJoinRule) } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt new file mode 100644 index 0000000000..eaf19fe075 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.roomprofile.settings.joinrule + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.activityViewModel +import com.airbnb.mvrx.withState +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import im.vector.app.R +import im.vector.app.core.extensions.cleanup +import im.vector.app.core.extensions.configureWith +import im.vector.app.core.platform.OnBackPressed +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentJoinRulesRecyclerBinding +import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedActions +import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import javax.inject.Inject + +class RoomJoinRuleFragment @Inject constructor( + val controller: RoomJoinRuleAdvancedController, + val avatarRenderer: AvatarRenderer +) : VectorBaseFragment(), + OnBackPressed, RoomJoinRuleAdvancedController.InteractionListener { + + private val viewModel: RoomJoinRuleChooseRestrictedViewModel by activityViewModel() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) = + FragmentJoinRulesRecyclerBinding.inflate(inflater, container, false) + + override fun onBackPressed(toolbarButton: Boolean): Boolean { + val hasUnsavedChanges = withState(viewModel) { it.hasUnsavedChanges } + val isLoading = withState(viewModel) { it.updatingStatus is Loading } + if (!hasUnsavedChanges || isLoading) { + requireActivity().finish() + } else { + MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.dialog_title_warning) + .setMessage(R.string.warning_unsaved_change) + .setPositiveButton(R.string.warning_unsaved_change_discard) { _, _ -> + requireActivity().finish() + } + .setNegativeButton(R.string.cancel, null) + .show() + return true + } + return true + } + + override fun invalidate() = withState(viewModel) { state -> + super.invalidate() + controller.setData(state) + if (state.hasUnsavedChanges) { + // show discard and save + views.cancelButton.isVisible = true + views.positiveButton.text = getString(R.string.warning_unsaved_change_discard) + views.positiveButton.isVisible = true + views.positiveButton.text = getString(R.string.save) + views.positiveButton.debouncedClicks { + viewModel.handle(RoomJoinRuleChooseRestrictedActions.DoUpdateJoinRules) + } + } else { + views.cancelButton.isVisible = false + views.positiveButton.isVisible = true + views.positiveButton.text = getString(R.string.ok) + views.positiveButton.debouncedClicks { requireActivity().finish() } + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + views.genericRecyclerView.configureWith(controller, hasFixedSize = true) + controller.interactionListener = this + views.cancelButton.debouncedClicks { requireActivity().finish() } + } + + override fun onDestroyView() { + views.genericRecyclerView.cleanup() + super.onDestroyView() + } + + override fun didSelectRule(rules: RoomJoinRules) { + val isLoading = withState(viewModel) { it.updatingStatus is Loading } + if (isLoading) return + + viewModel.handle(RoomJoinRuleChooseRestrictedActions.SelectJoinRules(rules)) + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleState.kt index 85253091c4..dd818a4631 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleState.kt @@ -22,10 +22,13 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRules data class RoomJoinRuleState( val currentRoomJoinRule: RoomJoinRules = RoomJoinRules.INVITE, + val allowedJoinedRules: List = + listOf(RoomJoinRules.INVITE, RoomJoinRules.PUBLIC).map { it.toOption(true) }, val currentGuestAccess: GuestAccess? = null ) : BottomSheetGenericState() { constructor(args: RoomJoinRuleBottomSheetArgs) : this( - currentRoomJoinRule = args.currentRoomJoinRule + currentRoomJoinRule = args.currentRoomJoinRule, + allowedJoinedRules = args.allowedJoinedRules ) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt new file mode 100644 index 0000000000..9110f9b32e --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.roomprofile.settings.joinrule + +import android.widget.Button +import android.widget.ImageView +import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.core.view.isVisible +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.onClick +import im.vector.app.core.utils.DebouncedClickListener +import im.vector.app.features.home.AvatarRenderer +import org.matrix.android.sdk.api.util.MatrixItem + +@EpoxyModelClass(layout = R.layout.item_bottom_sheet_joinrule_restricted) +abstract class SpaceJoinRuleItem : VectorEpoxyModel() { + + @EpoxyAttribute + var selected: Boolean = false + + @EpoxyAttribute + var needUpgrade: Boolean = false + + @EpoxyAttribute + lateinit var avatarRenderer: AvatarRenderer + + @EpoxyAttribute + var restrictedList: List = emptyList() + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + lateinit var listener: ClickListener + + override fun bind(holder: Holder) { + super.bind(holder) + + holder.view.onClick(listener) + holder.upgradeRequiredButton.setOnClickListener(DebouncedClickListener(listener)) + + if (selected) { + holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_on)) + holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_checked) + } else { + holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_off)) + holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_unchecked) + } + + holder.upgradeRequiredButton.isVisible = needUpgrade + holder.helperText.isVisible = selected + + val items = listOf(holder.space1, holder.space2, holder.space3, holder.space4, holder.space5) + holder.spaceMore.isVisible = false + items.onEach { it.isVisible = false } + if (!needUpgrade) { + if (restrictedList.isEmpty()) { + holder.listTitle.isVisible = false + } else { + holder.listTitle.isVisible = true + restrictedList.forEachIndexed { index, matrixItem -> + if (index < items.size) { + items[index].isVisible = true + avatarRenderer.render(matrixItem, items[index]) + } else if (index == items.size) { + holder.spaceMore.isVisible = true + } + } + } + } else { + holder.listTitle.isVisible = false + holder.helperText.isVisible = false + } + } + + class Holder : VectorEpoxyHolder() { + val radioImage by bind(R.id.radioIcon) + val actionTitle by bind(R.id.actionTitle) + val actionDescription by bind(R.id.actionDescription) + val upgradeRequiredButton by bind + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/values-cs/strings.xml b/vector/src/main/res/values-cs/strings.xml index b2c3c292f4..6686684cae 100644 --- a/vector/src/main/res/values-cs/strings.xml +++ b/vector/src/main/res/values-cs/strings.xml @@ -234,10 +234,10 @@ • Servery shodující se s %s jsou nyní zakázány. Změnili jste ACL serveru pro tuto místnost. %s změnil(a) ACL serveru pro tuto místnost. - • Server shodující se doslovně s IP je povolen. - • Server shodující se doslovně s IP je zakázán. - • Server shodující se s %s je povolen. - • Server shodující se s %s je zakázán. + • Servery shodující se doslovně s IP jsou povoleny. + • Servery shodující se doslovně s IP jsou zakázány. + • Servery shodující se s %s jsou povoleny. + • Servery shodující se s %s jsou zakázány. Nastavili jste ACL serveru pro tuto místnost. %s nastavili ACL serveru pro tuto místnost. Změnili jste adresy pro tuto místnost. @@ -385,7 +385,7 @@ Přihlásit se Odhlásit se Adresa domovského serveru - Adresa URL serveru identit + URL serveru identit Hledat Začít novou konverzaci Zahájit hlasový hovor @@ -870,7 +870,7 @@ Normální Snížené soukromí Aplikaci potřebuje svolení k chodu na pozadí - Aplikace na pozadí opravdu nepotřebuje spojení k domovskému serveru, to by mělo snížit spotřebu + Aplikace na pozadí opravdu nepotřebuje spojení k domovskému serveru, to by mělo snížit spotřebu energie • Oznámení se posílají pomocí Firebase Cloud Messaging • Oznámení pouze obsahují metadata • Obsah oznámení je bezpečně uložen přímo na domovském serveru Matrixu @@ -1523,7 +1523,7 @@ Neshoda klíčů Neshoda uživatelů Neznámá chyba - Nepoužíváte žádný server pro identity + Nepoužíváte žádný server identit Není konfigurován žádný server pro identity, musíte přenastavit heslo. Vypadá to, že se chcete připojit k jinému domovskému serveru. Chcete se odhlásit\? Upravit @@ -2048,7 +2048,7 @@ \n- Spojení do internetu obou zařízení \n \nDoporučujeme, abyste okamžitě změnili heslo a klíč obnovy v nastavení. - Ověřit svá zařízení v nastavení. + Ověření bylo zrušeno. Můžete je znovu spustit. Ověření zrušeno Přístupová fráze pro obnovu Klíč zpráv @@ -2528,7 +2528,7 @@ %1$d z %2$d Založit novou přímou konverzaci pomocí Matrix ID Založit novou přímou konverzaci pomocí skenu QR kódu - Abyste nalezli existující kontakty, jež znáte, souhlasíte s odesláním svých kontaktních údajů (telefonní čísla nebo emailové adresy) na nastavený server pro identity (%1$s)\? + Abyste nalezli existující kontakty, jež znáte, souhlasíte s odesláním svých kontaktních údajů (telefonní čísla nebo emailové adresy) na nastavený server identit (%1$s)\? \n \nZa účelem soukromí budou data před odesláním hašována. Poslat emailové adresy a telefonní čísla @@ -2893,4 +2893,14 @@ Chybějící oprávnění Pro provedení této akce udělte, prosím, oprávnění Fotoaparát v systémových nastaveních. Některá z oprávnění potřebných k provedení akce chybí, prosím, udělte oprávnění v systémových nastaveních. + + Zmeškaný video hovor + %d zmeškané video hovory + %d zmeškaných video hovorů + + + Zmeškaný hlasový hovor + %d zmeškané hlasové hovory + %d zmeškaných hlasových hovorů + \ No newline at end of file diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml index a7869e82f0..65e27a7f9f 100644 --- a/vector/src/main/res/values-de/strings.xml +++ b/vector/src/main/res/values-de/strings.xml @@ -573,7 +573,7 @@ Nicht gesendete Nachrichten erneut senden Nicht gesendete Nachrichten löschen Datei nicht gefunden - Du bist nicht berechtigt, in diesen Raum zu schreiben + Du bist nicht berechtigt, in diesen Raum zu schreiben. Vertrauen Nicht vertrauen diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index edd187daa6..c5f7234fc9 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -222,10 +222,10 @@ Muudatusi ei ole. • Nüüd on keelatud serverid, mille ip-aadress vastab mustrile. • Nüüd on lubatud serverid, mille ip-aadress vastab mustrile. - • Server, mille nimes leidub %s, eemaldati lubatud serverite loendist. + • Serverid, mille nimes leidub %s, eemaldati lubatud serverite loendist. • Nüüd on lubatud serverid, mille nimes leidub %s. - • Server, mille nimes leidub %s eemaldati keeluloendist. - • Keelatud on server, mille nimes leidub %s. + • Serverid, mille nimes leidub %s eemaldati keeluloendist. + • Keelatud on serverid, mille nimes leidub %s. Sina muutsid selle jututoa jaoks serverite pääsuloendit. %s muutis selle jututoa jaoks serverite pääsuloendit. Sina kirjeldasid selle jututoa jaoks serverite pääsuloendi. @@ -2289,7 +2289,7 @@ \n - Sinu või teise osapoole internetiühendus \n \nPalun vaheta seadistuste lehelt koheselt oma kasutajakonto salasõna ja taastevõti. - Seadistuste lehelt verifitseeri oma seade. + Verifitseerimine on katkestatud. Soovi korral saad seda uuesti alustada. Verifitseerimine on tühistatud Taastamiseks mõeldud paroolifraas Sõnumite krüptovõti @@ -2840,4 +2840,12 @@ Õigused on puudu Selle tegevuse jaoks palun luba seadistustes sellele rakendusele kaamera kasutamine. Selle tegevuse jaoks puuduvad sul õigused. Palun jaga vajalikud õigused süsteemi seadistustest. + + Vastamata videokõne + %d vastamata videokõnet + + + Vastamata kõne + %d vastamata kõnet + \ No newline at end of file diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml index 4d30b2a652..beadfd804f 100644 --- a/vector/src/main/res/values-fr/strings.xml +++ b/vector/src/main/res/values-fr/strings.xml @@ -681,7 +681,7 @@ La connexion au serveur a été perdue. Messages non envoyés. %1$s ou %2$s maintenant \? Messages non envoyés car des sessions inconnues sont présentes. %1$s ou %2$s maintenant \? - Vous n’avez pas la permission de poster dans ce salon + Vous n’avez pas la permission de poster dans ce salon. Empreinte (%s) : Impossible de vérifier l’identité du serveur distant. Cela pourrait signifier que quelqu’un intercepte malicieusement votre trafic ou que votre téléphone ne fait pas confiance au certificat fourni par le serveur distant. @@ -991,7 +991,7 @@ Change le nom d’affichage Markdown activé/désactivé Pour réparer la gestion des applications Matrix - Ce salon a été remplacé et n’est plus actif + Ce salon a été remplacé et n’est plus actif. La conversation continue ici Ce salon est la suite d’une autre conversation Cliquer ici pour voir les anciens messages @@ -1986,7 +1986,7 @@ \n- La connexion internet utilisée par un des deux appareils \n \nNous vous recommandons de modifier immédiatement votre mot de passe et votre clé de récupération dans les paramètres. - Vérifiez vos appareils depuis les paramètres. + La vérification a été annulée. Vous pouvez redémarrer la vérification. Vérification annulée Phrase de récupération clé des messages @@ -2822,4 +2822,37 @@ Adresse de l’espace Afficher et gérer les adresses de cet espace. Adresse de l’espace + Mettre à jour vers la version de salon recommandée + Ce salon utilise la version %s de salon, que ce serveur d’accueil considère comme instable. + Vous devez avoir le droit de mettre à jour ce salon + Mettre à jour automatiquement l’espace parent + Inviter automatiquement des utilisateurs + Vous allez mettre à jour ce salon de %s à %s. + La mise-à-jour d’un salon est une action avancée et n’est normalement recommandé que si un salon est instable à cause de bogues, fonctionnalités manquantes, ou failles de sécurité. +\nCela n’affecte normalement que la manière dont le salon est géré par le serveur. + Mettre à jour un salon privé + Mettre à jour un salon public + Mettre à jour + Soyez patient, cela peut prendre du temps. + Rejoindre le salon remplaçant + Mettre à jour un salon vers une nouvelle version + instable + stable + Version par défaut + Versions du salon 👓 + Vérifier en comparant des émoticônes à la place + Scanner avec cet appareil + Scannez le code avec votre autre appareil, ou échangez et scannez avec cet appareil + + Appel vidéo manqué + %d appels vidéos manqués + + + Appel vocal manqué + %d appels vocaux manqués + + URL de l’API du serveur d’accueil + Permissions manquantes + Pour effectuer cette action, veuillez autoriser la permission Caméra depuis les réglages système. + Certaines permissions manquent pour effectuer cette action, veuillez autoriser ces permissions depuis les réglages système. \ No newline at end of file diff --git a/vector/src/main/res/values-fy/strings.xml b/vector/src/main/res/values-fy/strings.xml index ad3ed8aea8..7db0afa759 100644 --- a/vector/src/main/res/values-fy/strings.xml +++ b/vector/src/main/res/values-fy/strings.xml @@ -935,7 +935,7 @@ Opslein In foto as fideo meitsje Kin gjin fideo opnimme - + %1$dm %2$ds %d s It delheljen ôfbrekke\? @@ -1036,4 +1036,16 @@ Jo hawwe de keamer ôfbylding feroare %1$s hat de keamer ôfbylding feroare %1$s hat syn profylfoto feroare + Jo hawwe %1$s harren útnûging ynlutsen. Reden: %2$s + %1$s hat %2$s harren útnûging ynlutsen. Reden: %3$s + Jo hawwe de útnûging foar %1$s akseptearre. Reden: %2$s + %1$s hat de útnûging foar %2$s akseptearre. Reden: %3$s + Jo hawwe %1$s net mear ferballe + %1$s hat %2$s net mear ferballe + + %d selektearre + %d selektearre + + Keamerleden filterje + Jo binne útlogd \ No newline at end of file diff --git a/vector/src/main/res/values-hu/strings.xml b/vector/src/main/res/values-hu/strings.xml index 933ee4b3f0..58eebfe0f4 100644 --- a/vector/src/main/res/values-hu/strings.xml +++ b/vector/src/main/res/values-hu/strings.xml @@ -1943,7 +1943,7 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró \n- Valamelyik eszköz által használt internet elérés \n \nJavasoljuk, hogy azonnal cseréld le a jelszavadat és a visszaállítási kulcsot a Beállításokban. - Ellenőrizd az eszközödet a Beállításokból. + Ellenőrzés megszakítva. Újrakezdheted az ellenőrzést. Ellenőrzés megszakítva Visszaállítási jelmondat Üzenet Kulcs @@ -2845,4 +2845,12 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró Hiányzó engedélyek A művelethez a rendszer beállításokban engedélyezni kell a kamera használatát. Ehhez a művelethez néhány engedély hiányzik amit a rendszer beállításokban lehet megadni. + + Nem fogadott videóhívás + %d nem fogadott videóhívás + + + Nem fogadott hanghívás + %d nem fogadott hanghívás + \ No newline at end of file diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index 3afab6fa23..1f2b5cfe81 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -87,7 +87,7 @@ Hanya kontak Matrix Ruang Laporan bug - "Aplikasi gagal saat terakhir digunakan. Apakah Anda ingin membuka halaman laporan kegagalan?" + Aplikasi gagal saat terakhir digunakan. Apakah Anda ingin membuka halaman laporan kegagalan\? Gabung di Ruang URL Server Identity Mulai Panggilan Suara @@ -194,7 +194,7 @@ Verifikasi alamat email gagal: pastikan tautan yang termuat di email telah diklik Kata sandi Anda telah disetel ulang. \n -\nAnda telah dikeluarkan dari seluruh sesi dan tidak lagi menerima push notification. Untuk kembali menerima pemberitahuan, masuklah kembali dengan tiap perangkat. +\nAnda telah dikeluarkan dari seluruh sesi dan tidak lagi menerima push notification. Untuk kembali menerima pemberitahuan, masuklah kembali di setiap perangkat. Tidak dapat masuk: Gangguan jaringan Tidak dapat mendaftar: Gangguan jaringan Tidak dapat mendaftar : gagal memastikan kepemilikan alamat email @@ -286,11 +286,11 @@ Ijinkan akses lewat halaman selanjutnya untuk menemukan pengguna ${app_name} yan ${app_name} memerlukan izin untuk mengakses daftar kontak Anda untuk menemukan pengguna Matrix lain berdasarkan email dan nomor telepon mereka. \n \nApakah anda bersedia bila ${app_name} mengakses daftar kontak Anda\? - Mohon Maaf. Aksi ini tidak dapat dilakukan karena belum menerima izin terkait + Mohon maaf. Aksi tidak dilakukan karena izin-izin yang kurang Daftar Anggota Buka kop Menyinkronkan… - Arahkan ke pesan pertama yang belum terbaca. + Arahkan ke yang belum terbaca Anda telah diundang untuk bergabung ke ruang ini oleh %s Undangan ini dikirim oleh %s, yang tidak terhubung dengan akun ini. \nAnda mungkin ingin masuk dengan akun lain, atau tambahkan email ini ke akun Anda. @@ -315,7 +315,7 @@ Ijinkan akses lewat halaman selanjutnya untuk menemukan pengguna ${app_name} yan %dj - $dh + %dh Tinggalkan ruang Apa benar Anda ingin meninggalkan ruang ini? @@ -375,7 +375,7 @@ Ijinkan akses lewat halaman selanjutnya untuk menemukan pengguna ${app_name} yan Kirim ulang pesan yang belum terkirim Hapus pesan yang belum terkirim Berkas tidak ditemukan - Anda belum mendapat permisi untuk mengirim di ruang ini + Anda tidak mempunyai ijin untuk mengirim di ruang ini. %d pesan baru @@ -566,16 +566,16 @@ Ijinkan akses lewat halaman selanjutnya untuk menemukan pengguna ${app_name} yan Avatar Baca sekarang Deaktivasi Akun - Ini akan mengakibatkan akun Anda tidak dapat digunakan secara permanen. Anda tidak akan dapat masuk dan orang lain tidak dapat mendaftar ulang dengan ID pengguna yang sama. Ini akan mengakibatkan akun Anda keluar dari semua ruang tempat Anda berpartisipasi serta menghapus semua detail akun dari identity server Anda. Tindakan ini tidak dapat diubah kembali. + Ini akan mengakibatkan akun Anda tidak dapat digunakan secara permanen. Anda tidak akan dapat masuk dan orang lain tidak dapat mendaftar ulang dengan ID pengguna yang sama. Ini akan mengakibatkan akun Anda keluar dari semua ruang tempat Anda berpartisipasi serta menghapus semua detail akun dari server identitas Anda. Tindakan ini tidak dapat diubah. \n -\nMenonaktifkan akun Anda tidak serta-merta membuat kami melupakan pesan-pesan yang Anda kirim. Jika Anda ingin kami melupakan pesan-pesan Anda, mohon centang kotak berikut. +\nMenonaktifkan akun Anda tidak membuat kami melupakan pesan-pesan yang Anda kirim secara default. Jika Anda ingin kami melupakan pesan-pesan Anda, mohon centang kotak berikut. \n -\nKeterbacaan pesan di Matrix serupa dengan email. Dengan kami melupakan pesan-pesan Anda, berarti pesan-pesan yang Anda kirim tidak akan dibagikan kepada pengguna baru ataupun yang belum terdaftar. Tetapi pengguna yang terdaftar dan telah dapat mengakses pesan-pesan tersebut masih bisa membaca rangkap yang mereka simpan. +\nKeterbacaan pesan di Matrix serupa dengan email. Dengan kami melupakan pesan-pesan Anda berarti pesan-pesan yang Anda kirim tidak akan dibagikan kepada pengguna baru ataupun yang belum terdaftar, tetapi pengguna yang terdaftar yang mempunyai mengakses pesan-pesan tersebut masih bisa mengakses salinan mereka. Mohon lupakan semua pesan yang telah kukirim ketika akunku dideaktivasi (Peringatan: ini akan mengakibatkan pengguna mendatang membaca percakapan yang tidak lengkap) Untuk melanjutkan, masukkan kata sandi Anda: Deaktivasi Akun Mohon masukkan kata sandi Anda. - Ruang ini telah berubah dan tidak lagi aktif + Ruang ini telah berubah dan tidak lagi aktif. Percakapan berlanjut di sini Ruang ini adalah kelanjutan percakapan lain Klik di sini untuk melihat pesan lama @@ -606,9 +606,9 @@ Ijinkan akses lewat halaman selanjutnya untuk menemukan pengguna ${app_name} yan Apabila cocok, tekan tombol verifikasi berikut. Apabila tidak, seseorang sedang menyadap perangkat ini dan mungkin perlu diblokir. Di masa mendatang proses verifikasi ini akan dimutakhirkan. - Ruang ini terdapat sesi yang yang belum diverifikasi. -\nIni artinya, tidak ada jaminan pengguna sesi tersebut sesuai dengan klaim mereka. -\nKami sarankan Anda untuk memverifikasi untuk setiap sesi terlebih dahulu sebelum melanjutkan, namun Anda juga boleh mengirim ulang pesan tanpa verifikasi bila anda memilih demikian. + Ruang ini terdapat sesi tidak dikenal yang belum diverifikasi. +\nIni artinya tidak ada jaminan pengguna sesi tersebut sesuai dengan klaim mereka. +\nKami sarankan Anda untuk memverifikasi untuk setiap sesi terlebih dahulu sebelum melanjutkan, namun Anda juga boleh mengirim ulang pesan tanpa verifikasi bila Anda memilih demikian. \n \nSesi yang tak dikenal: Server mungkin belum siap atau kelebihan beban @@ -838,7 +838,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. \n%1$s Pendaftaran Token Sukses mendaftarkan token FCM di HomeServer. - Gagal mendaftarkan token FCM ke HomeServer: + Gagal mendaftarkan token FCM ke homeserver: \n%1$s Layanan Pemberitahuan Layanan Pemberitahuan sedang berjalan. @@ -908,4 +908,79 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Tunjukkan kejadian bergabung dan meninggalkan Undangan, pengeluaran, dan larangan tidak terpengaruh. Tunjukkan kejadian akun + • Server-server yang cocok dengan %s diizinkan. + • Server-server yang cocok dengan %s dilarangkan. + Anda mengatur server ACL untuk ruangan ini. + %s mengatur server ACL untuk ruangan ini. + Anda meningkatkan di sini. + %s meningkatkan di sini. + Anda meningkatkan ruangan ini. + %s meningkatkan ruangan ini. + Anda mengaktifkan enkripsi ujung-ke-ujung (%1$s) + %1$s mengaktifkan enkripsi ujung-ke-ujung (%2$s) + tidak diketahui (%s). + siapa pun. + semua anggota ruangan. + semua anggota ruangan, dari kapan mereka bergabung. + semua anggota ruangan, dari kapan mereka diundang. + Anda membuat riwayat pesanan masa depan terlihat dengan %1$s + %1$s membuat riwayat pesanan masa depan terlihat dengan %2$s + Anda membuat riwayat ruangan masa depan terlihat dengan %1$s + %1$s membuat riwayat ruangan masa depan terlihat dengan %2$s + Anda mengakhiri panggilan. + %s mengakhiri panggilan. + %s mengirimkan data untuk mengatur panggilan. + Anda mengirimkan data untuk mengatur panggilan. + %s menjawab panggilan. + Anda menjawab panggilan. + Anda menempatkan panggilan suara. + %s menempatkan panggilan suara. + Anda menempatkan panggilan video. + %s menempatkan panggilan video. + Anda mengubah nama kamar menjadi: %1$s + %1$s mengubah nama ruangan menjadi: %2$s + Anda mengubah avatar ruangan + %1$s mengubah avatar ruangan + Anda mengubah topik menjadi: %1$s + %1$s mengubah topik menjadi: %2$s + Anda menghapus nama tampilan Anda (sebelumnya adalah %1$s) + Anda mengubah nama tampilan Anda dari %1$s ke %2$s + %1$s menghapus nama tampilan mereka (sebelumnya adalah %2$s) + %1$s mengubah nama tampilan mereka dari %2$s ke %3$s + Anda menetapkan nama tampilan Anda ke %1$s + %1$s menetapkan nama tampilannya ke %2$s + Anda mengubah avatar Anda + %1$s mengubah avatarnya + Anda menarik undangannya %1$s + %1$s menarik undangannya %2$s + Anda mencekal %1$s + %1$s mencekal %2$s + Anda membatalkan pencekalan %1$s + %1$s membatalkan pencekalan %2$s + Anda meng-kick %1$s + %1$s meng-kick %2$s + Anda menolak undangan + %1$s menolak undangan + Anda meninggalkan ruangan + %1$s meninggalkan ruangan + Anda meninggalkan ruangan + %1$s meninggalkan ruangan + Anda bergabung + %1$s bergabung + Anda bergabung ruangan + %1$s bergabung ruangan + %1$s mengundang Anda + Anda mengundang %1$s + %1$s mengundang %2$s + Anda membuat diskusi + %1$s membuat diskusi + Anda membuat ruangan + %1$s menciptakan ruangan + Undangan Anda + Undangan %s + Kamu mengirim sticker. + %1$s mengirim stiker. + Anda mengirim gambar. + %1$s mengirim gambar. + %1$s: %2$s \ No newline at end of file diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index e9dc787928..f91d02e45d 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -222,7 +222,7 @@ 🎉 Tutti i server sono banditi! Questa stanza non può più essere usata. Nessuna modifica. • I server che corrispondono a IP alfabetici ora sono banditi. - • I server che corrispondono a IP alfabetici ora sono permessi. + • I server che corrispondono a IP alfabetici ora sono ammessi. • I server che corrispondono a %s sono stati rimossi dalla lista degli ammessi. • I server che corrispondono a %s ora sono ammessi. • I server che corrispondono a %s sono stati rimossi dalla lista di ban. @@ -230,7 +230,7 @@ Hai cambiato le ACL del server per questa stanza. %s ha cambiato le ACL del server per questa stanza. • I server che corrispondono a IP alfabetici sono banditi. - • I server che corrispondono a IP alfabetici sono permessi. + • I server che corrispondono a IP alfabetici sono ammessi. • I server che corrispondono a %s sono ammessi. • I server che corrispondono a %s sono banditi. Hai impostato le ACL del server per questa stanza. @@ -367,7 +367,7 @@ Accedi Disconnetti URL dell\'homeserver - URL dell\'Identity Server + URL del server di identità Cerca Avvia una nuova chat diretta Avvia chiamata audio @@ -1204,8 +1204,8 @@ Recupero fallito del token FCM: \n%1$s Registrazione Token - Token FCM registrato con successo sull\'Home Server. - E\'fallita la registrazione del Token FCM sull\'Home Server: + Token FCM registrato con successo sull\'homeserver. + È fallita la registrazione del token FCM sull\'homeserver: \n %1$s Servizi di notifica Servizio di notifiche in esecuzione. @@ -1408,7 +1408,7 @@ Scegli Riproduci il suono dell\'otturatore Segna come letto - L\'app non ha bisogno di connettersi in background all\'Home Server. Ciò dovrebbe ridurre il consumo della batteria + L\'app non ha bisogno di connettersi in secondo piano all\'homeserver. Ciò dovrebbe ridurre il consumo della batteria %1$s: %2$d messaggio %1$s: %2$d messaggi @@ -1472,7 +1472,7 @@ Le chiavi non corrispondono L\'utente non corrisponde Errore sconosciuto - Esiste già un backup sul tuo Home Server + Esiste già un backup sul tuo homeserver Sembra tu abbia già impostato il backup delle chiavi crittografiche da un\'altra sessione. Vuoi sostituirlo con il backup che stai creando\? Sostituisci Ferma @@ -1567,7 +1567,7 @@ Nome o ID stanza (#esempio:matrix.org) Attiva lo swipe per rispondere nella timeline Link URL copiato negli appunti - Gestore delle integrazioni + Gestore di integrazioni Non è stato configurato nessun Integration Manager. Aggiungi per ID utente Creazione stanza … @@ -1619,7 +1619,7 @@ Configura l\'Identity Server per trovare e farsi trovare dagli altri utenti. Nome pubblico (visibile alle persone con cui comunichi) Il nome pubblico di una sessione è visibile alle persone con cui comunichi - Non stai usando alcun Identity Server + Non stai usando alcun server di identità Nessun Identity Server configurato. E\' necessario per poter ripristinare la tua password. Pare che tu stia provando a connetterti ad un altro homeserver. Vuoi disconnetterti da qui\? Identity Server @@ -1700,8 +1700,8 @@ Non puoi farlo da ${app_name} mobile E\'necessaria l\'autenticazione Integrazioni - Usa un Integration Manager per gestire bot, bridge, widget e pacchetti di sticker. -\nGli Integration Manager possono ricevere dati di configurazione, modificare widget, mandare inviti alle stanze e modificare permessi a tuo nome. + Usa un gestore di integrazioni per gestire bot, bridge, widget e pacchetti di sticker. +\nI gestori di integrazioni possono ricevere dati di configurazione, modificare widget, mandare inviti alle stanze e modificare permessi a tuo nome. Permetti l\'uso di integrazioni Widget Carica widget @@ -2065,7 +2065,7 @@ \n- La connessione internet usata da uno dei dispositivi \n \nTi consigliamo di cambiare immediatamente la password e le chiavi di recupero nelle impostazioni. - Verifica i tuoi dispositivi nelle impostazioni. + La verifica è stata annullata. Puoi iniziarne una nuova. Verifica annullata Passphrase di ripristino Chiave dei messaggi @@ -2536,7 +2536,7 @@ %1$d di %2$d Crea una nuova conversazione diretta scansionando un codice QR Crea una nuova conversazione diretta tramite ID utente - Per trovare gli utenti che già conosci, accetti di inviare le informazioni di contatto (numeri di telefono e/o email) all\'Identity Server configurato (%1$s)\? + Per trovare gli utenti che già conosci, accetti di inviare le tue informazioni di contatto (numeri di telefono e/o email) al server di identità configurato (%1$s)\? \n \nPer garantire la privacy, i dati verranno inviati in forma oscurata (hashing). Invio di email e numeri di telefono @@ -2894,4 +2894,12 @@ Autorizzazioni mancanti Per eseguire questa azione, concedi l\'autorizzazione Fotocamera dalle impostazioni di sistema. Mancano alcune autorizzazioni per eseguire questa azione, concedile dalle impostazioni di sistema. + + Videochiamata persa + %d videochiamate perse + + + Telefonata persa + %d telefonate perse + \ No newline at end of file diff --git a/vector/src/main/res/values-lv/strings.xml b/vector/src/main/res/values-lv/strings.xml index 6e2503a8b5..642b02f4aa 100644 --- a/vector/src/main/res/values-lv/strings.xml +++ b/vector/src/main/res/values-lv/strings.xml @@ -1903,18 +1903,18 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. Rādīt istabas ar vecuma ierobežojumu 🎉 Visi serveri ir aizliegti piedalīties! Šo istabu vairs nevar izmantot. Nekas nemainīts. - • Servers ar vienādu IP tagad ir aizliegts. - • Servers ar vienādu IP ir atļauts. - • Servers vienāds ar %s tika noņemts no atļautā saraksta. - • Servers vienāds ar %s tagad ir atļauts. - • Servers vienāds ar %s tika noņemts no aizliegtā saraksta. - • Servers vienāds ar %s tagad ir aizliegts. + • Serveri ar atbilstošu IP tagad ir aizliegti. + • Serveri ar atbilstošu IP ir atļauti. + • Serveri, kuri atbilst %s tika izņemti no atļauto saraksta. + • Serveri, kuri atbilst %s tagad ir atļauti. + • Serveri, kuri atbilst %s tika noņemti no aizliegto/nobanoto saraksta. + • Serveri, kuri atbilst %s tagad ir aizliegti. Jūs nomainījāt servera ACL šai istabai. %s nomainīja servera ACL šai istabai. - • Servers ar vienādu IP ir aizliegts. - • Servers ar vienādu IP ir atļauts. - • Servers vienāds ar %s ir atļauts. - • Servers vienāds ar %s ir aizliegts. + • Serveri ar vienādām IP ir aizliegti. + • Serveri ar vienādām IP ir atļauti. + • Serveri, kuri atbilst %s ir atļauti. + • Serveri, kuri atbilst %s ir nobanoti. Jūs iestatījāt servera ACL šai istabai. %s iestatīja servera ACL šai istabai. Jūs atjauninājāt šeit. @@ -2333,4 +2333,10 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. %ds %di + Trūkst atļauju + Lai veiktu šo darbību, lūdzu, piešķiriet kamerai atļauju sistēmas iestatījumos. + Lai veiktu šo darbību, trūkst dažu atļauju. Lūdzu, sistēmas Iestatījumos piešķiriet atļaujas. + Vietnes + Uzaicinājumi + Ieteiktās telpas \ No newline at end of file diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index 1339ce1c00..ee499914c4 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -322,7 +322,7 @@ Abrir Fechar Copiado para clipboard - Desativar + Desabilitar Confirmação Aviso @@ -420,7 +420,7 @@ Este servidorcasa gostaria de assegurar que você não é um robô Nome de usuária(o) em uso Servidorcasa: - Servidor de Identidade: + Servidor de identidade: Eu tenho verificado meu endereço de email Para resettar sua senha, entre o endereço de email linkado a sua conta: O endereço de email linkado a sua conta deve ser entrado. @@ -429,7 +429,7 @@ Falha para verificar endereço de email: assegure-se que clicou no link no email Sua senha tem sido resettada. \n -\nVocê tem sido feito logout de todas as sessões e não vai mais receber notificações push. Para re-ativar notificações, re-faça login em cada dispositivo. +\nVocê tem sido feito logout de todas as sessões e não vai mais receber notificações push. Para re-habilitar notificações, re-faça login em cada dispositivo. URL deve começar com http[s]:// Incapaz de fazer login: Erro de rede @@ -471,9 +471,9 @@ Chamada conectando… Chamada terminada Chamando… - Chamada Recebendo - Chamada de Vídeo Recebendo - Chamada de Voz Recebendo + Chamada Entrante + Chamada de Vídeo Entrante + Chamada de Voz Entrante Chamada Em Progresso… O lado remoto falhou para atender. Conexão de Mídia Falhou @@ -522,7 +522,7 @@ \nVocê pode desejar fazer login com uma conta diferente, ou adicionar este email a sua conta. Você está tentando acessar %s. Você gostaria de se juntar a fim de participar na discussão\? uma sala - Esta é uma previsualização desta sala. Interações de sala têm sido desativadas. + Esta é uma previsualização desta sala. Interações de sala têm sido desabilitadas. Novo Chat Adicionar membro @@ -651,8 +651,8 @@ Adicionar número de telefone Mostrar info de aplicativo nas configurações de sistema. Info de aplicativo - Ativar notificações para esta conta - Ativar notificações para esta sessão + Habilitar notificações para esta conta + Habilitar notificações para esta sessão Ligar a tela por 3 segundos Mnsgns em chats um-a-um Mnsgns em chats de grupo @@ -660,7 +660,7 @@ Convites de chamada Mensagens enviadas por bot Sincronização no background - Ativar sinc no background + Habilitar sinc em background Timeout de requisição de sinc Delay entre casa Sinc Versão @@ -698,7 +698,7 @@ Submeter Feito login como Servidorcasa - Servidor de Identidade + Servidor de identidade Verificação Pendente Por favor cheque seu email e clique no link que ele contém. Uma vez que isto for feito, clique em continuar. Incapaz de verificar endereço de email. Por favor cheque seu email e clique no link que ele contém. Uma vez que isto for feito, clique em continuar. @@ -764,7 +764,7 @@ Estes são recursos experimentais que podem quebrar de maneiras inesperadas. Use com cuidado. Encriptação Ponta-a-Ponta Encriptação Ponta-a-Ponta está ativa - Você precisa fazer logout para ser capaz de ativar a encriptação. + Você precisa fazer logout para ser capaz de habilitar a encriptação. Encriptar para sessões verificadas somente Nunca enviar mensagens encriptadas para sessões não-confirmadas nesta sala desta sessão. @@ -778,10 +778,10 @@ Des-definir como endereço principal Copiar ID de Sala Copiar Endereço de Sala - Encriptação está ativada nesta sala. - Encriptação está desativada nesta sala. - Ativar encriptação -\n(aviso: não pode ser desativada de novo!) + Encriptação está habilitada nesta sala. + Encriptação está desabilitada nesta sala. + Habilitar encriptação +\n(aviso: não pode ser desabilitada de novo!) Diretório @@ -1029,7 +1029,7 @@ Se possível, por favor escreva a descrição em Inglês. Enviar voz Enviar sticker - Atualmente você não tem nenhum pacote de stickers ativado. + Você não tem atualmente nenhum pacote de stickers habilitado. \n \nAdicionar alguns agora\? continuar com… @@ -1080,7 +1080,7 @@ Escolher uma outra opção Enviar dados de analítica ${app_name} coleta analítica anônima para nos permitir melhorar o aplicativo. - Por favor ative analítica para nos ajudar a melhorar ${app_name}. + Por favor habilite analítica para nos ajudar a melhorar ${app_name}. Sim, eu quero ajudar! Você não é atualmente um membro de quaisquer comunidades. Digite aqui… @@ -1139,8 +1139,8 @@ Erro Por favor revise e aceite as políticas deste servidorcasa: Chamadas - Usar toque default de ${app_name} para chamadas recebendo - Toque de chamada recebendo + Usar toque default de ${app_name} para chamadas entrantes + Toque de chamada entrante Selecionar toque para chamadas: Razão Versão %s @@ -1152,21 +1152,21 @@ Um ou mais testes têm falhado, tente correção(ões) sugerida(s). Um ou mais testes têm falhado, por favor submita um reporte de bug para nos ajudar a investigar. Configurações de Sistema. - Notificações estão ativadas nas configurações de sistema. - Notificações estão desativadas nas configurações do sistema. + Notificações estão habilitadas nas configurações de sistema. + Notificações estão desabilitadas nas configurações do sistema. \nPor favor cheque configurações de sistema. Abrir Configurações Configurações de Conta. - Notificações estão ativadas para sua conta. - Notificações estão desativadas para sua conta. + Notificações estão habilitadas para sua conta. + Notificações estão desabilitadas para sua conta. \nPor favor cheque configurações de conta. - Ativar + Habilitar Configurações de Sessão. - Notificações estão ativadas para esta sessão. + Notificações estão habilitadas para esta sessão. Expulsar - Notificações não estão ativadas para esta sessão. + Notificações não estão habilitadas para esta sessão. \nPor favor cheque as configurações de ${app_name}. - Ativar + Habilitar Checagem de Play Services APK de Google Play Services está disponível e atualizado. ${app_name} usa Google Play Services para entregar mensagens push mas não parece estar configurado corretamente: @@ -1179,8 +1179,8 @@ Falha para recuperar token do FCM: \n%1$s Registro de Token - Token FCM registrado com sucesso a ServidorCasa. - Falha para registrar token FCM a ServidorCasa: + Token FCM registrado com sucesso a servidorcasa. + Falha para registrar token FCM a servidorcasa: \n%1$s Serviço de Notificações Serviço de Notificações está rodando. @@ -1192,12 +1192,12 @@ Começar em boot Serviço vai começar quando o dispositivo for reiniciado. O serviço não vai começar quando o dispositivo for recomeçado, você não vai receber notificações até que ${app_name} tenha sido aberto uma vez. - Ativar Começar em boot + Habilitar Começar em boot Checar restrições de background Otimização de Bateria ${app_name} não é afetado por Otimização de Bateria. Auto-Reinício de Serviço de Notificações - Desativar restrições + Desabilitar restrições Ignorar Otimização Previsualizar links dentro do chat quando seu servidorcasa suporta este recurso. Enviar notificações de digitação @@ -1211,9 +1211,9 @@ Conexão no Background ${app_name} precisa manter uma conexão no background de baixo impacto a fim de ter notificações confiáveis. \nNa próxima tela você vai ser instigado a permitir ${app_name} sempre rodar em background, por favor aceite. - Restrições de background estão desativadas para ${app_name}. Este teste devia ser rodado usando dados móveis (sem Wi-Fi). + Restrições de background estão desabilitadas para ${app_name}. Este teste devia ser rodado usando dados móveis (sem Wi-Fi). \n%1$s - Restrições de background estão ativadas para ${app_name}. + Restrições de background estão habilitadas para ${app_name}. \nTrabalho que o app tenta fazer vai ser agressivamente restringido enquando ele está no background, e isto poderia afetar notificações. \n%1$s Formatação markdown @@ -1226,8 +1226,8 @@ Começar a câmera de sistema em vez da tela de câmera personalizada. Esta opção requer um aplicativo de terceiro para gravar as mensagens. O comando \"%s\" precisa de mais parâmetros, ou alguns parâmetros estão incorretos. - Markdown tem sido ativado. - Markdown tem sido desativado. + Markdown tem sido habilitado. + Markdown tem sido desabilitado. Aumenta performance ao somente carregar membros de salas em primeira visualização. Seu servidorcasa não suporta carregamento preguiçoso de membros de salas ainda. Tente mais tarde. Desculpe, um erro ocorreu @@ -1269,7 +1269,7 @@ Importância de notificação por evento Configurações Personalizadas. Observe que alguns tipos de mensagens estão definidos para serem silenciosos (vão produzir uma notificação sem nenhum som). - Algumas notificações estão desativadas em suas configurações personalizadas. + Algumas notificações estão desabilitadas em suas configurações personalizadas. Falha para carregar regras personalizadas, por favor retente. Checar Configurações [%1$s] @@ -1360,7 +1360,7 @@ Confirme sua senha Você não pode fazer isto desde ${app_name} mobile Autenticação é requerida - O app não precisa de se conectar ao ServidorCasa no background, isto deveria reduzir uso de bateria + O app não precisa de se conectar ao servidorcasa no background, isto deveria reduzir uso de bateria Modo Sinc no Background Optimizado para bateria ${app_name} vai sincar em background de maneira que preserva recursos limitados do dispositivo (bateria). @@ -1368,15 +1368,15 @@ Optimizado para tempo real ${app_name} vai sincar em background periodicamente em tempo preciso (configurável). \nIsto vai impactar uso de rádio e bateria, vai ter uma notificação permanente exibida declarando que ${app_name} está à escuta por eventos. - Sem sinc no background - Você não vai ser notificada(o) sobre mensagens recebendo quando o app está em background. + Sem sinc em background + Você não vai ser notificada(o) sobre mensagens entrantes quando o app está em background. Falha para atualizar configurações. Intervalo de Sinc Preferido %s \nA sinc pode ser adiada dependendo dos recursos (bateria) ou estado do dispositivo (sono). Integrações - Use um Gerenciador de Integração para gerenciar bots, bridges, widgets e pacotes de stickers. -\nGerenciadores de Integração recebem dados de configuração, e podem modificar widgets, enviar convites de sala e definir níveis de poder em seu nome. + Use um gerenciador de integrações para gerenciar bots, bridges, widgets e pacotes de stickers. +\nGerenciadores de integrações recebem dados de configuração, e podem modificar widgets, enviar convites de sala e definir níveis de poder em seu nome. Botão enter do teclado suave vai enviar mensagem em vez de adicionar uma quebra de linha Backup Seguro Gerenciar @@ -1390,9 +1390,9 @@ Gerenciar suas configurações de descoberta. Modo de economia de dados aplica um filtro específico para que atualizações de presença e notificações de digitação sejam filtradas fora. Permitir integrações - Gerenciador de Integração - Integrações estão desativadas - Ative \'Permitir integrações\' em Configurações para fazer isto. + Gerenciador de integrações + Integrações estão desabilitadas + Habilite \'Permitir integrações\' em Configurações para fazer isto. Atualizar Senha A senha não é válida Senhas não correspondem @@ -1453,7 +1453,7 @@ Usar a câmera Usar o microfone Ler Mídia protegida por DRM - Nenhum gerenciador de integração configurado. + Nenhum gerenciador de integrações configurado. Para continuar você precisa aceitar os Termos deste serviço. Uma nova sessão está requisitando chaves de encriptação. \nNome de sessão: %1$s @@ -1502,7 +1502,7 @@ \n \nAviso: este arquivo pode ser deletado se o aplicativo for desinstalado. A chave de recuperação tem sido salva. - Um backup já existe em seu ServidorCasa + Um backup já existe em seu servidorcasa Parece que você já tem configurado backup de chave de uma outra sessão. Você quer substituí-lo pelo que você está criando\? Substituir Parar @@ -1592,7 +1592,7 @@ Verificar ao comparar um string de texto curto. Para máxima segurança, nós recomendamos que você faça isto em pessoa ou use um outro meio de comunicação confiado. Começar a Verificar - Requisição de Verificação Chegando + Requisição de Verificação Entrante Verifique esta sessão para marcá-la como confiada. Confiar em sessões de parceiras(os) dá a você paz de mente extra quando usando mensagens encriptadas ponta-a-ponta. Verificar esta sessão vai marcá-la como confiada, e também marcar sua sessão como confiada para a/o parceira(o). Verifique esta sessão ao confirmar que os seguintes emoji aparecem na tela da/do parceira(o) @@ -1610,7 +1610,7 @@ Requisição Cancelada A outra parte cancelou a verificação. \n%s - A verificação foi cancelada. + A verificação está cancelada. \nRazão: %s Verificação de Sessão Interativa Requisição de Verificação @@ -1626,7 +1626,7 @@ Disparidade de chave Disparidade de usuária(o) Erro Desconhecido - Você não está usando nenhum Servidor de Identidade + Você não está usando nenhum servidor de identidade Nenhum servidor de identidade está configurado, ele é requerido para resettar sua senha. Parece que você está tentando se conectar a um outro servidorcasa. Você quer fazer signout\? Editar @@ -1719,7 +1719,7 @@ Enviar uma nova mensagem direta Visualizar o diretório de salas Nome ou ID (#exemplo:matrix.org) - Ativar deslize para responder em timeline + Habilitar deslizar para responder em timeline Adicionar uma aba dedicada para notificações não-lidas em tela principal. Link copiado para clipboard Adicionar por ID matrix @@ -1757,8 +1757,8 @@ O código de verificação não está correto. Você está atualmente compartilhando endereços de email ou números de telefone no servidor de identidade %1$s. Você vai precisar reconectar-se a %2$s para parar de os compartilhar. Concorde com os Termos de Serviço do servidor de identidade (%s) para permitir você mesma(o) ser descobertável por endereço de email ou número de telefone. - Ativar verbose logs. - Verbose logs vão ajudar desenvolvedoras(es) ao prover mais logs quando você enviar uma RageShake. Mesmo quando ativado, o aplicativo não registra conteúdos de mensagem ou quaisquer outros dados privados. + Habilitar verbose logs. + Verbose logs vão ajudar desenvolvedoras(es) ao prover mais logs quando você enviar uma RageShake. Mesmo quando habilitado, o aplicativo não registra conteúdos de mensagem ou quaisquer outros dados privados. Por favor retente uma vez que você tenha aceitado os termos e condições de seu servidorcasa. Parece que o servidor está demorando muito para responder, isto pode ser causado por ou má conectividade ou um erro com o servidor. Por favor tente de novo daqui a pouco. Enviar anexo @@ -1885,7 +1885,7 @@ Eu tenho verificado meu endereço de email Sucesso! Sua senha tem sido resettada. - Você tem sido feito logout de todas suas sessões e você não vai mais receber notificações push. Para reativar notificações, faça signin de novo em cada dispositivo. + Você tem sido feito logout de todas suas sessões e você não vai mais receber notificações push. Para re-habilitar notificações, faça signin de novo em cada dispositivo. Voltar para Fazer Signin Aviso Sua senha ainda não tem sido mudada. @@ -1988,8 +1988,8 @@ Rápida-falha ${app_name} pode crashar com mais frequência quando um erro inesperado ocorre Prepende ¯\\_(ツ)_/¯ a uma mensagem de texto puro - Ativar encriptação - Uma vez ativada, encriptação não poder ser desativada. + Habilitar encriptação + Uma vez habilitada, encriptação não poder ser desabilitada. Seu domínio de email não está autorizado a se registrar neste servidor Signin desconfiado Eles correspondem @@ -2072,11 +2072,11 @@ Envia o dado emote colorido como um arco-íris Timeline Editor de mensagem - Ativar encriptação ponta-a-ponta… - Uma vez ativada, encriptação não poder ser desativada. - Ativar encriptação\? - Uma vez ativada, encriptação para uma sala não pode ser desativada. Mensagens enviadas numa sala encriptada não podem ser vistas pelo servidor, somente pelas(os) participantes da sala. Ativar encriptação pode prevenir que muitos bots e bridges de funcionarem corretamente. - Ativar encriptação + Habilitar encriptação ponta-a-ponta… + Uma vez habilitada, encriptação não poder ser desabilitada. + Habilitar encriptação\? + Uma vez habilitada, encriptação para uma sala não pode ser desabilitada. Mensagens enviadas numa sala encriptada não podem ser vistas pelo servidor, somente pelas(os) participantes da sala. Habilitar encriptação pode prevenir que muitos bots e bridges de funcionarem corretamente. + Habilitar encriptação Para estar segura(o), verifique %s ao checar um código de única vez. Para estar segura(o), faça isto em pessoa ou use uma outra forma de se comunicar. Compare os emoji únicos, assegurando que eles apareçam na mesma ordem. @@ -2084,15 +2084,15 @@ Mensagens com esta(e) usuária(o) são encriptadas ponta-a-ponta e não podem ser lidas por terceiros. Sua nova sessão agora está confirmada. Ela tem acesso a suas mensagens encriptadas, e outras(os) usuárias(os) vão vê-la como confiada. Assinatura Cruzada - Assinatura Cruzada está ativada + Assinatura Cruzada está habilitada \nChaves Privadas em dispositivo. - Assinatura Cruzada está ativada + Assinatura Cruzada está habilitada \nChaves são confiadas. \nChaves privadas não são conhecidas - Assinatura Cruzada está ativada. + Assinatura Cruzada está habilitada. \nChaves não são confiadas - Assinatura Cruzada não está ativada - O/a administrador(a) de seu servidor tem desativado encriptação ponta-a-ponta por default em salas privadas & Mensagens Diretas. + Assinatura Cruzada não está habilitada + O/a administrador(a) de seu servidor tem desabilitado encriptação ponta-a-ponta por default em salas privadas & Mensagens Diretas. Sessões Ativas Mostrar Todas as Sessões Gerenciar Sessões @@ -2178,7 +2178,7 @@ \n- A conexão de internet que qualquer um dos dois dispositivos está usando \n \nNós recomendamos que você mude sua senha & chave de recuperação em Configurações imediatamente. - Verifique seus dispositivos desde Configurações. + Verificação tem sido cancelada. Você pode começar verificação de novo. Verificação Cancelada Frasepasse de Recuperação Chave de Mensagem @@ -2212,8 +2212,8 @@ Salve-a em uma chave USB ou drive de backup Copie-a para seu armazenamento nuvem pessoal Você não pode fazer isso por celular - Encriptação ativada - Encriptação não ativada + Encriptação habilitada + Encriptação não habilitada Esperando por %s… Configuração de notificações Solucionar problemas @@ -2245,7 +2245,7 @@ Nome de usuária(o) e/ou senha incorretos. A senha entrada começa ou termina com espaços, por favor cheque-a. Esta conta tem sido desativada. Upgrade de encriptação disponível - Ativar Assinatura Cruzada + Habilitar Assinatura Cruzada Verifique-se a si mesma(o) & outras(os) para manter seus chats seguros Entre sua %s para continuar Não é uma chave de recuperação válida @@ -2262,7 +2262,7 @@ Se você não sabe sua Frasepasse de Backup de Chave, você pode %s. Chave de recuperação de Backup de Chave Prevenir screenshots do aplicativo - Ativar esta configuração adiciona FLAG_SECURE a todas as Atividades. Recomece o aplicativo para que a mudança tenha efeito. + Habilitar esta configuração adiciona FLAG_SECURE a todas as Atividades. Recomece o aplicativo para que a mudança tenha efeito. Arquivo de mídia adicionado à Galeria Não foi possível adicionar arquivo de mídia à Galeria Não foi possível salvar arquivo de mídia @@ -2376,8 +2376,8 @@ Revogar convite para %1$s\? Banida(o) por %1$s Falha para DesBanir usuária(o) - Notificações push estão desativadas - Revise suas configurações para permitir notificações push + Notificações push estão desabilitadas + Revise suas configurações para habilitar notificações push Escolha um PIN por segurança Confirme PIN Falha para validar PIN, por favor toque um novo. @@ -2386,9 +2386,9 @@ Resettar PIN Novo PIN Para resettar seu PIN, você vai precisar refazer login e criar um novo. - Ativar PIN + Habilitar PIN Se você quer resettar seu PIN, toque em Esqueceu PIN para fazer logout e resettá-lo. - Confirmar PIN para desativar PIN + Confirmar PIN para desabilitar PIN Prevenir chamada acidental Pedir por confirmação antes de começar uma chamada Você não tem permissão para começar uma chamada de conferência nesta sala @@ -2455,8 +2455,8 @@ Mostrar detalhes como nomes de salas e conteúdo de mensagens. Mostrar conteúdo em notificações Código PIN é a única maneira de destrancar ${app_name}. - Ativar biometria específica de dispositivo, como impressões digitais e reconhecimento de face. - Ativar biometria + Habilitar biometria específica de dispositivo, como impressões digitais e reconhecimento de face. + Habilitar biometria Configurar a proteção Proteger acesso usando PIN e biometria. Proteger acesso @@ -2543,17 +2543,17 @@ Este é o começo de seu histórico de mensagem direta com %s. Este é o começo desta conversa. Este é o começo de %s. - Você não tem permissão para ativar encriptação nesta sala. + Você não tem permissão para habilitar encriptação nesta sala. Criando sala… Alguns caracteres não são permitidos Este endereço já está em uso Endereço de sala - Você pode ativar isto se a sala vai somente ser usada para colaborar com times internos em seu servidorcasa. Isto não poder ser mudado mais tarde. + Você poderia habilitar isto se a sala vai somente ser usada para colaborar com times internos em seu servidorcasa. Isto não poder ser mudado mais tarde. Bloquear qualquer pessoa que não é parte de %s de jamais se juntar a esta sala %1$d de %2$d Criar uma nova conversa direta ao scannar um QR code Criar uma nova conversa direta por ID Matrix - A fim de descobrir contatos existentes que você conhece, você aceita enviar seus dados de contato (números de telefone e/ou emails) para o Servidor de Identidade configurado (%1$s)\? + A fim de descobrir contatos existentes que você conhece, você aceita enviar seus dados de contato (números de telefone e/ou emails) para o servidor de identidade configurado (%1$s)\? \n \nPara mais privacidade, os dados enviados serão hashados antes de serem enviados. Enviar emails e números de telefone @@ -2625,7 +2625,7 @@ Mudar permissões Mudar nome de sala Mudar visibilidade do histórico - Ativar encriptação da sala + Habilitar encriptação da sala Mudar endereço principal para a sala Mudar avatar da sala Modificar widgets @@ -2910,4 +2910,12 @@ Permissões faltando Para performar esta ação, por favor conceda a permissão Câmera a partir das configurações de sistema. Algumas permissões estão faltando para performar esta ação, por favor conceda as permissões a partir das configurações de sistema. + + Chamada de vídeo perdida + %d chamadas de vídeo perdidas + + + Chamadad de áudio perdida + %d chamadas de áudio perdidas + \ No newline at end of file diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index dc8387733c..20c151a9d6 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -23,9 +23,9 @@ %s ответил(а) на звонок. %s завершил(а) вызов. %1$s сделал(а) будущую историю комнаты видимой %2$s - всем членам, с момента их приглашения. - всем членам, с момента присоединения. - всем членам. + всем участникам, с момента их приглашения. + всем участникам, с момента присоединения. + всем участникам. всем. неизвестно (%s). %1$s включил(а) сквозное шифрование (%2$s) @@ -236,16 +236,16 @@ 🎉 Всем серверам запрещено участвовать! Эта комната больше не может быть использована. Без изменений. Пустая комната (была %s) - • Соответствующий сервер %s заблокирован. - • Сервер, соответствующий буквальным IP-адресам, теперь запрещён. - • Сервер, соответствующий буквальным IP-адресам, теперь разрешён. - • Сервер, соответствующий %s, теперь запрещён. - • Сервер, соответствующий %s, теперь разрешён. - • Сервер, соответствующий %s, был удалён из списка блокировки. - • Сервер, соответствующий буквальным IP-адресам, запрещён. - • Сервер, соответствующий буквальным IP-адресам, разрешён. - • Сервер, соответствующий %s, разрешён. - • Сервер, соответствующий %s, был удалён из разрешённого списка. + • Соответствующие серверы %s заблокированы. + • Серверы, соответствующие буквальным IP-адресам, теперь запрещены. + • Серверы, соответствующие буквальным IP-адресам, теперь разрешены. + • Серверы, соответствующие %s, теперь запрещены. + • Серверы, соответствующие %s, теперь разрешены. + • Серверы, соответствующие %s, были удалены из списка блокировки. + • Серверы, соответствующие буквальным IP-адресам, запрещены. + • Серверы, соответствующие буквальным IP-адресам, разрешены. + • Серверы, соответствующие %s, разрешены. + • Серверы, соответствующие %s, были удалены из разрешённого списка. Вы изменили права доступа сервера (ACL) для этой комнаты. %s изменил права доступа сервера (ACL) для этой комнаты. Вы настроили права доступа сервера (ACL) для этой комнаты. @@ -392,7 +392,7 @@ Создать аккаунт Войти Выйти - URL сервера + URL домашнего сервера URL сервера авторизации Поиск Начать новый чат @@ -435,9 +435,9 @@ Регистрация одновременно по email и номеру телефона пока не поддерживается. Только номер телефона будет связан с аккаунтом. \n \nВы можете добавить свой email в настройках профиля. - Проверка не являетесь ли вы роботом + Этот домашний сервер хочет убедиться, что вы не робот Логин уже используется - Сервер: + Домашний сервер: Сервер идентификации: Я проверил мой email адрес Для сброса пароля введите email привязанный к учетной записи: @@ -529,7 +529,7 @@ Просмотр Отклонить - Перейти к первому непрочитанному сообщению. + Перейти к непрочитанному %s пригласил вас присоединиться к этой комнате Приглашение пришло на адрес %s, который не связан с этим аккаунтом. @@ -591,7 +591,7 @@ Отправить неотправленные сообщения Удалить неотправленные сообщения Файл не найден - У вас нет прав писать сообщения в этом чате + У вас нет прав писать сообщения в этом чате. Доверять Не доверять @@ -711,7 +711,7 @@ Пароль: Отправить Авторизован как - Сервер + Домашний сервер Сервер идентификации Ожидается подтверждение Проверьте электронную почту и перейдите по высланной ссылке. Затем нажмите продолжить. @@ -760,9 +760,9 @@ Кто имеет доступ к комнате? Все - Только члены (с момента выбора этой опции) - Только члены (с момента приглашения) - Только члены (с момента присоединения) + Только участники (с момента выбора этой опции) + Только участники (с момента приглашения) + Только участники (с момента присоединения) Для генерации ссылки команда должна иметь адрес. Только приглашенные @@ -855,7 +855,7 @@ Выбор списка комнат Сервер возможно недоступен или перегружен Введите домашний сервер для отображения списка публичных комнат - URL домашнего сервера + Имя сервера Все комнаты на сервере %s Все местные комнаты %s @@ -1116,7 +1116,7 @@ Выкинуть пользователя с заданным ID Изменить ваш псевдоним Вкл/выкл markdown - Эта комната была заменена и больше не активна + Эта комната была заменена и больше не активна. Этот разговор продолжается здесь Эта комната является продолжением другого разговора Нажмите здесь для просмотра старых сообщений @@ -1249,8 +1249,8 @@ Не удалось получить токен FCM: \n%1$s Регистрация токена - Токен FCM успешно зарегистрирован на сервере. - Не удалось зарегистрировать токен FCM на сервере: + Токен FCM успешно зарегистрирован на домашнем сервере. + Не удалось зарегистрировать токен FCM на домашнем сервере: \n%1$s Служба уведомлений Служба уведомлений запущена. @@ -1671,7 +1671,7 @@ Не удалось обновить настройки. Предпочтительный интервал синхронизации Обнаружение - Будет использовать%s в качестве помощника, если ваш домашний сервер не предлагает его (ваш IP-адрес будет доступен во время разговора) + Будет использовать %s в качестве помощника, если ваш домашний сервер не предлагает его (ваш IP-адрес будет доступен во время разговора) Добавьте идентификационный сервер в свои настройки, чтобы выполнить это действие. Режим фоновой синхронизации ${app_name} будет синхронизироваться в фоновом режиме таким образом, чтобы сохранить ограниченные ресурсы устройства (батарея). @@ -1932,7 +1932,7 @@ Соединение с сервером потеряно Используйте пароль восстановления или ключ Разблокировать историю зашифрованных сообщений - Проверьте свои устройства в разделе Настройки. + Проверка была отменена. Вы можете начать проверку снова. Парольная фраза для восстановления Пароль учётной записи Задайте %s @@ -2078,7 +2078,7 @@ Вы сделали комнату только по приглашению. Сохраняйте приватность ваших переписок с помощью шифрования Расширьте и персонализируйте свой опыт использования - Присоединяйтесь к миллионам бесплатных на самом большом публичном сервере + Присоединяйтесь к миллионам бесплатно на крупнейшем публичном сервере Войти в %1$s Введите адрес сервера, который вы хотите использовать На ваш почтовый ящик будет отправлено письмо с подтверждением установки нового пароля. @@ -2676,9 +2676,9 @@ Изменение того, кто может читать историю, будет применяться только к будущим сообщениям в этой комнате. Видимость существующей истории не изменится. Отменить публикацию Добавить - отправляет снег ❄️ + отправляет снегопад ❄️ отправляет конфетти 🎉 - Отправляет данное сообщение со снегом + Отправляет данное сообщение со снегопадом Отправляет данное сообщение с конфетти Очистить историю Единая точка входа @@ -2821,4 +2821,187 @@ Начальная синхронизация: \nОжидание ответа сервера… Сообщение отправлено + Отзыв о пространствах + Адреса пространства + Извините, при попытке присоединиться произошла ошибка: %s + Обновить до рекомендованной версии комнаты + В этой комнате запущена версия комнаты %s, которую этот домашний сервер пометил как нестабильную. + Для обновления комнаты необходимо разрешение + Автоматическое обновление родительского пространства + Автоматическое приглашение пользователей + Вы обновили эту комнату с %s до %s. + Обновление комнаты - это расширенное действие, которое обычно рекомендуется, когда комната работает нестабильно из-за ошибок, отсутствующих функций или уязвимостей безопасности. +\nОбычно это влияет только на то, как комната обрабатывается на сервере. + Модернизировать приватную комнату + Модернизировать публичную комнату + Обновление + Пожалуйста, будьте терпеливы, это может занять некоторое время. + Присоединиться к замещающей комнате + В настоящее время люди не могут присоединиться к созданным вами приватным комнатам. +\n +\nМы улучшим это в рамках бета-версии, но мы просто хотели сообщить вам об этом. + Пространства для членов команды еще не совсем готовы, но вы все еще можете их попробовать + Комната без названия + Некоторые комнаты могут быть скрыты, потому что они приватные, и вам нужно приглашение. + Некоторые комнаты могут быть скрыты, потому что они приватные, и вам нужно приглашение. +\nУ вас нет разрешения на добавление комнат. + В этом пространстве нет комнат + Для получения дополнительной информации обратитесь к администратору домашнего сервера + Похоже, что ваш домашний сервер пока не поддерживает пространства + Чувствуете себя экспериментатором\? +\nВы можете добавить существующие пространства в пространство. + Экспериментальное пространство - показывать в Главной только сирот + Управление комнатами и пространствами + Отметить как не рекомендуется + Отметить как рекомендуется + Предложенно + Сделайте это пространство публичным + Управление комнатами + Ищете кого-то не в %s\? + %s приглашает вас + Предупреждение: требует поддержки сервера и экспериментальной версии комнаты + Экспериментальное пространство - Ограниченная комната. + Вы приглашены + Пространства - это новый способ группировки комнат и людей. + Добро пожаловать в Пространства! + Добавить комнаты + Добавить существующие комнаты и пространство + Вы являетесь администратором этого пространства, перед уходом убедитесь, что передали права администратора другому пользователю. + Это пространство не является публичным. Вы не сможете присоединиться к нему без приглашения. + Вы здесь единственный человек. Если вы уйдёте, никто не сможет присоединиться в будущем, включая вас. + Вы уверены, что хотите покинуть пространство\? + Покинуть пространство + Добавить комнаты + Список комнат + + %d человек, которого вы знаете, уже присоединился + %d человека, которых вы знаете, уже присоединились + %d человек, которых вы знаете, уже присоединились + %d человек, которых вы знаете, уже присоединились + + Добро пожаловать в %1$s, %2$s. + Вы ещё не находитесь ни в одной комнате. Ниже приведены некоторые предлагаемые комнаты, но вы можете посмотреть другие с помощью зелёной кнопки внизу справа. + В данный момент этот псевдоним недоступен. +\nПовторите попытку позже или попросите администратора комнаты проверить, есть ли у вас доступ. + Присоединиться в любом случае + Присоединиться к пространству + Создать пространство + Пока пропустить + Присоединяйтесь к моему пространству %1$s %2$s + Они не будут участвовать в %s + Только в эту комнату + Они смогут изучить %s + Пригласить в %s + Поделиться ссылкой + Пригласить по имени пользователя + Пригласить по электронной почте + На данный момент здесь только вы. С другими в %s будет ещё лучше. + Пригласить в %s + Пригласить людей + Пригласите людей в свое пространство + Описание + Создание пространства… + Случайный + Общие + Давайте создадим комнату для каждого из них. Позже можно добавить и другие, в том числе уже существующие. + Над чем вы работаете\? + Мы создадим для них комнаты. Позже вы сможете добавить и другие. + Какие обсуждения вы хотите провести в %s\? + Дайте ему название, чтобы продолжить. + Добавьте некоторые детали, чтобы помочь людям идентифицировать его. Вы сможете изменить их в любой момент. + Добавьте некоторые детали, чтобы помочь ему выделиться. Вы сможете изменить их в любой момент. + Создание пространства + Только по приглашениям, лучше для себя или команды + Приватное + Открыто для всех, лучше всего подходит для сообществ + Публичное + Приватное пространство для вас и членов команды + Приватное пространство для организации ваших комнат + Я и члены команды + Только я + Убедитесь, что нужные люди имеют доступ к %s. Вы сможете изменить это позже. + С кем вы работаете\? + Чтобы присоединиться к существующему пространству, вам необходимо получить приглашение. + Вы сможете изменить это позже + Какой тип пространства вы хотите создать\? + Пространства - это новый способ группировки комнат и людей + Ваше приватное пространство + Ваше публичное пространство + Добавить простанство + Приватное пространство + Публичное пространство + Обновляет комнату до новой версии + Покинуть комнату с заданным id (или текущую комнату, если null) + Присоединитесь к пространству с заданным id + Создать пространство + Это пространство публичное + Эта комната публичная + Непроверенные + Неизвестное лицо + Перевести на %1$s + Запросить с %1$s + + Отправить видео в исходном размере + Отправить видео в исходном размере + Отправить видео в исходном размере + Отправить видео в исходном размере + + Отправить медиафайлы в исходном размере + нестабильная + стабильная + Версия по умолчанию + Версии комнаты 👓 + Проверьте, сравнив эмодзи + Сканирование с помощью этого устройства + Сканируйте код с помощью другого устройства или переключитесь и сканируйте с помощью этого устройства + Адрес пространства + Файл слишком большой для загрузки. + Эта функция находится в бета-версии + Поиск по имени + Сжатие видео %d%% + Сжатие изображения… + Дать отзыв + Отзыв не отправлен (%s) + Спасибо, ваш отзыв успешно отправлен + Вы можете связаться со мной, если у вас возникнут какие-либо последующие вопросы + Вы используете бета-версию пространств. Ваши отзывы помогут при разработке следующих версий. Ваша платформа и имя пользователя будут отмечены, чтобы мы могли максимально использовать ваш отзыв. + Отзыв + Извините, при попытке присоединиться к конференции произошла ошибка + Этот сервер уже присутствует в списке + Не удается найти этот сервер или список его комнат + Введите имя нового сервера, который вы хотите исследовать. + Добавить новый сервер + Ваш сервер + Любой человек в пространстве с этой комнатой может найти её и присоединиться к ней. Только администраторы этой комнаты могут добавить её в пространство. + Пространства + Любой желающий может найти комнату и присоединиться + Публичный + Только приглашенные люди могут найти и присоединиться + Приватный + Неизвестная настройка доступа (%s) + Любой может постучаться в комнату, участники могут принять или отклонить его + Просмотреть и управлять адресами этого пространства. + Разрешить гостям присоединяться + Продолжить в любом случае + + Пропущенный видеозвонок + %d пропущенных видеозвонка + %d пропущенных видеозвонков + %d пропущенных видеозвонков + + + Пропущенный аудиовызов + %d пропущенных аудиовызова + %d пропущенных аудиовызовов + %d пропущенных аудиовызовов + + Использовать по умолчанию и больше не спрашивать + Всегда спрашивать + URL API домашнего сервера + Пространства + Приглашения + Предлагаемые комнаты + Отсутствующие разрешения + Для выполнения этого действия, пожалуйста, предоставьте разрешение Камеры в настройках системы. + Для выполнения этого действия отсутствуют некоторые разрешения, пожалуйста, предоставьте разрешения в настройках системы. \ No newline at end of file diff --git a/vector/src/main/res/values-sq/strings.xml b/vector/src/main/res/values-sq/strings.xml index 85a074ab86..ea2bc85917 100644 --- a/vector/src/main/res/values-sq/strings.xml +++ b/vector/src/main/res/values-sq/strings.xml @@ -228,7 +228,7 @@ • Shërbyesit që kanë përputhje me %s tani janë të lejuar. • Shërbyesit që kanë përputhje me %s u hoqën nga lista e ndalimeve. • Shërbyesit që kanë përputhje me %s tani janë të ndaluar. - • Shërbyesit që kanë përputhje me %s janë të ndaluar. + • Shërbyesit që kanë përputhje me %s janë të lejuar. • Shërbyesit që kanë përputhje me %s janë të ndaluar. Ndryshuat adresat për këtë dhomë. %1$s ndryshoi adresat për këtë dhomë. @@ -397,7 +397,7 @@ Ky shërbyes Home do të donte të sigurohej se s’jeni robot Emër përdoruesi në përdorim Shërbyes Home: - Shërbyes Identitetesh: + Shërbyes identitetesh: E kam verifikuar adresën time email Që të ricaktoni fjalëkalimin, jepni adresën email të lidhur me llogarinë tuaj: Duhet dhënë adresa email e lidhur me llogarinë tuaj. @@ -660,7 +660,7 @@ Parashtroje I futur si Shërbyes Home - Shërbyes Identitetesh + Shërbyes identitetesh Ndërfaqe përdoruesi Gjuhë Zgjidhni gjuhë @@ -1132,8 +1132,8 @@ S’u arrit të merreh token FCM: \n%1$s Regjistrim Token-i - Token-i FCM u regjistrua me sukses te Shërbyes Home. - S’u arrit të regjistrohej token FCM te Shërbyes Home: + Token-i FCM u regjistrua me sukses te shërbyesi Home. + S’u arrit të regjistrohej token FCM te shërbyesi Home: \n%1$s Shërbim Njoftimesh Shërbimi i Njoftimeve po xhiron. @@ -1402,7 +1402,7 @@ Mospërputhje kyçesh Mospërputhje përdoruesish Gabim i Panjohur - Ka tashmë një kopjeruajtje te Shërbyesi juaj Home + Ka tashmë një kopjeruajtje te shërbyesi juaj Home Duket sikur keni tashmë kopjeruajtje kyçesh nga një sesion tjetër. Doni të zëvendësohet me atë që po krijoni\? Zëvendësoje Ndale @@ -1473,7 +1473,7 @@ Faleminderit, sugjerimi u dërgua me sukses S’u arrit të dërgohej sugjerimi (%s) Shfaq te rrjedha kohore akte të fshehura - Përgjegjës Integrimesh + Përgjegjës integrimesh Pa përgjegjës Integrimesh të formësuar. app_id: push_key: @@ -1545,7 +1545,7 @@ Administroni rregullimet tuaja për zbulime. Emër publik (i dukshëm për persona me të cilët komunikoni) Emri publik i një sesioni është i dukshëm për persona me të cilët komunikoni - S’po përdorni ndonjë Shërbyes Identitetesh + S’po përdorni ndonjë shërbyes identitetesh S’ka shërbyes identitetesh të formësuar, kjo është e domosdoshme për ricaktimin e fjalëkalimit tuaj. Duket se po rrekeni të lidheni me një tjetër shërbyes Home. Doni të bëhet dalja\? Që të përgjigjeni te rrjedha kohore, aktivizoni fërkimin @@ -1626,8 +1626,8 @@ Këtë s’e bëni dot që nga ${app_name} për celular Lypset mirëfilltësim Integrime - Përdorni një Përgjegjës Integrimesh që të administroni robotë, ura, widget-e dhe paketa ngjitësish. -\nPërgjegjësit e Integrimeve marrin të dhëna formësimi dhe mund të ndryshojnë widget-e, të dërgojnë ftesa për në dhoma dhe të caktojnë shkallë pushteti në emrin tuaj. + Përdorni një përgjegjës integrimesh që të administroni robotë, ura, widget-e dhe paketa ngjitësish. +\nPërgjegjësit e integrimeve marrin të dhëna formësimi dhe mund të ndryshojnë widget-e, të dërgojnë ftesa për në dhoma dhe të caktojnë shkallë pushteti në emrin tuaj. Lejo integrim Widget Ngarko Widget @@ -1999,7 +1999,7 @@ \n- Lidhja internet që përdor njëra pajisje, ose tjetra \n \nKëshillojmë të ndryshoni menjëherë fjalëkalimin & kyçin tuaj të rimarrjeve te Rregullimet. - Verifikoni pajisjet tuaja që prej Rregullimeve. + Verifikimi u anulua. Mund ta rifilloni verifikimin. Verifikimi u Anulua Frazëkalim Rikthimesh Kyç Mesazhesh @@ -2469,7 +2469,7 @@ %1$d nga %2$d Krijoni një bisedë të re të drejtpërdrejtë duke skanuar një kod QR Krijoni një bisedë të re të drejtpërdrejtë përmes ID-je Matrix - Që të mund të zbulohet kontakte ekzistuese që njihni, pranoni të dërgohen të dhënat tuaja të kontaktit (numra telefonash dhe/ose email-e) te Shërbyesi i formësuar për Identitete (%1$s)\? + Që të mund të zbulohet kontakte ekzistuese që njihni, pranoni të dërgohen të dhënat tuaja të kontaktit (numra telefonash dhe/ose email-e) te shërbyesi i formësuar për identitete (%1$s)\? \n \nPër më tepër privatësi, të dhënat e dërguara do të kodohen, para se të dërgohen. Dërgoni email-e dhe numra telefonash @@ -2830,4 +2830,12 @@ Mungojnë leje Për kryerjen e këtij veprimi, ju lutemi, akordoni leje Kamerës që nga rregullimet e sistemit. Për kryerjen e këtij veprimi mungojnë disa leje, ju lutemi, akordojini lejet që nga rregullimet e sistemit. + + Thirrje video e humbur + %d thirrje video të humbura + + + Thirrje audio e humbur + %d thirrje audio të humbura + \ No newline at end of file diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index 9941e387db..0239932106 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -1335,7 +1335,7 @@ Стоп Замінити Схоже у вас вже є резервна копія ключа налаштування з іншого сеансу. Хочете замінити його тим, який ви створюєте\? - Резервна копія вже існує на вашому HomeServer + Резервна копія вже існує на вашому homeserver Ключ відновлення збережено. Ключ відновлення збережено до теки «%s». \n @@ -1516,7 +1516,7 @@ Включає події запрошення/приєднання/виходу/видалення/заборони та зміни зображень профілю/видимих імен. Показати стан подій учасників кімнати Керування криптографічними ключами - Використовуйте Менеджер інтеграції для керування ботами, мостами, знадобами та пакунками наліпок. + Використовуйте менеджер інтеграції для керування ботами, мостами, знадобами та пакунками наліпок. \nМенеджери інтеграції отримують дані конфігурації та можуть змінювати знадоби, надсилати запрошення до кімнати та надавати права від вашого імені. Інтеграції @@ -1538,7 +1538,7 @@ \nЗалежно від стану ресурсів вашого пристрою, синхронізацію може бути відкладено операційною системою. Оптимізовано для батареї Режим фонової синхронізації - Застосунки не потребують з\'єднання з HomeServer у фоновому режимі, це має скоротити споживання батареї + Застосунки не потребують з\'єднання з homeserver у фоновому режимі, це має скоротити споживання батареї Нехтувати оптимізацією Якщо користувач залишає пристрій від\'єднаним та нерухомим впродовж певного часу з вимкненим екраном, пристрій переходить у режим дрімання. Це запобігає доступу програм до мережі та відкладає їх завдання, синхронізацію та стандартні сигнали тривоги. Оптимізація акумулятора не впливає на ${app_name}. @@ -1570,9 +1570,9 @@ Застосунок отримує PUSH Застосунок очікує PUSH Випробувальне надсилання - Не вдалося зареєструвати токен FCM на HomeServer: + Не вдалося зареєструвати токен FCM на homeserver: \n%1$s - Токен FCM успішно зареєстровано на HomeServer. + Токен FCM успішно зареєстровано на homeserver. Реєстрація токена Додати обліковий запис [%1$s] @@ -2022,9 +2022,9 @@ Зазначте, будь ласка, адресу сервера ідентифікації Неможливо під\'єднатись до сервера ідентифікації Зазначте адресу сервера ідентифікації - Чи погоджуєтесь ви надіслати дані ваших контактів (номери телефонів та/або електронні адреси) на налаштований сервер ідентифікації(%1$s) задля виявлення відомих вам наявних контактів\? + Чи погоджуєтесь ви надіслати дані ваших контактів (номери телефонів та/або електронні адреси) на налаштований сервер ідентифікації(%1$s) для виявлення відомих вам наявних контактів\? \n -\nДля поліпшення приватності дані буде захешовано перед надсиланням. +\nДля поліпшення приватності дані буде хешовано перед надсиланням. Ласкаво просимо! Повторити Від\'єднання від вашого сервера ідентифікації означатиме, що ви не будете виявними для інших користувачів та не зможете запрошувати інших через електронну пошту або номер телефону. diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml index f3e6219bf0..051cbc72b3 100644 --- a/vector/src/main/res/values-zh-rCN/strings.xml +++ b/vector/src/main/res/values-zh-rCN/strings.xml @@ -1415,7 +1415,7 @@ 在你的设置中添加身份服务器以执行此操作。 取消邀请 降低你自己的级别? - 你家无法撤销此操作因为你正在降低你的级别,如果你是聊天室中最后一个特权用户将无法恢复特权。 + 你正在降低你的级别,此操作无法撤销。如果你是聊天室中最后一个特权用户,你将无法恢复特权。 降级 忽略用户 忽略此用户将从你共享的聊天室移除他们的消息。 @@ -1451,8 +1451,8 @@ %s \n取决于资源(电量)或设备状态(睡眠)同步可能会延迟。 集成 - 使用集成管理器管理机器人,桥接,部件和贴纸包。 -\n集成管理器接收配置数据,可以代表你修改部件,发送聊天室邀请及设置特权等级。 + 使用集成管理器管理机器人、桥接、部件和贴纸包。 +\n集成管理器接收配置数据,可以代表你修改部件、发送聊天室邀请及设置特权等级。 安全备份 管理 设置安全备份 @@ -2024,7 +2024,7 @@ \n- 设备使用的网络连接 \n \n我们推荐你在设置中立即更换你的密码和恢复密钥。 - 通过设置验证你的设备。 + 已取消验证。 您可以重新开始验证。 验证已取消 恢复密语 消息密钥 @@ -2474,11 +2474,11 @@ 未验证,缺少有效验证凭证 返回 系统默认 - • 匹配 %s 的服务器已被屏蔽。 - • IP 地址匹配的服务器已被屏蔽。 - • IP 地址匹配的服务器已被允许。 - • 匹配 %s 的服务器已被屏蔽。 - • 匹配 %s 的服务器已被允许。 + • 匹配 %s 的服务器现已被屏蔽。 + • 已封禁匹配 IP 地址的服务器。 + • 已允许匹配 IP 地址的服务器。 + • 匹配 %s 的服务器被屏蔽。 + • 已允许匹配 %s 的服务器。 已勾选 已选中 活跃通话(%1$s) @@ -2746,11 +2746,11 @@ 消息已发送 🎉 所有服务器都被禁止参与!此聊天室已无法再使用。 无更改。 - • 服务器匹配 IP 常量,现已被封禁。 - • 服务器匹配 IP 常量,现已被允许。 - • 服务器符合 %s 已从允许列表中移除。 - • 服务器符合 %s 现已被允许。 - • 服务器符合 %s 已从封禁列表中移除。 + • 已封禁匹配 IP 地址的服务器。 + • 现已允许匹配 IP 地址的服务器。 + • 已从允许列表中移除匹配 %s 的服务器。 + • 已允许匹配 %s 的服务器。 + • 已从封禁列表中移除匹配 %s 的服务器。 未命名的聊天室 私有空间 公开空间 @@ -2797,4 +2797,10 @@ 缺少权限 要执行此操作,请从系统设置中授予相机权限。 缺少执行此操作的某些权限,请从系统设置中授予权限。 + + %d 个未接视频电话 + + + %d 个未接音频电话 + \ No newline at end of file diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index dd32aaf460..e84e948d08 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -214,18 +214,18 @@ %1$s, %2$s 與 %3$s 🎉 禁止所有伺服器參與!無法再使用此聊天室。 無變更。 - • 禁止伺服器符合 IP 文字。 - • 允許伺服器符合 IP 文字。 - • 伺服器符合 %s 已從允許清單中移除。 - • 允許伺服器符合 %s。 - • 伺服器符合 %s 已從禁止清單中移除。 - • 現在禁止伺服器符合 %s。 + • 禁止符合 IP 文字的伺服器。 + • 允許符合 IP 文字的伺服器。 + • 符合 %s 的伺服器已從允許清單中移除。 + • 允許符合 %s 的伺服器。 + • 符合 %s 的伺服器已從禁止清單中移除。 + • 現在禁止符合 %s 的伺服器。 您為此聊天室變更了伺服器 ACL。 %s 為此聊天室變更了伺服器 ACL。 - • 禁止伺服器符合 IP 文字。 - • 允許伺服器符合 IP 文字。 - • 已允許伺服器符合 %s。 - • 已禁止伺服器符合 %s。 + • 禁止符合 IP 文字的伺服器。 + • 允許符合 IP 文字的伺服器。 + • 已允許符合 %s 的伺服器。 + • 已禁止符合 %s 的伺服器。 您為此聊天室設定了伺服器 ACL。 %s 為此聊天室設定了伺服器 ACL。 您變更了此聊天室的地址。 @@ -456,8 +456,8 @@ 聊天室名稱 聊天室主題 通話 - 通話已連接 - 通話正在連接… + 通話已連線 + 通話正在連線…… 通話結束 正在通話… 來電 @@ -1971,7 +1971,7 @@ \n- 任一裝置正在使用的網際網路連線 \n \n我們建議您立刻在設定中變更您的密碼與復原金鑰。 - 透過設定驗證您的裝置。 + 已取消驗證。您可以再次開始驗證。 驗證已取消 復原通關密語 訊息金鑰 @@ -2787,4 +2787,10 @@ 缺少權限 要執行此動作,請從系統設定中授予「相機」權限。 缺少執行此動作的部份權限,請從系統設定中授予權限。 + + %d 通未接聽通話 + + + %d 通未接聽通話 + \ No newline at end of file diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index f421e451a9..8e6bf85eae 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1475,11 +1475,21 @@ Anyone can knock on the room, members can then accept or reject Unknown access setting (%s) Private + Private (Invite Only) Only people invited can find and join Public Anyone can find the room and join - Spaces + Space members only Anyone in a space with this room can find and join it. Only admins of this room can add it to a space. + Members of Space %s can find, preview and join. + Allow space members to find and access. + Spaces which can access + Decide which spaces can access this room. If a space is selected its members will be able to find and join Room name. + Select spaces + Tap to edit spaces + Decide who can find and join this room. + Space you know that contain this room + Other spaces or rooms you might not know Banned users @@ -3435,6 +3445,7 @@ Please be patient, it may take some time. Upgrade + Upgrade Required Upgrade public room Upgrade private room Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.\nThis usually only affects how the room is processed on the server. @@ -3442,6 +3453,7 @@ Automatically invite users Automatically update space parent You need permission to upgrade a room + Allow anyone in %s to find and access. You can select other spaces too. This room is running room version %s, which this homeserver has marked as unstable. Upgrade to the recommended room version @@ -3463,4 +3475,9 @@ Cannot record a voice message Cannot reply or edit while voice message is active Voice Message (%1$s) + + Anyone in %s will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime. + Anyone in a parent space will be able to find and join this room - no need to manually invite everyone. You’ll be able to change this in room settings anytime. + + Please note upgrading will make a new version of the room. All current messages will stay in this archived room. diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml index 03232dc8a4..bacf323b76 100644 --- a/vector/src/main/res/xml/vector_settings_notifications.xml +++ b/vector/src/main/res/xml/vector_settings_notifications.xml @@ -97,7 +97,7 @@ + app:fragment="im.vector.app.features.settings.notifications.VectorSettingsNotificationsTroubleshootFragment" />