From 0c10e7a22b22037f16dd29bc1d532e4eae419f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 9 Aug 2022 16:28:40 +0000 Subject: [PATCH 001/270] Translated using Weblate (Estonian) Currently translated at 99.6% (2322 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- vector/src/main/res/values-et/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-et/strings.xml b/vector/src/main/res/values-et/strings.xml index 124ca1eae7..bb39ecfb5d 100644 --- a/vector/src/main/res/values-et/strings.xml +++ b/vector/src/main/res/values-et/strings.xml @@ -2594,4 +2594,8 @@ %1$s ja %2$s E-posti aadress on kinnitamata, palun vaata oma saabunud e-kirju + Kaardi laadimine ei õnnestu. +\nSee koduserver ei pruugi olla seadistatud kuvama kaarte. + Ava seadistused + Kõik vestlused \ No newline at end of file From 0cda6af1f6112d934f36291da525e23edf59eaa8 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Tue, 9 Aug 2022 15:35:03 +0000 Subject: [PATCH 002/270] Translated using Weblate (Persian) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- vector/src/main/res/values-fa/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-fa/strings.xml b/vector/src/main/res/values-fa/strings.xml index 591ae21198..42daf1dff8 100644 --- a/vector/src/main/res/values-fa/strings.xml +++ b/vector/src/main/res/values-fa/strings.xml @@ -2603,4 +2603,8 @@ %1$s و %2$s رایانامه تأیید نشده. صندوق ورودیتان را بررسی کنید + ناتوان در بار کردن نقشه +\nشاید این کارساز خانگی برای نمایش نقشه‌ها پیکربندی نشده باشد. + گشودن تنظیمات + تمامی گپ‌ها \ No newline at end of file From 7bc8b42028d1126193d757e5e6a0e13601e0edc6 Mon Sep 17 00:00:00 2001 From: Linerly Date: Tue, 9 Aug 2022 17:41:31 +0000 Subject: [PATCH 003/270] Translated using Weblate (Indonesian) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- vector/src/main/res/values-in/strings.xml | 24 ++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index cbe5173920..ff1fa24255 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -1420,7 +1420,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Terverifikasi Verifikasi Gunakan sesi yang ada untuk memverifikasi yang satu ini, memberikan aksesnya ke pesan terenkripsi. - Verifikasi login ini + Verifikasi perangkat ini %d sesi aktif @@ -2490,7 +2490,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Pesan di obrolan ini akan dienkripsi secara ujung-ke-ujung. Mulai Ikuti petunjuk yang terkirim ke %s - Untuk mengonfirmasi email Anda, ketuk tombol dalam email yang kami kirim ke %s + Ikuti petunjuk yang terkirim ke %s %d pesan dihapus @@ -2504,7 +2504,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Lupa kata sandi Kirim ulang email Belum menerima email\? - Periksa email Anda untuk memverifikasi. + Verifikasi email Anda Kirim ulang kode Sebuah kode terkirim ke %s Konfirmasi nomor telepon Anda @@ -2541,4 +2541,22 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Pilih secara manual Atur secara otomatis Pilih ukuran font + Terima akses kamera / mikrofon widget Element Call secara otomatis + Aktifkan pintasan izin Element Call + Lokasi langsung + Tidak dapat memuat peta +\nHomeserver ini mungkin tidak diatur untuk menampilkan peta. + Buka pengaturan + Kode QR ini tampaknya tidak benar. Mohon coba verifikasi dengan metode lain. + Anda tidak akan dapat mengakses riwayat pesan terenkripsi. Atur ulang Cadangan Pesan Aman dan kunci-kunci verifikasi Anda untuk memulai secara segar. + Tidak dapat memverifikasi perangkat ini + Apa alamat server Anda\? + Di mana percakapan Anda tinggal + Memperbarui data Anda… + + %1$s dan %2$d lainnya + + %1$s dan %2$s + Email belum diverifikasi, periksa kotak masuk Anda + Semua Obrolan \ No newline at end of file From a01fe4d8e2477eaf806c565d8e65b8c1914f987f Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Wed, 10 Aug 2022 23:24:39 +0000 Subject: [PATCH 004/270] Translated using Weblate (Russian) Currently translated at 99.0% (2309 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index 1fd522c7d5..51e8a72ec7 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -960,7 +960,7 @@ Изменение сообщения Изменения не найдены Отфильтровать беседы… - Не можете найти то, что ищете\? + Не можете найти нужное\? Создать новую комнату Отправить новое личное сообщение Просмотр каталога комнат @@ -1455,7 +1455,7 @@ %d сессии активны %d сессий активно - Подтвердите это устройство + Подтверждение этого устройства Используйте существующую сессию для подтверждения этой, предоставив ей доступ к зашифрованным сообщениям. Инструменты для разработчиков Данные учётной записи @@ -1743,10 +1743,10 @@ Защитите доступ с помощью PIN-кода и биометрии. Защита доступа Вы перезапустите приложение без истории, сообщений, доверенных устройств или доверенных пользователей - Если сбросить все + Если сбросить всё Делайте это только в том случае, если у вас нет другого устройства, с которого вы можете проверить это устройство. - Сбросить все - Забыли или потеряли все варианты восстановления\? Сбросить все + Сбросить всё + Забыли или потеряли все варианты восстановления\? Сбросить всё Вы вошли. %s вошёл(ла). Сообщения в этой переписке защищены сквозным шифрованием. @@ -2663,4 +2663,8 @@ Или Создать учётную запись %1$s и %2$s + Открыть настройки + Не удалось загрузить карту +\nВозможно, этот домашний сервер не настроен для отображения карт. + Все Беседы \ No newline at end of file From 36c8877dbe11240a8b0f39ac299d954042484684 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Wed, 10 Aug 2022 11:49:32 +0000 Subject: [PATCH 005/270] Translated using Weblate (Slovak) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/ --- vector/src/main/res/values-sk/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-sk/strings.xml b/vector/src/main/res/values-sk/strings.xml index cac6187d8a..3ca5d6ee62 100644 --- a/vector/src/main/res/values-sk/strings.xml +++ b/vector/src/main/res/values-sk/strings.xml @@ -2653,4 +2653,8 @@ %1$s a %2$s E-mail nie je overený, skontrolujte si schránku + Nie je možné načítať mapu +\nTento domovský server nemusí byť nakonfigurovaný na zobrazovanie máp. + Otvoriť nastavenia + Všetky konverzácie \ No newline at end of file From 7e8b5479c4df4375dd073806891084a422a76117 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Wed, 10 Aug 2022 19:27:27 +0000 Subject: [PATCH 006/270] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- vector/src/main/res/values-uk/strings.xml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/vector/src/main/res/values-uk/strings.xml b/vector/src/main/res/values-uk/strings.xml index 8300199e8a..706e18fc63 100644 --- a/vector/src/main/res/values-uk/strings.xml +++ b/vector/src/main/res/values-uk/strings.xml @@ -2293,15 +2293,15 @@ Це запрошення до простору надіслане %s, не пов\'язаній із вашим обліковим записом Це запрошення до кімнати надіслане %s, не пов\'язаній із вашим обліковим записом Зауважте, що поліпшення створить нову версію кімнати. Всі наявні повідомлення залишаться в цій архівованій кімнаті. - Будь-хто в батьківському просторі зможемо знайти кімнату й долучитись — нема потреба вручну запрошувати всіх. Можна змінити це в налаштуваннях кімнати будь-коли. - Будь-хто в %s зможе знайти кімнату й долучитись — нема потреби вручну запрошувати всіх. Можна змінити це в налаштуваннях кімнати будь-коли. + Будь-хто в батьківському просторі зможе знайти кімнату й приєднатись — непотрібно вручну запрошувати всіх. Це можна змінити в налаштуваннях кімнати будь-коли. + Будь-хто в %s зможе знайти кімнату й приєднатись — непотрібно вручну запрошувати всіх. Це можна змінити в налаштуваннях кімнати будь-коли. Не вдалося відповісти чи редагувати, бо голосове повідомлення активне Кімната — версії %s, яку домашній сервер позначив нестабільною. Поліпшення кімнати — серйозна операція. Її зазвичай радять, коли кімната нестабільна через вади, брак функціоналу чи вразливості безпеки. \nЗазвичай це впливає лише на деталі опрацювання кімнати сервером. Деяких кімнат може бути не видно, бо вони закриті й потребують запрошення. - Деяких кімнат може бути не видно, бо вони закриті й потребують запрошення. -\nУ вас нема дозволу додавати кімнати. + Деякі кімнати можуть бути приховані, оскільки вони приватні й потребують запрошення. +\nУ вас немає дозволу додавати кімнати. Ви єдиний адміністратор цього простору. Якщо вийдете, він залишиться без керівництва. Ви не зможете приєднатись, поки вас не запросять знову. Ви єдина особа тут. Якщо ви вийдете, більше ніхто не зможе приєднатись, навіть ви ж. @@ -2703,4 +2703,8 @@ %1$s і %2$s Електронна пошта не підтверджена, перевірте свою поштову скриньку + Неможливо завантажити карту +\nМожливо, цей домашній сервер не налаштовано для показу карт. + Відкрити налаштування + Усі бесіди \ No newline at end of file From 467d17ddf9693d8e798083cec00eb6ad09608243 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 10 Aug 2022 02:13:16 +0000 Subject: [PATCH 007/270] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- vector/src/main/res/values-zh-rTW/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-zh-rTW/strings.xml b/vector/src/main/res/values-zh-rTW/strings.xml index effb6e7410..f1f1d633e6 100644 --- a/vector/src/main/res/values-zh-rTW/strings.xml +++ b/vector/src/main/res/values-zh-rTW/strings.xml @@ -2553,4 +2553,8 @@ %1$s 與 %2$s 電子郵件未驗證,請檢查您的收件匣 + 無法載入地圖 +\n此家伺服器可能未設定好顯示地圖。 + 開啟設定 + 所有聊天 \ No newline at end of file From 2deeff389577d724f7d64d6de6c8774df6684d86 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Wed, 10 Aug 2022 11:52:14 +0000 Subject: [PATCH 008/270] Translated using Weblate (Slovak) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sk/ --- fastlane/metadata/android/sk/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/sk/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/sk/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/sk/changelogs/40104310.txt diff --git a/fastlane/metadata/android/sk/changelogs/40104300.txt b/fastlane/metadata/android/sk/changelogs/40104300.txt new file mode 100644 index 0000000000..dd0f554532 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Umožňuje vylepšené postupy prihlasovania a registrácie. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40104310.txt b/fastlane/metadata/android/sk/changelogs/40104310.txt new file mode 100644 index 0000000000..dd0f554532 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Umožňuje vylepšené postupy prihlasovania a registrácie. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases From 32375f30eb5ab03bd59b01770be9ca77db925d0d Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Tue, 9 Aug 2022 21:14:58 +0000 Subject: [PATCH 009/270] Translated using Weblate (Ukrainian) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/uk/ --- fastlane/metadata/android/uk/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/uk/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/uk/changelogs/40104310.txt diff --git a/fastlane/metadata/android/uk/changelogs/40104300.txt b/fastlane/metadata/android/uk/changelogs/40104300.txt new file mode 100644 index 0000000000..727508a0cc --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Поліпшені вхід і реєстрація. +Перелік усіх змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/uk/changelogs/40104310.txt b/fastlane/metadata/android/uk/changelogs/40104310.txt new file mode 100644 index 0000000000..727508a0cc --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Поліпшені вхід і реєстрація. +Перелік усіх змін: https://github.com/vector-im/element-android/releases From d94f09a3b1fd99d7ac3da2207830b930f7d8acf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 9 Aug 2022 16:27:13 +0000 Subject: [PATCH 010/270] Translated using Weblate (Estonian) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/et/ --- fastlane/metadata/android/et/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/et/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/et/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/et/changelogs/40104310.txt diff --git a/fastlane/metadata/android/et/changelogs/40104300.txt b/fastlane/metadata/android/et/changelogs/40104300.txt new file mode 100644 index 0000000000..e01c9b4329 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: senisest parem liitumise ja sisselogimise töövoog. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/et/changelogs/40104310.txt b/fastlane/metadata/android/et/changelogs/40104310.txt new file mode 100644 index 0000000000..e01c9b4329 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: senisest parem liitumise ja sisselogimise töövoog. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases From 9d0298273471e858fceec36f518f826c9a77fcc1 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Tue, 9 Aug 2022 15:33:41 +0000 Subject: [PATCH 011/270] Translated using Weblate (Persian) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fa/ --- fastlane/metadata/android/fa/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/fa/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/fa/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/fa/changelogs/40104310.txt diff --git a/fastlane/metadata/android/fa/changelogs/40104300.txt b/fastlane/metadata/android/fa/changelogs/40104300.txt new file mode 100644 index 0000000000..7a0e87b263 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104300.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: به کار انداختن ورود بهبود یافته و سفرهای ورود. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fa/changelogs/40104310.txt b/fastlane/metadata/android/fa/changelogs/40104310.txt new file mode 100644 index 0000000000..7a0e87b263 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104310.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: به کار انداختن ورود بهبود یافته و سفرهای ورود. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases From 9be766a1076b8919d42db17a5489637ddf2f072e Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 10 Aug 2022 02:12:29 +0000 Subject: [PATCH 012/270] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/zh_Hant/ --- fastlane/metadata/android/zh-TW/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/zh-TW/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40104310.txt diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104300.txt b/fastlane/metadata/android/zh-TW/changelogs/40104300.txt new file mode 100644 index 0000000000..3055389b2b --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104300.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:啟用改善的登入與註冊流程。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104310.txt b/fastlane/metadata/android/zh-TW/changelogs/40104310.txt new file mode 100644 index 0000000000..3055389b2b --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104310.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:啟用改善的登入與註冊流程。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases From 0083c2996802891a69f7bbe487304d9a0374f501 Mon Sep 17 00:00:00 2001 From: Linerly Date: Tue, 9 Aug 2022 17:31:21 +0000 Subject: [PATCH 013/270] Translated using Weblate (Indonesian) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/id/ --- fastlane/metadata/android/id/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/id/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/id/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/id/changelogs/40104310.txt diff --git a/fastlane/metadata/android/id/changelogs/40104300.txt b/fastlane/metadata/android/id/changelogs/40104300.txt new file mode 100644 index 0000000000..3d8d13e23d --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Mengaktifkan perjalanan masuk dan keluar yang diperbaiki. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40104310.txt b/fastlane/metadata/android/id/changelogs/40104310.txt new file mode 100644 index 0000000000..3d8d13e23d --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Mengaktifkan perjalanan masuk dan keluar yang diperbaiki. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases From d8115a79a4c57172db6757700472eda8ee72eede Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 12 Aug 2022 11:17:13 +0200 Subject: [PATCH 014/270] Adds persisted backstack --- .../im/vector/app/SpaceStateHandlerImpl.kt | 19 +++++++++++++++-- .../features/settings/VectorPreferences.kt | 21 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index c6a4b2c5f0..a8739bfd0f 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -23,6 +23,7 @@ import im.vector.app.core.utils.BehaviorDataSource import im.vector.app.features.analytics.AnalyticsTracker import im.vector.app.features.analytics.plan.UserProperties import im.vector.app.features.session.coroutineScope +import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.ui.UiStateRepository import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -52,7 +53,8 @@ class SpaceStateHandlerImpl @Inject constructor( private val sessionDataSource: ActiveSessionDataSource, private val uiStateRepository: UiStateRepository, private val activeSessionHolder: ActiveSessionHolder, - private val analyticsTracker: AnalyticsTracker + private val analyticsTracker: AnalyticsTracker, + private val vectorPreferences: VectorPreferences, ) : SpaceStateHandler { private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) @@ -82,7 +84,7 @@ class SpaceStateHandlerImpl @Inject constructor( } if (isForwardNavigation) { - spaceBackstack.addLast(currentSpace?.roomId) + addToBackstacks(spaceSummary) } if (persistNow) { @@ -104,6 +106,15 @@ class SpaceStateHandlerImpl @Inject constructor( } } + private fun addToBackstacks(space: RoomSummary?) { + val spaceId = space?.roomId ?: ROOT_SPACE_ID + spaceBackstack.addLast(spaceId) + + val currentPersistedBackstack = vectorPreferences.getPersistedSpaceBackstack().toMutableList() + currentPersistedBackstack.add(spaceId) + vectorPreferences.setPersistedSpaceBackstack(currentPersistedBackstack) + } + private fun observeActiveSession() { sessionDataSource.stream() .distinctUntilChanged() @@ -144,4 +155,8 @@ class SpaceStateHandlerImpl @Inject constructor( val session = activeSessionHolder.getSafeActiveSession() ?: return uiStateRepository.storeSelectedSpace(selectedSpaceDataSource.currentValue?.orNull()?.roomId, session.sessionId) } + + companion object { + private const val ROOT_SPACE_ID = "ROOT" + } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index ac14bfc3c7..0a99cffe47 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -25,6 +25,7 @@ import androidx.core.content.edit import com.squareup.seismic.ShakeDetector import im.vector.app.R import im.vector.app.core.di.DefaultSharedPreferences +import im.vector.app.core.extensions.join import im.vector.app.core.resources.BuildMeta import im.vector.app.core.time.Clock import im.vector.app.features.disclaimer.SHARED_PREF_KEY @@ -77,6 +78,7 @@ class VectorPreferences @Inject constructor( const val SETTINGS_ALLOW_INTEGRATIONS_KEY = "SETTINGS_ALLOW_INTEGRATIONS_KEY" const val SETTINGS_INTEGRATION_MANAGER_UI_URL_KEY = "SETTINGS_INTEGRATION_MANAGER_UI_URL_KEY" const val SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY = "SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY" + const val SETTINGS_PERSISTED_SPACE_BACKSTACK = "SETTINGS_PERSISTED_SPACE_BACKSTACK" const val SETTINGS_CRYPTOGRAPHY_HS_ADMIN_DISABLED_E2E_DEFAULT = "SETTINGS_CRYPTOGRAPHY_HS_ADMIN_DISABLED_E2E_DEFAULT" // const val SETTINGS_SECURE_BACKUP_RESET_PREFERENCE_KEY = "SETTINGS_SECURE_BACKUP_RESET_PREFERENCE_KEY" @@ -1113,6 +1115,25 @@ class VectorPreferences @Inject constructor( .apply() } + /** + * Sets the space backstack that is used for up navigation + * This needs to be persisted because navigating up through spaces should work across sessions + * + * Only the IDs of the spaces are stored + */ + fun setPersistedSpaceBackstack(spaceBackstack: List) { + val spaceIdsJoined = spaceBackstack.joinToString(",") + defaultPrefs.edit().putString(SETTINGS_PERSISTED_SPACE_BACKSTACK, spaceIdsJoined).apply() + } + + /** + * Gets the space backstack used for up navigation + */ + fun getPersistedSpaceBackstack(): List { + val spaceIdsJoined = defaultPrefs.getString(SETTINGS_PERSISTED_SPACE_BACKSTACK, null) + return spaceIdsJoined?.split(",").orEmpty() + } + fun showLiveSenderInfo(): Boolean { return defaultPrefs.getBoolean(SETTINGS_TIMELINE_SHOW_LIVE_SENDER_INFO, getDefault(R.bool.settings_timeline_show_live_sender_info_default)) } From 7ee58ccc88184daa88d70204bdb337711b452442 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 12 Aug 2022 13:18:26 +0200 Subject: [PATCH 015/270] Fixes back navigation --- .../im/vector/app/SpaceStateHandlerImpl.kt | 10 +++------- .../app/features/home/NewHomeDetailFragment.kt | 18 ++++++++++-------- .../app/features/settings/VectorPreferences.kt | 5 ++--- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index a8739bfd0f..800b3f9589 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -77,14 +77,14 @@ class SpaceStateHandlerImpl @Inject constructor( val activeSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return val currentSpace = selectedSpaceDataSource.currentValue?.orNull() val spaceSummary = spaceId?.let { activeSession.getRoomSummary(spaceId) } - val sameSpaceSelected = currentSpace != null && spaceId == currentSpace.roomId + val sameSpaceSelected = spaceId == currentSpace?.roomId if (sameSpaceSelected) { return } if (isForwardNavigation) { - addToBackstacks(spaceSummary) + addToBackstacks(currentSpace) } if (persistNow) { @@ -107,7 +107,7 @@ class SpaceStateHandlerImpl @Inject constructor( } private fun addToBackstacks(space: RoomSummary?) { - val spaceId = space?.roomId ?: ROOT_SPACE_ID + val spaceId = space?.roomId spaceBackstack.addLast(spaceId) val currentPersistedBackstack = vectorPreferences.getPersistedSpaceBackstack().toMutableList() @@ -155,8 +155,4 @@ class SpaceStateHandlerImpl @Inject constructor( val session = activeSessionHolder.getSafeActiveSession() ?: return uiStateRepository.storeSelectedSpace(selectedSpaceDataSource.currentValue?.orNull()?.roomId, session.sessionId) } - - companion object { - private const val ROOT_SPACE_ID = "ROOT" - } } diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 4766cd5006..16600abea5 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -178,14 +178,18 @@ class NewHomeDetailFragment @Inject constructor( } private fun navigateBack() { - val previousSpaceId = spaceStateHandler.getSpaceBackstack().removeLastOrNull() - val parentSpaceId = spaceStateHandler.getCurrentSpace()?.flattenParentIds?.lastOrNull() - setCurrentSpace(previousSpaceId ?: parentSpaceId) + val spaceBackstack = spaceStateHandler.getSpaceBackstack() + + try { + val previousSpaceId = spaceBackstack.removeLast() + setCurrentSpace(previousSpaceId) + } catch (e: NoSuchElementException) { + requireActivity().finish() + } } private fun setCurrentSpace(spaceId: String?) { spaceStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) - sharedActionViewModel.post(HomeActivitySharedAction.OnCloseSpace) } private fun handleCallStarted() { @@ -452,10 +456,8 @@ class NewHomeDetailFragment @Inject constructor( return this } - override fun onBackPressed(toolbarButton: Boolean) = if (spaceStateHandler.getCurrentSpace() != null) { + override fun onBackPressed(toolbarButton: Boolean): Boolean { navigateBack() - true - } else { - false + return true } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 0a99cffe47..6e2fdd1d6c 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -25,7 +25,6 @@ import androidx.core.content.edit import com.squareup.seismic.ShakeDetector import im.vector.app.R import im.vector.app.core.di.DefaultSharedPreferences -import im.vector.app.core.extensions.join import im.vector.app.core.resources.BuildMeta import im.vector.app.core.time.Clock import im.vector.app.features.disclaimer.SHARED_PREF_KEY @@ -1121,7 +1120,7 @@ class VectorPreferences @Inject constructor( * * Only the IDs of the spaces are stored */ - fun setPersistedSpaceBackstack(spaceBackstack: List) { + fun setPersistedSpaceBackstack(spaceBackstack: List) { val spaceIdsJoined = spaceBackstack.joinToString(",") defaultPrefs.edit().putString(SETTINGS_PERSISTED_SPACE_BACKSTACK, spaceIdsJoined).apply() } @@ -1129,7 +1128,7 @@ class VectorPreferences @Inject constructor( /** * Gets the space backstack used for up navigation */ - fun getPersistedSpaceBackstack(): List { + fun getPersistedSpaceBackstack(): List { val spaceIdsJoined = defaultPrefs.getString(SETTINGS_PERSISTED_SPACE_BACKSTACK, null) return spaceIdsJoined?.split(",").orEmpty() } From 5012f37e6f0453ee0dd6dee6aa1427757b1938b9 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Fri, 12 Aug 2022 13:28:01 +0200 Subject: [PATCH 016/270] Refactors space backstack handling --- vector/src/main/java/im/vector/app/SpaceStateHandler.kt | 6 +++--- .../src/main/java/im/vector/app/SpaceStateHandlerImpl.kt | 9 ++++++++- .../im/vector/app/features/home/HomeDetailFragment.kt | 2 +- .../im/vector/app/features/home/NewHomeDetailFragment.kt | 4 +--- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt index d9f002be37..dcd4eec230 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt @@ -51,11 +51,11 @@ interface SpaceStateHandler : DefaultLifecycleObserver { ) /** - * Gets the current backstack of spaces (via their id). + * Gets the Space ID of the space on top of the backstack * - * null may be an entry in the ArrayDeque to indicate the root space (All Chats) + * May return null to indicate the All Chats space */ - fun getSpaceBackstack(): ArrayDeque + fun popSpaceBackstack(): String? /** * Gets a flow of the selected space for clients to react immediately to space changes. diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index 800b3f9589..af050df995 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -138,7 +138,14 @@ class SpaceStateHandlerImpl @Inject constructor( }.launchIn(session.coroutineScope) } - override fun getSpaceBackstack() = spaceBackstack + override fun popSpaceBackstack(): String? { + val poppedSpaceId = spaceBackstack.removeLast() + vectorPreferences.getPersistedSpaceBackstack().toMutableList().apply { + removeLast() + vectorPreferences.setPersistedSpaceBackstack(this) + } + return poppedSpaceId + } override fun getSelectedSpaceFlow() = selectedSpaceFlow diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index d4c89c1bca..e4a572e2a0 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -183,7 +183,7 @@ class HomeDetailFragment @Inject constructor( } private fun navigateBack() { - val previousSpaceId = spaceStateHandler.getSpaceBackstack().removeLastOrNull() + val previousSpaceId = spaceStateHandler.popSpaceBackstack() val parentSpaceId = spaceStateHandler.getCurrentSpace()?.flattenParentIds?.lastOrNull() setCurrentSpace(previousSpaceId ?: parentSpaceId) } diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 16600abea5..09617a8dd8 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -178,10 +178,8 @@ class NewHomeDetailFragment @Inject constructor( } private fun navigateBack() { - val spaceBackstack = spaceStateHandler.getSpaceBackstack() - try { - val previousSpaceId = spaceBackstack.removeLast() + val previousSpaceId = spaceStateHandler.popSpaceBackstack() setCurrentSpace(previousSpaceId) } catch (e: NoSuchElementException) { requireActivity().finish() From 959a833c232635a0767d34749894121c39781d93 Mon Sep 17 00:00:00 2001 From: "Auri B. P" Date: Fri, 12 Aug 2022 18:54:26 +0000 Subject: [PATCH 017/270] Translated using Weblate (Catalan) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ca/ --- vector/src/main/res/values-ca/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-ca/strings.xml b/vector/src/main/res/values-ca/strings.xml index f7366b7dd3..8f811ba8b8 100644 --- a/vector/src/main/res/values-ca/strings.xml +++ b/vector/src/main/res/values-ca/strings.xml @@ -2603,4 +2603,8 @@ %1$s i %2$s Correu no verificat, mira la teva safata d\'entrada + No s\'ha pogut carregar el mapa +\nPotser el servidor utilitzat no està configurat per mostrar mapes. + Obre configuració + Tots els xats \ No newline at end of file From 17ac9f3b57f896b89711434be27c2f1838c63eb1 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Sat, 13 Aug 2022 07:30:23 +0000 Subject: [PATCH 018/270] Translated using Weblate (Hungarian) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/hu/ --- vector/src/main/res/values-hu/strings.xml | 36 +++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-hu/strings.xml b/vector/src/main/res/values-hu/strings.xml index 33c0044843..f5343fd948 100644 --- a/vector/src/main/res/values-hu/strings.xml +++ b/vector/src/main/res/values-hu/strings.xml @@ -1233,7 +1233,7 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze %d aktív munkamenet %d aktív munkamenet - Munkamenet ellenőrzése + Az eszköz ellenőrzése A titkosított üzenetekhez való hozzáféréshez nyiss meg egy létező munkamenetet és használd ennek a hitelesítésére. Ellenőriz Hitelesített @@ -1394,7 +1394,7 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze Meghívó elküldve neki: %1$s és még %2$d helyre Felhasználókat nem tudtuk meghívni. Ellenőrizd azokat a felhasználókat akiket meg szeretnél hívni és próbáld újra. - Üzenet törölve + Üzenet eltávolítva Helykitöltő mutatása a törölt szövegek helyett Megerősítő levelet küldtünk ide: %s, először ellenőrizd az e-mailedet és kattints a megerősítő hivatkozásra MÉDIA @@ -2575,4 +2575,36 @@ A Visszaállítási Kulcsot tartsd biztonságos helyen, mint pl. egy jelszókeze Itt lesznek tárolva a beszélgetéseid Mi a szervered címe\? Itt lesz tárolva az összes üzeneted Az email cím nem lett ellenőrizve, kérlek nézd meg a beérkező email-jeidet + Element Call kisalkalmazás kamera és mikrofon használatának automatikus engedélyezése + Element Call jogosultságok engedélyezése + + %d üzenet eltávolítva + %d üzenet eltávolítva + + Élő földrajzi helyzet + Tartózkodási hely megosztása + Az élő helymegosztáshoz ebben a szobában megfelelő jogosultságokra van szükséged. + Nincs jogosultságod az élő helymegosztáshoz + A térkép betöltése sikertelen +\nEz a matrix szerver nincs beállítva, hogy térképet mutasson. + Beállítások megnyitása + Ez a QR code nem tűnik jónak. Próbáld meg az ellenőrzést másik metódussal. + A régi titkosított üzenetekhez nem férsz majd hozzá. Állítsd be újra a Biztonságos Üzenet Mentést és ellenőrizd a kulcsokat az újrakezdéshez. + Ennek az eszköznek az ellenőrzése nem lehetséges + Ez a hivatkozás nem nyitható meg: a közösségeket felváltották a terek + Válassz jelszót + Új jelszó + Ellenőrizd az e-mailed. + %s ellenőrző hivatkozást fog küldeni + Adatok frissítése… + Rendszerbeállítás használata + Kézi beállítás + Automatikus beállítás + Válassz betűméretet + + %1$s és %2$d másik + %1$s és %2$d másik + + %1$s és %2$s + Minden beszélgetés \ No newline at end of file From 6b26e00dd87bb2089327d8670ae95dc948f7e132 Mon Sep 17 00:00:00 2001 From: Linerly Date: Fri, 12 Aug 2022 12:57:39 +0000 Subject: [PATCH 019/270] Translated using Weblate (Indonesian) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- vector/src/main/res/values-in/strings.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml index ff1fa24255..aba69da375 100644 --- a/vector/src/main/res/values-in/strings.xml +++ b/vector/src/main/res/values-in/strings.xml @@ -965,7 +965,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Perubahan siapa yang dapat membaca riwayat hanya akan berlaku untuk pesan berikutnya di ruangan ini. Visibilitas riwayat yang ada tidak akan berubah. Pengaturan akun Anda dapat mengelola notifikasi di %1$s. - Harap dicatat bahwa pemberitahuan sebutan & kata kunci tidak tersedia di ruangan terenkripsi di ponsel. + Harap dicatat bahwa pemberitahuan sebutan & kata kunci tidak tersedia dalam ruangan terenkripsi di ponsel. Beritahu saya untuk Putar suara rana Pilih @@ -1005,11 +1005,11 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Tidak ada sinkronisasi latar belakang ${app_name} akan disinkronkan di latar belakang secara berkala pada waktu yang tepat (dapat dikonfigurasi). \nIni akan memengaruhi penggunaan radio dan baterai, dan ada juga pemberitahuan yang ditampilkan permanen menyatakan bahwa ${app_name} sedang mendengarkan peristiwa. - Anda tidak akan mendapatkan notifikasi untuk sebutan & keyword di ruangan terenkripsi di ponsel. + Anda tidak akan mendapatkan notifikasi untuk sebutan & kata kunci dalam ruangan terenkripsi di ponsel. Peningkatan ruangan Pesan dari bot Undangan ruangan - Keyword + Kata kunci \@room Pesan grup terenkripsi Pesan grup @@ -1021,16 +1021,16 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Saat ruangan ditingkatkan Pesan terenkripsi di obrolan grup Pesan terenkripsi di chat satu-ke-satu - Keyword tidak boleh berisi \'%s\' - Keyword tidak boleh diawali dengan \'.\' - Tambahkan keyword baru - Keyword Anda + Kata kunci tidak boleh berisi \'%s\' + Kata kunci tidak boleh diawali dengan \'.\' + Tambahkan kata kunci baru + Kata kunci Anda Beritahu saya untuk Lainnya - Sebutan dan Keyword + Sebutan dan Kata Kunci Notifikasi Bawaan Tidak ada - Hanya sebutan & keyword + Hanya sebutan & kata kunci Mengakhiri panggilan… Tidak ada jawaban Pengguna yang Anda panggil sedang sibuk. @@ -1097,7 +1097,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. %1$s membuat ruangan publik untuk siapa pun yang mengetahui tautannya. Tekan lama pada sebuah ruangan untuk melihat lebih banyak pilihan Anda tidak mengabaikan pengguna apa pun - Ketik keyword untuk mencari reaksi. + Ketik kata kunci untuk mencari sebuah reaksi. Spoiler Mengirim pesan sebagai spoiler Anda tidak membuat perubahan From 557508c7b5c8e048b34e842508dea63cf1d0e44f Mon Sep 17 00:00:00 2001 From: random Date: Fri, 12 Aug 2022 10:03:33 +0000 Subject: [PATCH 020/270] Translated using Weblate (Italian) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- vector/src/main/res/values-it/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-it/strings.xml b/vector/src/main/res/values-it/strings.xml index 46bb5453a8..afa0831206 100644 --- a/vector/src/main/res/values-it/strings.xml +++ b/vector/src/main/res/values-it/strings.xml @@ -2594,4 +2594,8 @@ %1$s e %2$s Email non verificata, controlla la posta in arrivo + Impossibile caricare la mappa +\nQuesto homeserver potrebbe non essere configurato per mostrare mappe. + Apri le impostazioni + Tutte le chat \ No newline at end of file From 302c084701076f12ebb5cc355f0e12765af67253 Mon Sep 17 00:00:00 2001 From: lvre <7uu3qrbvm@relay.firefox.com> Date: Fri, 12 Aug 2022 17:03:06 +0000 Subject: [PATCH 021/270] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- vector/src/main/res/values-pt-rBR/strings.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml index 8e4e1942da..18a8e3d490 100644 --- a/vector/src/main/res/values-pt-rBR/strings.xml +++ b/vector/src/main/res/values-pt-rBR/strings.xml @@ -2576,7 +2576,7 @@ URL de servidor Qual é o endereço de seu servidor\? Isto é como uma casa para todos os seus dados Selecionar seu servidor - Boas-vindas de volta! + Boas vindas de volta! Editar Ou Onde suas conversas vão viver @@ -2603,4 +2603,8 @@ %1$s e %2$s Email não verificado, cheque sua inbox + Incapaz de carregar mapa +\nEste servidor casa pode não estar configurado para exibir mapas. + Abrir configurações + Todos os Chats \ No newline at end of file From 44cfa5dcb04029768f28c848807e7c3979302ef2 Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Fri, 12 Aug 2022 22:58:34 +0000 Subject: [PATCH 022/270] Translated using Weblate (Russian) Currently translated at 99.0% (2309 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- vector/src/main/res/values-ru/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml index 51e8a72ec7..f634025e86 100644 --- a/vector/src/main/res/values-ru/strings.xml +++ b/vector/src/main/res/values-ru/strings.xml @@ -55,7 +55,7 @@ Начальная синхронизация: \nИмпорт сообществ Начальная синхронизация: -\nИмпорт данных учетной записи +\nИмпорт данных учётной записи %s обновил эту комнату. Отправка сообщения… %1$s отозвал приглашение %2$s присоединиться к комнате @@ -194,7 +194,7 @@ %1$s, %2$s и %3$s 🎉 Всем серверам запрещено участвовать! Эта комната больше не может быть использована. Без изменений. - Пустая комната (был(а) %s) + Пустая комната (без %s) • Соответствующие серверы %s заблокированы. • Серверы, соответствующие буквальным IP-адресам, теперь запрещены. • Серверы, соответствующие буквальным IP-адресам, теперь разрешены. @@ -1455,7 +1455,7 @@ %d сессии активны %d сессий активно - Подтверждение этого устройства + Подтвердите это устройство Используйте существующую сессию для подтверждения этой, предоставив ей доступ к зашифрованным сообщениям. Инструменты для разработчиков Данные учётной записи @@ -2235,7 +2235,7 @@ Входящий видеовызов Входящий голосовой вызов Вы отклонили этот вызов - Настройки учетной записи + Настройки учётной записи Вы можете управлять уведомлениями в %1$s. Обратите внимание, что уведомления об упоминаниях и ключевых словах недоступны в зашифрованных комнатах на мобильных устройствах. Уведомлять меня о @@ -2449,7 +2449,7 @@ Команды Друзья и семья Мы поможем вам подключиться - С кем вы будете общаться больше всего\? + С кем вы будете общаться чаще всего\? Вы уже просматриваете это обсуждение! Просмотр в Комнате Обсудить @@ -2661,7 +2661,7 @@ URL-адрес сервера С возвращением! Или - Создать учётную запись + Создайте учётную запись %1$s и %2$s Открыть настройки Не удалось загрузить карту From b14aed43b8782d892a87a2d07dee10b18b33e73e Mon Sep 17 00:00:00 2001 From: lvre <7uu3qrbvm@relay.firefox.com> Date: Fri, 12 Aug 2022 17:04:47 +0000 Subject: [PATCH 023/270] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pt_BR/ --- fastlane/metadata/android/pt-BR/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/pt-BR/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/pt-BR/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/pt-BR/changelogs/40104310.txt diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104300.txt b/fastlane/metadata/android/pt-BR/changelogs/40104300.txt new file mode 100644 index 0000000000..5f1aaf4b3d --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Habilita as jornadas melhoradas de sign in e sign up. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104310.txt b/fastlane/metadata/android/pt-BR/changelogs/40104310.txt new file mode 100644 index 0000000000..5f1aaf4b3d --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Habilita as jornadas melhoradas de sign in e sign up. +Changelog completo: https://github.com/vector-im/element-android/releases From 9281f5564e9c13fd319e63256aa6c03f4fa41331 Mon Sep 17 00:00:00 2001 From: random Date: Fri, 12 Aug 2022 10:04:34 +0000 Subject: [PATCH 024/270] Translated using Weblate (Italian) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/it/ --- fastlane/metadata/android/it-IT/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/it-IT/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/40104310.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/40104300.txt b/fastlane/metadata/android/it-IT/changelogs/40104300.txt new file mode 100644 index 0000000000..40d9618137 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: introduce i percorsi migliorati di accesso e registrazione. +Cronologia completa: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/it-IT/changelogs/40104310.txt b/fastlane/metadata/android/it-IT/changelogs/40104310.txt new file mode 100644 index 0000000000..40d9618137 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: introduce i percorsi migliorati di accesso e registrazione. +Cronologia completa: https://github.com/vector-im/element-android/releases From b04d338f26ee2b10a186ec138a550f3dfd3bc54b Mon Sep 17 00:00:00 2001 From: Linerly Date: Fri, 12 Aug 2022 13:15:48 +0000 Subject: [PATCH 025/270] Translated using Weblate (Indonesian) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/id/ --- .../metadata/android/id/full_description.txt | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fastlane/metadata/android/id/full_description.txt b/fastlane/metadata/android/id/full_description.txt index d3bed0bf6b..20d805c582 100644 --- a/fastlane/metadata/android/id/full_description.txt +++ b/fastlane/metadata/android/id/full_description.txt @@ -1,42 +1,42 @@ -Element adalah perpesanan yang aman dan aplikasi kolaborasi tim produktivitas yang ideal untuk obrolan grup saat bekerja jarak jauh. Aplikasi perpesanan ini menggunakan enkripsi ujung-ke-ujung untuk memberikan konferensi video, pembagian file, dan panggilan suara yang aman. +Element adalah perpesanan yang aman dan aplikasi kolaborasi tim produktivitas yang ideal untuk obrolan grup saat bekerja jarak jauh. Aplikasi perpesanan ini menggunakan enkripsi ujung-ke-ujung untuk menyediakan konferensi video, pembagian berkas, dan panggilan suara yang aman. -Fitur Element termasuk -- Alat komunikasi online yang canggih +Fitur Element termasuk: +- Alat komunikasi daring yang canggih - Pesan-pesan yang dienkripsi sepenuhnya untuk memungkinkan komunikasi perusahaan yang lebih aman, bahkan untuk pekerja jarak jauh -- Obrolan terdesentralisasi berdasarkan kerangka Matrix yang sumber terbuka -- Pembagian file aman dengan data terenkripsi saat mengelola proyek +- Obrolan terdesentralisasi berdasarkan kerangka kerja Matrix yang sumber terbuka +- Pembagian berkas aman dengan data terenkripsi saat mengelola proyek - Obrolan video dengan VoIP dan pembagian layar -- Integrasi yang mudah dengan alat kolaborasi online favorit Anda, alat manajemen proyek, layanan VoIP dan aplikasi perpesanan tim lainnya +- Integrasi yang mudah dengan alat kolaborasi daring favorit Anda, alat pengelola proyek, layanan VoIP dan aplikasi perpesanan tim lainnya -Element benar-benar berbeda dari aplikasi perpesanan dan aplikasi kolaborasi lainnya. Element beroperasi pada Matrix, jaringan terbuka untuk pengiriman pesan yang aman dan komunikasi terdesentralisasi. +Element benar-benar berbeda dari aplikasi perpesanan dan aplikasi kolaborasi lainnya. Element beroperasi pada Matrix, jaringan terbuka untuk pengiriman pesan yang aman dan komunikasi yang terdesentralisasi. Perpesanan dengan privasi dan enkripsi -Element melindungi Anda dari iklan yang tidak diinginkan, penambangan data dan taman berdinding. Element juga mengamankan semua data Anda, komunikasi video dan suara satu-ke-satu dengan enkripsi ujung-ke-ujung dan verifikasi perangkat menggunakan penandatanganan silang. +Element melindungi Anda dari iklan yang tidak diinginkan, penambangan data, dan taman berdinding. Element juga mengamankan semua data Anda, komunikasi video dan suara satu-ke-satu dengan enkripsi ujung-ke-ujung, dan verifikasi perangkat menggunakan penandatanganan silang. -Element memberikan Anda kendali atas privasi Anda sambil memungkinkan Anda untuk berkomunikasi dengan siapa saja secara aman di jaringan Matrix, atau alat kolaborasi bisnis lainnya dengan mengintegrasikan aplikasi-aplikasi seperti Slack. +Element memberikan Anda kendali atas privasi Anda sambil memungkinkan Anda untuk berkomunikasi dengan siapa saja secara aman di jaringan Matrix, atau alat kolaborasi bisnis lainnya dengan mengintegrasikan aplikasi seperti Slack. -Element dapat dihost sendiri -Untuk memungkinkan lebih banyak kendali atas data dan pesan-pesan sensitif Anda, Element dapat dihost sendiri atau Anda dapat memilih host berbasis Matrix, standar untuk komunikasi terdesentralisasi sumber terbuka. Element memberi Anda privasi, kepatuhan keamanan, dan fleksibilitas integrasi. +Element dapat di-host sendiri +Untuk memungkinkan lebih banyak kendali atas data dan pesan-pesan sensitif Anda, Element dapat dilayani sendiri atau Anda dapat memilih layanan berbasis Matrix, standar untuk komunikasi terdesentralisasi sumber terbuka. Element memberikan Anda privasi, kepatuhan keamanan, dan fleksibilitas integrasi. Miliki data Anda Anda memutuskan di mana untuk menyimpan data dan pesan-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 +1. Dapatkan akun gratis pada server publik matrix.org yang dilayani oleh pengembang Matrix, atau memilih dari ribuan server publik yang dilayani oleh sukarelawan +2. Layani akun Anda sendiri dengan menjalankan server pada infrastruktur IT Anda sendiri 3. Daftar untuk akun di server khusus dengan berlangganan platform hosting Layanan Matrix Element Perpesanan dan kolaborasi terbuka -Anda dapat mengobrol dengan siapa saja di jaringan Matrix, jika mereka menggunakan Element, aplikasi Matrix lain atau bahkan menggunakan aplikasi perpesanan yang berbeda. +Anda dapat mengobrol dengan siapa saja di jaringan Matrix, jika mereka menggunakan Element, aplikasi Matrix lain, atau bahkan menggunakan aplikasi perpesanan yang berbeda. Sangat aman -Enkripsi ujung-ke-ujung yang nyata (hanya mereka yang dalam obrolan dapat mendekripsi pesan), dan verifikasi perangkat menggunakan penandatanganan silang. +Enkripsi ujung-ke-ujung yang nyata (hanya mereka yang di dalam obrolan dapat mendekripsikan pesan), dan verifikasi perangkat menggunakan penandatanganan silang. Komunikasi dan integrasi lengkap -Perpesanan, panggilan suara dan video, pembagian file, pembagian layar dan banyak integrasi bot dan widget. Buat ruangan dan komunitas, tetap terhubung dan selesaikan hal-hal penting. +Perpesanan, panggilan suara dan video, pembagian berkas, pembagian layar dan banyak integrasi bot dan widget. Buat ruangan dan komunitas, tetap terhubung, dan selesaikan hal-hal penting. Ambil di mana Anda tinggalkan -Tetap terhubung di mana Anda berada, dengan riwayat pesan yang disinkronkan di semua perangkat Anda dan web di https://app.element.io +Tetap terhubung di mana Anda berada, dengan riwayat pesan yang disinkronkan pada semua perangkat Anda dan pada web di https://app.element.io Sumber terbuka -Element Android adalah proyek sumber terbuka, dihost oleh GitHub. Silakan laporkan masalah yang Anda temukan, atau membuat kontribusi ke pengembangannya di https://github.com/vector-im/element-android +Element Android adalah proyek sumber terbuka, dilayani oleh GitHub. Silakan laporkan masalah yang Anda temukan, atau membuat kontribusi ke pengembangannya di https://github.com/vector-im/element-android From 894d4f700ea056327f49a8e92e6960bbaed259af Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Mon, 15 Aug 2022 20:41:29 +0200 Subject: [PATCH 026/270] Makes space bottom sheet header reflect backstack --- .../java/im/vector/app/SpaceStateHandler.kt | 2 + .../im/vector/app/SpaceStateHandlerImpl.kt | 41 ++++++++++++++----- .../features/settings/VectorPreferences.kt | 4 +- .../features/spaces/NewSpaceListHeaderItem.kt | 28 ++++++++++++- .../spaces/NewSpaceSummaryController.kt | 9 +++- .../app/features/spaces/SpaceListViewModel.kt | 7 +++- .../app/features/spaces/SpaceListViewState.kt | 1 + .../res/layout/item_new_space_list_header.xml | 1 + 8 files changed, 76 insertions(+), 17 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt index dcd4eec230..b8f90471e8 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt @@ -57,6 +57,8 @@ interface SpaceStateHandler : DefaultLifecycleObserver { */ fun popSpaceBackstack(): String? + fun getPersistedSpaceBackstack(): List + /** * Gets a flow of the selected space for clients to react immediately to space changes. */ diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index af050df995..53e2ebd1b5 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -75,26 +75,28 @@ class SpaceStateHandlerImpl @Inject constructor( isForwardNavigation: Boolean, ) { val activeSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return - val currentSpace = selectedSpaceDataSource.currentValue?.orNull() - val spaceSummary = spaceId?.let { activeSession.getRoomSummary(spaceId) } - val sameSpaceSelected = spaceId == currentSpace?.roomId + val spaceToLeave = selectedSpaceDataSource.currentValue?.orNull() + val spaceToSet = spaceId?.let { activeSession.getRoomSummary(spaceId) } + val sameSpaceSelected = spaceId == spaceToLeave?.roomId if (sameSpaceSelected) { return } if (isForwardNavigation) { - addToBackstacks(currentSpace) + addToBackstacks(spaceToLeave, spaceToSet) + } else { + popBackstackUntil(spaceToSet) } if (persistNow) { - uiStateRepository.storeSelectedSpace(spaceSummary?.roomId, activeSession.sessionId) + uiStateRepository.storeSelectedSpace(spaceToSet?.roomId, activeSession.sessionId) } - if (spaceSummary == null) { + if (spaceToSet == null) { selectedSpaceDataSource.post(Option.empty()) } else { - selectedSpaceDataSource.post(Option.just(spaceSummary)) + selectedSpaceDataSource.post(Option.just(spaceToSet)) } if (spaceId != null) { @@ -106,12 +108,29 @@ class SpaceStateHandlerImpl @Inject constructor( } } - private fun addToBackstacks(space: RoomSummary?) { + private fun addToBackstacks(spaceToLeave: RoomSummary?, spaceToSet: RoomSummary?) { + spaceBackstack.addLast(spaceToLeave?.roomId) + + // Only add to the persisted backstack if the space to set is not All Chats, else reset the persisted stack + if (spaceToSet != null && spaceToLeave != null) { + val currentPersistedBackstack = vectorPreferences.getPersistedSpaceBackstack().toMutableList() + currentPersistedBackstack.add(spaceToLeave.roomId) + vectorPreferences.setPersistedSpaceBackstack(currentPersistedBackstack) + } else if (spaceToSet == null) { + vectorPreferences.setPersistedSpaceBackstack(emptyList()) + } + } + + private fun popBackstackUntil(space: RoomSummary?) { val spaceId = space?.roomId - spaceBackstack.addLast(spaceId) + while (spaceBackstack.last() != spaceId) { + spaceBackstack.removeLast() + } val currentPersistedBackstack = vectorPreferences.getPersistedSpaceBackstack().toMutableList() - currentPersistedBackstack.add(spaceId) + while (currentPersistedBackstack.last() != spaceId) { + currentPersistedBackstack.removeLast() + } vectorPreferences.setPersistedSpaceBackstack(currentPersistedBackstack) } @@ -147,6 +166,8 @@ class SpaceStateHandlerImpl @Inject constructor( return poppedSpaceId } + override fun getPersistedSpaceBackstack() = vectorPreferences.getPersistedSpaceBackstack() + override fun getSelectedSpaceFlow() = selectedSpaceFlow override fun getSafeActiveSpaceId(): String? { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 6e2fdd1d6c..cb571da9d3 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -1121,7 +1121,7 @@ class VectorPreferences @Inject constructor( * Only the IDs of the spaces are stored */ fun setPersistedSpaceBackstack(spaceBackstack: List) { - val spaceIdsJoined = spaceBackstack.joinToString(",") + val spaceIdsJoined = spaceBackstack.takeIf { it.isNotEmpty() }?.joinToString(",") defaultPrefs.edit().putString(SETTINGS_PERSISTED_SPACE_BACKSTACK, spaceIdsJoined).apply() } @@ -1130,7 +1130,7 @@ class VectorPreferences @Inject constructor( */ fun getPersistedSpaceBackstack(): List { val spaceIdsJoined = defaultPrefs.getString(SETTINGS_PERSISTED_SPACE_BACKSTACK, null) - return spaceIdsJoined?.split(",").orEmpty() + return spaceIdsJoined?.takeIf { it.isNotEmpty() }?.split(",").orEmpty() } fun showLiveSenderInfo(): Boolean { diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt index 8fc53f07d4..647b31084e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt @@ -16,6 +16,9 @@ package im.vector.app.features.spaces +import android.content.Context +import android.widget.TextView +import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder @@ -23,5 +26,28 @@ import im.vector.app.core.epoxy.VectorEpoxyModel @EpoxyModelClass abstract class NewSpaceListHeaderItem : VectorEpoxyModel(R.layout.item_new_space_list_header) { - class Holder : VectorEpoxyHolder() + + @EpoxyAttribute var currentSpace: String? = null + @EpoxyAttribute var spaceHistory: List> = emptyList() + + override fun bind(holder: Holder) { + super.bind(holder) + holder.spaceHeader.text = buildSpaceHeaderText(holder.spaceHeader.context) + } + + private fun buildSpaceHeaderText(context: Context): String { + val allChats = context.getString(R.string.all_chats) + var spaceHeaderText = allChats + if (spaceHistory.isNotEmpty()) { + spaceHeaderText += " > ${spaceHistory.joinToString(" > ") { it.second }}" + } + if (currentSpace != null) { + spaceHeaderText += " > $currentSpace" + } + return spaceHeaderText + } + + class Holder : VectorEpoxyHolder() { + val spaceHeader by bind(R.id.space_header) + } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt index 7c4435bf59..47b0f23f44 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceSummaryController.kt @@ -50,7 +50,8 @@ class NewSpaceSummaryController @Inject constructor( nonNullViewState.spaces, nonNullViewState.selectedSpace, nonNullViewState.rootSpacesOrdered, - nonNullViewState.homeAggregateCount + nonNullViewState.homeAggregateCount, + nonNullViewState.spaceHistory, ) } @@ -58,11 +59,15 @@ class NewSpaceSummaryController @Inject constructor( spaceSummaries: List?, selectedSpace: RoomSummary?, rootSpaces: List?, - homeCount: RoomAggregateNotificationCount + homeCount: RoomAggregateNotificationCount, + spaceHistory: List>, ) { val host = this + newSpaceListHeaderItem { id("space_list_header") + currentSpace(selectedSpace?.displayName) + spaceHistory(spaceHistory) } if (selectedSpace != null) { diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt index 9048026771..fdec36add0 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt @@ -65,7 +65,7 @@ class SpaceListViewModel @AssistedInject constructor( private val session: Session, private val vectorPreferences: VectorPreferences, private val autoAcceptInvites: AutoAcceptInvites, - private val analyticsTracker: AnalyticsTracker + private val analyticsTracker: AnalyticsTracker, ) : VectorViewModel(initialState) { @AssistedFactory @@ -85,11 +85,14 @@ class SpaceListViewModel @AssistedInject constructor( } observeSpaceSummaries() + val spaceHistory = spaceStateHandler.getPersistedSpaceBackstack() + .map { it to it?.let { session.roomService().getRoomSummary(it)?.displayName }.orEmpty() } spaceStateHandler.getSelectedSpaceFlow() .distinctUntilChanged() .setOnEach { selectedSpaceOption -> copy( - selectedSpace = selectedSpaceOption.orNull() + selectedSpace = selectedSpaceOption.orNull(), + spaceHistory = spaceHistory, ) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt index f75c336b5d..ebdc9e72ac 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewState.kt @@ -32,5 +32,6 @@ data class SpaceListViewState( val spaceOrderInfo: Map? = null, val spaceOrderLocalEchos: Map? = null, val expandedStates: Map = emptyMap(), + val spaceHistory: List> = emptyList(), // List of space id to display name val homeAggregateCount: RoomAggregateNotificationCount = RoomAggregateNotificationCount(0, 0) ) : MavericksState diff --git a/vector/src/main/res/layout/item_new_space_list_header.xml b/vector/src/main/res/layout/item_new_space_list_header.xml index 2c52304249..bb05f4cb53 100644 --- a/vector/src/main/res/layout/item_new_space_list_header.xml +++ b/vector/src/main/res/layout/item_new_space_list_header.xml @@ -1,6 +1,7 @@ Date: Mon, 15 Aug 2022 07:10:22 +0000 Subject: [PATCH 027/270] Translated using Weblate (Czech) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- vector/src/main/res/values-cs/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-cs/strings.xml b/vector/src/main/res/values-cs/strings.xml index 5733fde468..68c8362878 100644 --- a/vector/src/main/res/values-cs/strings.xml +++ b/vector/src/main/res/values-cs/strings.xml @@ -2653,4 +2653,8 @@ %1$s a %2$s E-mail nebyl ověřen, zkontrolujte si schránku + Nelze načíst mapu +\nTento domovský server nemusí být nakonfigurován pro zobrazování map. + Otevřít nastavení + Všechny konverzace \ No newline at end of file From d9e440e7eef7bbea74bfe91c8d47286e52709ac0 Mon Sep 17 00:00:00 2001 From: phardyle Date: Tue, 16 Aug 2022 04:47:42 +0000 Subject: [PATCH 028/270] Translated using Weblate (Chinese (Simplified)) Currently translated at 99.8% (2327 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/ --- vector/src/main/res/values-zh-rCN/strings.xml | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml index 0549bd84a9..b8b2b5856f 100644 --- a/vector/src/main/res/values-zh-rCN/strings.xml +++ b/vector/src/main/res/values-zh-rCN/strings.xml @@ -81,8 +81,8 @@ %1$s 为此房间移除了主要地址。 %1$s 已允许访客加入房间。 %1$s 已禁止访客加入房间。 - %1$s 已开启端对端加密。 - %1$s 已开启端对端加密(无法识别的演算法 %2$s)。 + %1$s已开启端到端加密。 + %1$s已开启端到端加密(无法识别的算法%2$s)。 %1$s 创建了这个房间 你的邀请 你创建了这个房间 @@ -152,8 +152,8 @@ 你移除了此房间的主要地址。 你已允许访客加入房间。 你已禁止访客加入房间。 - 你已开启端对端加密。 - 你已开启端对端加密(无法识别的算法 %1$s)。 + 你已开启端到端加密。 + 你已开启端到端加密(无法识别的算法%1$s)。 你已离开。理由:%1$s %1$s 已离开。理由:%2$s 你已加入。理由:%1$s @@ -312,13 +312,13 @@ 高级 此房间的内部 ID 这些是实验性功能,可能会出现不可预料的错误。请谨慎使用。 - 导出端对端房间密钥 + 导出端到端房间密钥 导出房间密钥 导出密钥到本地文件 导出 输入密语 确认密语 - 导入端对端房间密钥 + 导入端到端房间密钥 导入房间密钥 从本地文件导入密钥 仅向已验证的会话发送加密消息 @@ -666,9 +666,9 @@ 密语太弱了 如果你想要 ${app_name} 生成一个恢复密钥,请删除密语。 永不丢失已加密消息 - 加密房间中的信息会被端对端加密以确保安全。只有你和拥有密钥的接收方可以读取这些信息。 + 加密房间中的消息是端到端加密的,以确保安全。只有你和接收者拥有密钥读取这些消息。 \n -\n安全地备份你的密钥以免丢失信息。 +\n安全地备份你的密钥以免丢失消息。 开始使用备份密钥 (高级) 手动导出密钥 @@ -967,7 +967,7 @@ 建议发送失败 (%s) 在时间线上显示隐藏事件 私聊消息 - 正在等待… + 正在等待…… 正在加密缩略图… 正在发送缩略图 (%1$s / %2$s) 正在加密文件… @@ -1117,7 +1117,7 @@ 电子邮件 新密码 注意! - 更改你的密码将重置所有会话上的端对端加密密钥,从而使加密聊天记录无法读取。在重设密码之前,请设置“密钥备份”或从另一个会话中导出房间密钥。 + 更改你的密码将重置所有会话上的端到端加密密钥,从而使加密聊天记录无法读取。在重设密码之前,请设置“密钥备份”或从另一个会话中导出房间密钥。 继续 电子邮件未链接到任何账户 检查你的收件箱 @@ -1239,7 +1239,7 @@ 音频 文件 贴纸 - 正在等待… + 正在等待…… %s 已取消 你已取消 %s 已接受 @@ -1254,9 +1254,9 @@ 通过比较表情符号验证 验证 %s 已验证 %s - 正在等待 %s… - 此房间的消息未经端对端加密。 - 该房间的消息已被端对端加密。 + 正在等待%s…… + 此房间的消息未经端到端加密。 + 该房间的消息已端到端加密。 \n \n你的消息受加密保护,并且只有你和消息接收者拥有唯一解密密钥。 安全 @@ -1289,7 +1289,7 @@ 和彩虹一样给给定的表情上色后发送 时间线 消息编辑器 - 启用端对端加密… + 启用端到端加密…… 是否启用加密? 房间加密一经启用,便无法禁用。在加密房间中,发送的消息无法被服务器看到,只能被房间的参与者看到。启用加密可能会使许多机器人和桥接无法正常运作。 启用加密 @@ -1297,7 +1297,7 @@ 为保证安全,请当面验证,或者使用其他通讯方式验证。 比较独特表情,确保它们以相同顺序出现。 与其他用户设备上显示的代码比较。 - 与此用户的消息端对端加密,无法被第三方读取。 + 与此用户的消息是端到端加密的,无法被第三方读取。 你的新会话已验证。它可以访问你的加密消息,其他用户会将其视为可信任。 交叉签名 交叉签名已启用 @@ -1308,7 +1308,7 @@ 交叉签名已启用。 \n密钥未信任 交叉签名未启用 - 你的服务器管理员已默认禁用私有房间和私聊消息端对端加密。 + 你的服务器管理员已默认禁用私有房间和私聊消息端到端加密。 活跃的会话 显示全部会话 管理会话 @@ -1344,7 +1344,7 @@ 使用恢复密语或密钥 如果你无法访问已有会话 无法在存储中找到秘密 - 移除… + 移除…… 你想要发送此附件到 %1$s 吗? 发送原始尺寸图片 @@ -1409,7 +1409,7 @@ \n \n你也可以通过设置菜单来建立保护备份以及管理你的密钥。 加密已开启 - 本房间信息已经端对端加密。验证成员时,请查看其个人档案以了解更多信息。 + 本房间信息已经端到端加密。验证成员时,请查看其个人档案以了解更多信息。 加密未开启 不支持本房间使用的加密方式 %s 创建并配置了房间。 @@ -1632,13 +1632,13 @@ 忘记或丢失了所有的恢复选项?重置一切 你已加入。 %s 已加入。 - 此聊天的消息是端对端加密的。 + 此聊天的消息是端到端加密的。 离开 设置 - 此处的消息已被端对端加密。 + 此处的消息已端到端加密。 \n \n你的消息受加密保护,并且只有你和消息接收者拥有唯一解密密钥。 - 此处的消息未经端对端加密。 + 此处的消息未经端到端加密。 此主服务器正在运行较旧版本。要求你的主服务器管理员升级。你可以继续,但一些功能可能无法正确工作。 你仅发出此邀请。 %1$s 仅发出此邀请。 @@ -1819,7 +1819,7 @@ 初始化同步: \n正在下载数据… 初始化同步: -\n正在等待服务器响应… +\n正在等待服务器响应…… 空房间(曾为 %s) %1$s,%2$s,%3$s 和 %4$d 位其他成员 @@ -1970,7 +1970,7 @@ 提供反馈 反馈发送失败(%s) 感谢,你的反馈已成功送达 - 如果你后续有任何问题,欢迎联系我 + 如果你有任何后续问题,可以联系我 你正在使用空间的测试版。你的反馈将有助于改善下一版本。我们将会记录你的平台和用户名以帮助我们尽我们所能多发挥你的反馈的作用。 反馈 空间反馈 @@ -2456,7 +2456,7 @@ 主服务器不接收仅有数字的用户名。 发送你的第一条消息邀请%s聊天 加密配置错误 - 此聊天中的消息会被端对端加密。 + 此聊天中的消息会端到端加密。 还原加密 请联系管理员将加密还原到有效状态。 加密被错误地配置了。 From 1f7196b8d56218ea25bbb7a92febdeb0985b0c60 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 15 Aug 2022 07:11:34 +0000 Subject: [PATCH 029/270] Translated using Weblate (Czech) Currently translated at 100.0% (73 of 73 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/cs/ --- fastlane/metadata/android/cs-CZ/changelogs/40104300.txt | 2 ++ fastlane/metadata/android/cs-CZ/changelogs/40104310.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40104300.txt create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40104310.txt diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104300.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104300.txt new file mode 100644 index 0000000000..e74d892209 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104300.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Umožňuje vylepšené přihlašování a registraci. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104310.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104310.txt new file mode 100644 index 0000000000..e74d892209 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104310.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Umožňuje vylepšené přihlašování a registraci. +Úplný seznam změn: https://github.com/vector-im/element-android/releases From 06baae04edaef7589b58500c88e6c9444ee3b91b Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 16 Aug 2022 10:59:32 +0200 Subject: [PATCH 030/270] Adds working back navigation --- .../im/vector/app/SpaceStateHandlerImpl.kt | 17 +------------- .../features/home/NewHomeDetailFragment.kt | 23 +++++-------------- 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index 53e2ebd1b5..6c70c3266a 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -85,8 +85,6 @@ class SpaceStateHandlerImpl @Inject constructor( if (isForwardNavigation) { addToBackstacks(spaceToLeave, spaceToSet) - } else { - popBackstackUntil(spaceToSet) } if (persistNow) { @@ -121,19 +119,6 @@ class SpaceStateHandlerImpl @Inject constructor( } } - private fun popBackstackUntil(space: RoomSummary?) { - val spaceId = space?.roomId - while (spaceBackstack.last() != spaceId) { - spaceBackstack.removeLast() - } - - val currentPersistedBackstack = vectorPreferences.getPersistedSpaceBackstack().toMutableList() - while (currentPersistedBackstack.last() != spaceId) { - currentPersistedBackstack.removeLast() - } - vectorPreferences.setPersistedSpaceBackstack(currentPersistedBackstack) - } - private fun observeActiveSession() { sessionDataSource.stream() .distinctUntilChanged() @@ -160,7 +145,7 @@ class SpaceStateHandlerImpl @Inject constructor( override fun popSpaceBackstack(): String? { val poppedSpaceId = spaceBackstack.removeLast() vectorPreferences.getPersistedSpaceBackstack().toMutableList().apply { - removeLast() + removeLastOrNull() vectorPreferences.setPersistedSpaceBackstack(this) } return poppedSpaceId diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 09617a8dd8..4e429c4bf9 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -79,7 +79,6 @@ class NewHomeDetailFragment @Inject constructor( private val viewModel: HomeDetailViewModel by fragmentViewModel() private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel() - private val unreadMessagesSharedViewModel: UnreadMessagesSharedViewModel by activityViewModel() private val serverBackupStatusViewModel: ServerBackupStatusViewModel by activityViewModel() private lateinit var sharedActionViewModel: HomeSharedActionViewModel @@ -177,19 +176,6 @@ class NewHomeDetailFragment @Inject constructor( } } - private fun navigateBack() { - try { - val previousSpaceId = spaceStateHandler.popSpaceBackstack() - setCurrentSpace(previousSpaceId) - } catch (e: NoSuchElementException) { - requireActivity().finish() - } - } - - private fun setCurrentSpace(spaceId: String?) { - spaceStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) - } - private fun handleCallStarted() { dismissLoadingDialog() val fragmentTag = HomeTab.DialPad.toFragmentTag() @@ -454,8 +440,11 @@ class NewHomeDetailFragment @Inject constructor( return this } - override fun onBackPressed(toolbarButton: Boolean): Boolean { - navigateBack() - return true + override fun onBackPressed(toolbarButton: Boolean) = try { + val lastSpace = spaceStateHandler.popSpaceBackstack() + spaceStateHandler.setCurrentSpace(lastSpace, isForwardNavigation = false) + true + } catch (e: NoSuchElementException) { + false } } From fc301c8a2e956c63d3e3b4c84b53fa50d8d42fdc Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Tue, 16 Aug 2022 11:50:15 +0200 Subject: [PATCH 031/270] Unifies back and persisted navigation --- .../im/vector/app/SpaceStateHandlerImpl.kt | 18 +++++++----------- .../features/spaces/NewSpaceListHeaderItem.kt | 7 +++++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index 6c70c3266a..c36b6de17b 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -60,7 +60,6 @@ class SpaceStateHandlerImpl @Inject constructor( private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) private val selectedSpaceFlow = selectedSpaceDataSource.stream() - private val spaceBackstack = ArrayDeque() override fun getCurrentSpace(): RoomSummary? { return selectedSpaceDataSource.currentValue?.orNull()?.let { spaceSummary -> @@ -84,7 +83,7 @@ class SpaceStateHandlerImpl @Inject constructor( } if (isForwardNavigation) { - addToBackstacks(spaceToLeave, spaceToSet) + addToBackstack(spaceToLeave, spaceToSet) } if (persistNow) { @@ -106,15 +105,13 @@ class SpaceStateHandlerImpl @Inject constructor( } } - private fun addToBackstacks(spaceToLeave: RoomSummary?, spaceToSet: RoomSummary?) { - spaceBackstack.addLast(spaceToLeave?.roomId) - + private fun addToBackstack(spaceToLeave: RoomSummary?, spaceToSet: RoomSummary?) { // Only add to the persisted backstack if the space to set is not All Chats, else reset the persisted stack - if (spaceToSet != null && spaceToLeave != null) { + if (spaceToSet != null) { val currentPersistedBackstack = vectorPreferences.getPersistedSpaceBackstack().toMutableList() - currentPersistedBackstack.add(spaceToLeave.roomId) + currentPersistedBackstack.add(spaceToLeave?.roomId) vectorPreferences.setPersistedSpaceBackstack(currentPersistedBackstack) - } else if (spaceToSet == null) { + } else { vectorPreferences.setPersistedSpaceBackstack(emptyList()) } } @@ -143,12 +140,11 @@ class SpaceStateHandlerImpl @Inject constructor( } override fun popSpaceBackstack(): String? { - val poppedSpaceId = spaceBackstack.removeLast() vectorPreferences.getPersistedSpaceBackstack().toMutableList().apply { - removeLastOrNull() + val poppedSpaceId = removeLast() vectorPreferences.setPersistedSpaceBackstack(this) + return poppedSpaceId } - return poppedSpaceId } override fun getPersistedSpaceBackstack() = vectorPreferences.getPersistedSpaceBackstack() diff --git a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt index 647b31084e..29538be16e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/NewSpaceListHeaderItem.kt @@ -38,8 +38,11 @@ abstract class NewSpaceListHeaderItem : VectorEpoxyModel ") { it.second }}" + + val nonRootSpaceHistory = spaceHistory.filter { it.second.isNotEmpty() } + + if (nonRootSpaceHistory.isNotEmpty()) { + spaceHeaderText += " > ${nonRootSpaceHistory.joinToString(" > ") { it.second }}" } if (currentSpace != null) { spaceHeaderText += " > $currentSpace" From d42b72c8bf207ddd5dfd0a4a32eb31c2c8158d45 Mon Sep 17 00:00:00 2001 From: phardyle Date: Tue, 16 Aug 2022 10:02:24 +0000 Subject: [PATCH 032/270] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/ --- vector/src/main/res/values-zh-rCN/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml index b8b2b5856f..c52edec4bd 100644 --- a/vector/src/main/res/values-zh-rCN/strings.xml +++ b/vector/src/main/res/values-zh-rCN/strings.xml @@ -2553,4 +2553,8 @@ 你的对话发生的地方 %1$s和%2$s 电子邮件未确认,检查你的收件箱 + 无法加载地图 +\n此主服务器可能没有设置好显示地图。 + 打开设置 + 全部聊天 \ No newline at end of file From a56a7adb46d831b53df9c695b0a3e769623b54fd Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 15 Aug 2022 16:36:53 +0100 Subject: [PATCH 033/270] including the worker failure message in the logs and including throwable class name --- .../MultipleEventSendingDispatcherWorker.kt | 4 ++-- .../worker/SessionSafeCoroutineWorker.kt | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt index 2afca6e554..801ff0ec79 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt @@ -53,7 +53,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo @Inject lateinit var timelineSendEventWorkCommon: TimelineSendEventWorkCommon @Inject lateinit var localEchoRepository: LocalEchoRepository - override fun doOnError(params: Params): Result { + override fun doOnError(params: Params, failureMessage: String): Result { params.localEchoIds.forEach { localEchoIds -> localEchoRepository.updateSendState( eventId = localEchoIds.eventId, @@ -63,7 +63,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo ) } - return super.doOnError(params) + return super.doOnError(params, failureMessage) } override fun injectWith(injector: SessionComponent) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt index 030f51428b..b98b61c9f0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionSafeCoroutineWorker.kt @@ -55,14 +55,16 @@ internal abstract class SessionSafeCoroutineWorker( // Make sure to inject before handling error as you may need some dependencies to process them. injectWith(sessionComponent) - if (params.lastFailureMessage != null) { - // Forward error to the next workers - doOnError(params) - } else { - doSafeWork(params) + + when (val lastFailureMessage = params.lastFailureMessage) { + null -> doSafeWork(params) + else -> { + // Forward error to the next workers + doOnError(params, lastFailureMessage) + } } } catch (throwable: Throwable) { - buildErrorResult(params, throwable.localizedMessage ?: "error") + buildErrorResult(params, "${throwable::class.java.name}: ${throwable.localizedMessage ?: "N/A error message"}") } } @@ -89,10 +91,10 @@ internal abstract class SessionSafeCoroutineWorker( * This is called when the input parameters are correct, but contain an error from the previous worker. */ @CallSuper - open fun doOnError(params: PARAM): Result { + open fun doOnError(params: PARAM, failureMessage: String): Result { // Forward the error return Result.success(inputData) - .also { Timber.e("Work cancelled due to input error from parent") } + .also { Timber.e("Work cancelled due to input error from parent: $failureMessage") } } companion object { From 1fd1a4e82436f502b33bda2d3be8f642898689ce Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 17 Aug 2022 15:22:28 +0100 Subject: [PATCH 034/270] fixing SyncWorker becoming stuck in failure state on uncaught exception - the sync worker makes use of the CoroutineWorker which does not stop when the work completes, this means we often append to the existing worker. When appending by default the previous worker result payload is merged with (or in our case overwrites) the input data instead, meaning any failure state is set and kept until the worker stops, which in turns causes the sync worker to never sync - the fix is to make use of an input merge that always favour the request input data instead of the previous worker results --- .../matrix/android/sdk/internal/session/sync/job/SyncWorker.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt index 0cc7944d58..a04bc74628 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt @@ -30,6 +30,7 @@ import org.matrix.android.sdk.internal.session.sync.SyncTask import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.SessionWorkerParams import org.matrix.android.sdk.internal.worker.WorkerParamsFactory +import org.matrix.android.sdk.internal.worker.startChain import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -136,6 +137,7 @@ internal class SyncWorker(context: Context, workerParameters: WorkerParameters, .setConstraints(WorkManagerProvider.workConstraints) .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) .setInputData(data) + .startChain(true) .build() workManagerProvider.workManager .enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest) From a3a76d1c351c24c7fa2663d879236532e285d996 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 17 Aug 2022 15:24:05 +0100 Subject: [PATCH 035/270] adding changelog entry --- changelog.d/6836.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6836.bugfix diff --git a/changelog.d/6836.bugfix b/changelog.d/6836.bugfix new file mode 100644 index 0000000000..6fbcc35001 --- /dev/null +++ b/changelog.d/6836.bugfix @@ -0,0 +1 @@ +Fixes uncaught exceptions in the SyncWorker to cause the worker to become stuck in the failure state From 9c47c82da4b3ee75df05e6d5437487bbb8a4d683 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 17 Aug 2022 22:23:39 +0200 Subject: [PATCH 036/270] Adds click action to toolbar to open space settings --- .../im/vector/app/features/home/NewHomeDetailFragment.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 839ae6da88..74b7dcce51 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -297,11 +297,20 @@ class NewHomeDetailFragment @Inject constructor( } } + views.collapsingToolbar.debouncedClicks(::openSpaceSettings) + views.toolbar.debouncedClicks(::openSpaceSettings) + views.avatar.debouncedClicks { navigator.openSettings(requireContext()) } } + private fun openSpaceSettings() = withState(viewModel) { viewState -> + viewState.selectedSpace?.let { + sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(it.roomId)) + } + } + private fun setupBottomNavigationView() { views.bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible = vectorPreferences.labAddNotificationTab() views.bottomNavigationView.setOnItemSelectedListener { From 003a254c17d4578a1ba624a4b44a597fc851e969 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 17 Aug 2022 22:31:18 +0200 Subject: [PATCH 037/270] Adds changelog file --- changelog.d/6859.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6859.wip diff --git a/changelog.d/6859.wip b/changelog.d/6859.wip new file mode 100644 index 0000000000..02fc3616cd --- /dev/null +++ b/changelog.d/6859.wip @@ -0,0 +1 @@ +[New Layout] Adds space settings accessible through clicking the toolbar From a59011ffd241a0c08f37a72f03ee15297f54f752 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Wed, 17 Aug 2022 23:33:31 +0200 Subject: [PATCH 038/270] Adds debug button to new app layout --- .../app/features/home/NewHomeDetailFragment.kt | 16 ++++++++++++++++ .../main/res/layout/fragment_new_home_detail.xml | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 4e429c4bf9..1acbeccc28 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -22,6 +22,7 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup +import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.activityViewModel @@ -36,6 +37,7 @@ import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorMenuProvider +import im.vector.app.core.resources.BuildMeta import im.vector.app.core.resources.ColorProvider import im.vector.app.core.ui.views.CurrentCallsView import im.vector.app.core.ui.views.CurrentCallsViewPresenter @@ -71,6 +73,7 @@ class NewHomeDetailFragment @Inject constructor( private val vectorPreferences: VectorPreferences, private val spaceStateHandler: SpaceStateHandler, private val session: Session, + private val buildMeta: BuildMeta, ) : VectorBaseFragment(), KeysBackupBanner.Delegate, CurrentCallsView.Callback, @@ -125,6 +128,7 @@ class NewHomeDetailFragment @Inject constructor( setupToolbar() setupKeysBackupBanner() setupActiveCallView() + setupDebugButton() withState(viewModel) { // Update the navigation view if needed (for when we restore the tabs) @@ -192,6 +196,7 @@ class NewHomeDetailFragment @Inject constructor( updateTabVisibilitySafely(R.id.bottom_action_notification, vectorPreferences.labAddNotificationTab()) callManager.checkForProtocolsSupportIfNeeded() refreshSpaceState() + refreshDebugButtonState() } private fun refreshSpaceState() { @@ -367,6 +372,17 @@ class NewHomeDetailFragment @Inject constructor( } } + private fun setupDebugButton() { + views.debugButton.debouncedClicks { + sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) + navigator.openDebug(requireActivity()) + } + } + + private fun refreshDebugButtonState() { + views.debugButton.isVisible = buildMeta.isDebug && vectorPreferences.developerMode() + } + /* ========================================================================================== * KeysBackupBanner Listener * ========================================================================================== */ diff --git a/vector/src/main/res/layout/fragment_new_home_detail.xml b/vector/src/main/res/layout/fragment_new_home_detail.xml index 8066ab1bd9..eae8a7ba30 100644 --- a/vector/src/main/res/layout/fragment_new_home_detail.xml +++ b/vector/src/main/res/layout/fragment_new_home_detail.xml @@ -74,6 +74,19 @@ + + From fc76d08186bdf02c80d627f4de602b3d35e1afeb Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 09:22:37 +0200 Subject: [PATCH 039/270] Makes home activity restart if app layout flag change is detected --- .../java/im/vector/app/features/home/HomeActivity.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 12cdaecdf9..16ee0c1958 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -41,6 +41,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.replaceFragment +import im.vector.app.core.extensions.restart import im.vector.app.core.extensions.validateBackPressed import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorMenuProvider @@ -136,6 +137,8 @@ class HomeActivity : @Inject lateinit var fcmHelper: FcmHelper @Inject lateinit var nightlyProxy: NightlyProxy + private var isNewAppLayoutEnabled: Boolean = false // delete once old app layout is removed + private val createSpaceResultLauncher = registerStartForActivityResult { activityResult -> if (activityResult.resultCode == Activity.RESULT_OK) { val spaceId = SpaceCreationActivity.getCreatedSpaceId(activityResult.data) @@ -193,6 +196,7 @@ class HomeActivity : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + isNewAppLayoutEnabled = vectorFeatures.isNewAppLayoutEnabled() analyticsScreenName = MobileScreen.ScreenName.Home supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false) unifiedPushHelper.register(this) { @@ -556,6 +560,14 @@ class HomeActivity : // Check nightly nightlyProxy.onHomeResumed() + + checkNewAppLayoutFlagChange() + } + + private fun checkNewAppLayoutFlagChange() { + if (buildMeta.isDebug && vectorFeatures.isNewAppLayoutEnabled() != isNewAppLayoutEnabled) { + restart() + } } override fun getMenuRes() = if (vectorFeatures.isNewAppLayoutEnabled()) R.menu.menu_new_home else R.menu.menu_home From 0b8c68739e2148dd744295a02b12c018fa469fe9 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 09:43:29 +0200 Subject: [PATCH 040/270] Makes debug settings refresh state onResume in old app layout --- .../java/im/vector/app/features/home/HomeDrawerFragment.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt index 535f38e68e..c10027cc3f 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt @@ -113,10 +113,14 @@ class HomeDrawerFragment @Inject constructor( } // Debug menu - views.homeDrawerHeaderDebugView.isVisible = buildMeta.isDebug && vectorPreferences.developerMode() views.homeDrawerHeaderDebugView.debouncedClicks { sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) navigator.openDebug(requireActivity()) } } + + override fun onResume() { + super.onResume() + views.homeDrawerHeaderDebugView.isVisible = buildMeta.isDebug && vectorPreferences.developerMode() + } } From 2e323e6f2e52401176d086b702fae3d188697933 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 10:09:32 +0200 Subject: [PATCH 041/270] Makes debug icon hide when collapsing toolbar --- .../im/vector/app/features/home/NewHomeDetailFragment.kt | 5 +++++ vector/src/main/res/layout/fragment_new_home_detail.xml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt index 1acbeccc28..760b6d8a4f 100644 --- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt @@ -28,6 +28,7 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState +import com.google.android.material.appbar.AppBarLayout import com.google.android.material.badge.BadgeDrawable import im.vector.app.R import im.vector.app.SpaceStateHandler @@ -377,6 +378,10 @@ class NewHomeDetailFragment @Inject constructor( sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer) navigator.openDebug(requireActivity()) } + + views.appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset -> + views.debugButton.isVisible = verticalOffset == 0 + }) } private fun refreshDebugButtonState() { diff --git a/vector/src/main/res/layout/fragment_new_home_detail.xml b/vector/src/main/res/layout/fragment_new_home_detail.xml index eae8a7ba30..d54d799a62 100644 --- a/vector/src/main/res/layout/fragment_new_home_detail.xml +++ b/vector/src/main/res/layout/fragment_new_home_detail.xml @@ -68,8 +68,8 @@ android:id="@+id/avatar" android:layout_width="36dp" android:layout_height="36dp" - android:padding="6dp" android:contentDescription="@string/a11y_open_settings" + android:padding="6dp" tools:src="@sample/user_round_avatars" /> From 136ca4bafbdf24bb4fb6693b14f6c73e51a799fe Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 10:16:54 +0200 Subject: [PATCH 042/270] Adds changelog file --- changelog.d/6871.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6871.feature diff --git a/changelog.d/6871.feature b/changelog.d/6871.feature new file mode 100644 index 0000000000..313be1a602 --- /dev/null +++ b/changelog.d/6871.feature @@ -0,0 +1 @@ +Improves Developer Mode Debug Button UX and adds it to New App Layout From 457f7fffeecbcd403f817306264421a12fa2c4dd Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 18 Aug 2022 09:50:43 +0100 Subject: [PATCH 043/270] promoting the accept certificate to an explict ViewEvent - allows a retryAction to be provided to the event to avoid mutatble state within the view model along with providing a clear path of execution --- .../android/sdk/api/failure/Extensions.kt | 2 + .../features/onboarding/OnboardingAction.kt | 2 +- .../onboarding/OnboardingViewEvents.kt | 2 + .../onboarding/OnboardingViewModel.kt | 42 +++++++++++-------- .../ftueauth/AbstractFtueAuthFragment.kt | 12 +++--- .../onboarding/ftueauth/FtueAuthVariant.kt | 1 + 6 files changed, 36 insertions(+), 25 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt index 68b931b33c..429d346a1b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt @@ -93,6 +93,8 @@ fun Throwable.isMissingEmailVerification() = this is Failure.ServerError && error.code == MatrixError.M_UNAUTHORIZED && error.message == "Unable to get validated threepid" +fun Throwable.isUnrecognisedCertificate() = this is Failure.UnrecognizedCertificateFailure + /** * Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible */ diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt index d07ac46b85..f1617b660b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt @@ -82,7 +82,7 @@ sealed interface OnboardingAction : VectorViewModelAction { data class PostViewEvent(val viewEvent: OnboardingViewEvents) : OnboardingAction - data class UserAcceptCertificate(val fingerprint: Fingerprint) : OnboardingAction + data class UserAcceptCertificate(val fingerprint: Fingerprint, val retryAction: OnboardingAction) : OnboardingAction object PersonalizeProfile : OnboardingAction data class UpdateDisplayName(val displayName: String) : OnboardingAction diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt index bbbf13fba9..1441152128 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt @@ -21,6 +21,7 @@ import im.vector.app.core.platform.VectorViewEvents import im.vector.app.features.login.ServerType import im.vector.app.features.login.SignMode import org.matrix.android.sdk.api.auth.registration.Stage +import org.matrix.android.sdk.api.failure.Failure as SdkFailure /** * Transient events for Login. @@ -29,6 +30,7 @@ sealed class OnboardingViewEvents : VectorViewEvents { data class Loading(val message: CharSequence? = null) : OnboardingViewEvents() data class Failure(val throwable: Throwable) : OnboardingViewEvents() data class DeeplinkAuthenticationFailure(val retryAction: OnboardingAction) : OnboardingViewEvents() + data class UnrecognisedCertificateFailure(val retryAction: OnboardingAction, val cause: SdkFailure.UnrecognizedCertificateFailure) : OnboardingViewEvents() object DisplayRegistrationFallback : OnboardingViewEvents() data class DisplayRegistrationStage(val stage: Stage) : OnboardingViewEvents() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 73288bd6d5..b0ba113d41 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -60,7 +60,9 @@ import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider import org.matrix.android.sdk.api.auth.login.LoginWizard import org.matrix.android.sdk.api.auth.registration.RegistrationAvailability import org.matrix.android.sdk.api.auth.registration.RegistrationWizard +import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.isHomeserverUnavailable +import org.matrix.android.sdk.api.failure.isUnrecognisedCertificate import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider import timber.log.Timber @@ -113,8 +115,6 @@ class OnboardingViewModel @AssistedInject constructor( } } - // Store the last action, to redo it after user has trusted the untrusted certificate - private var lastAction: OnboardingAction? = null private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() @@ -146,9 +146,9 @@ class OnboardingViewModel @AssistedInject constructor( is OnboardingAction.UpdateServerType -> handleUpdateServerType(action) is OnboardingAction.UpdateSignMode -> handleUpdateSignMode(action) is OnboardingAction.InitWith -> handleInitWith(action) - is OnboardingAction.HomeServerChange -> withAction(action) { handleHomeserverChange(action) } + is OnboardingAction.HomeServerChange -> handleHomeserverChange(action) is OnboardingAction.UserNameEnteredAction -> handleUserNameEntered(action) - is AuthenticateAction -> withAction(action) { handleAuthenticateAction(action) } + is AuthenticateAction -> handleAuthenticateAction(action) is OnboardingAction.LoginWithToken -> handleLoginWithToken(action) is OnboardingAction.WebLoginSuccess -> handleWebLoginSuccess(action) is OnboardingAction.ResetPassword -> handleResetPassword(action) @@ -221,11 +221,6 @@ class OnboardingViewModel @AssistedInject constructor( ) } - private fun withAction(action: OnboardingAction, block: (OnboardingAction) -> Unit) { - lastAction = action - block(action) - } - private fun handleAuthenticateAction(action: AuthenticateAction) { when (action) { is AuthenticateAction.Register -> handleRegisterWith(action.username, action.password, action.initialDeviceName) @@ -276,15 +271,15 @@ class OnboardingViewModel @AssistedInject constructor( private fun handleUserAcceptCertificate(action: OnboardingAction.UserAcceptCertificate) { // It happens when we get the login flow, or during direct authentication. // So alter the homeserver config and retrieve again the login flow - when (val finalLastAction = lastAction) { - is OnboardingAction.HomeServerChange.SelectHomeServer -> { + when (action.retryAction) { + is OnboardingAction.HomeServerChange -> { currentHomeServerConnectionConfig ?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) } - ?.let { startAuthenticationFlow(finalLastAction, it, serverTypeOverride = null) } + ?.let { startAuthenticationFlow(action.retryAction, it, serverTypeOverride = null) } } is AuthenticateAction.LoginDirect -> handleDirectLogin( - finalLastAction, + action.retryAction, HomeServerConnectionConfig.Builder() // Will be replaced by the task .withHomeServerUri("https://dummy.org") @@ -589,9 +584,19 @@ class OnboardingViewModel @AssistedInject constructor( currentJob = viewModelScope.launch { directLoginUseCase.execute(action, homeServerConnectionConfig).fold( onSuccess = { onSessionCreated(it, authenticationDescription = AuthenticationDescription.Login) }, - onFailure = { + onFailure = { error -> setState { copy(isLoading = false) } - _viewEvents.post(OnboardingViewEvents.Failure(it)) + when { + error.isUnrecognisedCertificate() -> { + _viewEvents.post( + OnboardingViewEvents.UnrecognisedCertificateFailure( + retryAction = action, + cause = error as Failure.UnrecognizedCertificateFailure + ) + ) + } + else -> _viewEvents.post(OnboardingViewEvents.Failure(error)) + } } ) } @@ -723,9 +728,10 @@ class OnboardingViewModel @AssistedInject constructor( retryAction = (trigger as OnboardingAction.HomeServerChange.SelectHomeServer).resetToDefaultUrl() ) ) - else -> _viewEvents.post( - OnboardingViewEvents.Failure(error) - ) + error.isUnrecognisedCertificate() -> { + _viewEvents.post(OnboardingViewEvents.UnrecognisedCertificateFailure(trigger, error as Failure.UnrecognizedCertificateFailure)) + } + else -> _viewEvents.post(OnboardingViewEvents.Failure(error)) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt index 072e94bc30..f3cb326221 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt @@ -33,7 +33,6 @@ import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewModel import im.vector.app.features.onboarding.OnboardingViewState import kotlinx.coroutines.CancellationException -import org.matrix.android.sdk.api.failure.Failure /** * Parent Fragment for all the login/registration screens. @@ -68,6 +67,7 @@ abstract class AbstractFtueAuthFragment : VectorBaseFragment showFailure(viewEvents.throwable) + is OnboardingViewEvents.UnrecognisedCertificateFailure -> showUnrecognizedCertificateFailure(viewEvents) else -> // This is handled by the Activity Unit @@ -84,20 +84,20 @@ abstract class AbstractFtueAuthFragment : VectorBaseFragment /* Ignore this error, user has cancelled the action */ Unit - is Failure.UnrecognizedCertificateFailure -> showUnrecognizedCertificateFailure(throwable) else -> onError(throwable) } } - private fun showUnrecognizedCertificateFailure(failure: Failure.UnrecognizedCertificateFailure) { + private fun showUnrecognizedCertificateFailure(event: OnboardingViewEvents.UnrecognisedCertificateFailure) { // Ask the user to accept the certificate + val cause = event.cause unrecognizedCertificateDialog.show(requireActivity(), - failure.fingerprint, - failure.url, + cause.fingerprint, + cause.url, object : UnrecognizedCertificateDialog.Callback { override fun onAccept() { // User accept the certificate - viewModel.handle(OnboardingAction.UserAcceptCertificate(failure.fingerprint)) + viewModel.handle(OnboardingAction.UserAcceptCertificate(cause.fingerprint, event.retryAction)) } override fun onIgnore() { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 150ab74ec2..e568b3d92b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -202,6 +202,7 @@ class FtueAuthVariant( openMsisdnConfirmation(viewEvents.msisdn) } is OnboardingViewEvents.Failure, + is OnboardingViewEvents.UnrecognisedCertificateFailure, is OnboardingViewEvents.Loading -> // This is handled by the Fragments Unit From a6ff10cbafd57ab4ba72292b062084d9788649ff Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 18 Aug 2022 10:02:47 +0100 Subject: [PATCH 044/270] allowing fingerprint to be passed to the config factory - which in turn allows the android Uri to be bypassed and a unit test around the direct local certificate case added --- .../HomeServerConnectionConfigFactory.kt | 10 ++++- .../onboarding/OnboardingViewModel.kt | 7 +--- .../onboarding/OnboardingViewModelTest.kt | 37 ++++++++++++++++--- .../FakeHomeServerConnectionConfigFactory.kt | 5 ++- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/login/HomeServerConnectionConfigFactory.kt b/vector/src/main/java/im/vector/app/features/login/HomeServerConnectionConfigFactory.kt index 955c3f7290..253c514e5a 100644 --- a/vector/src/main/java/im/vector/app/features/login/HomeServerConnectionConfigFactory.kt +++ b/vector/src/main/java/im/vector/app/features/login/HomeServerConnectionConfigFactory.kt @@ -17,12 +17,13 @@ package im.vector.app.features.login import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig +import org.matrix.android.sdk.api.network.ssl.Fingerprint import timber.log.Timber import javax.inject.Inject class HomeServerConnectionConfigFactory @Inject constructor() { - fun create(url: String?): HomeServerConnectionConfig? { + fun create(url: String?, fingerprint: Fingerprint? = null): HomeServerConnectionConfig? { if (url == null) { return null } @@ -30,6 +31,13 @@ class HomeServerConnectionConfigFactory @Inject constructor() { return try { HomeServerConnectionConfig.Builder() .withHomeServerUri(url) + .run { + if (fingerprint == null) { + this + } else { + withAllowedFingerPrints(listOf(fingerprint)) + } + } .build() } catch (t: Throwable) { Timber.e(t) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index b0ba113d41..0cd5437e5b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -280,11 +280,8 @@ class OnboardingViewModel @AssistedInject constructor( is AuthenticateAction.LoginDirect -> handleDirectLogin( action.retryAction, - HomeServerConnectionConfig.Builder() - // Will be replaced by the task - .withHomeServerUri("https://dummy.org") - .withAllowedFingerPrints(listOf(action.fingerprint)) - .build() + // Will be replaced by the task + homeServerConnectionConfigFactory.create("https://dummy.org", action.fingerprint) ) else -> Unit } diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index b505d05944..f802c3e8f6 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -58,6 +58,7 @@ import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider import org.matrix.android.sdk.api.auth.registration.Stage import org.matrix.android.sdk.api.failure.Failure +import org.matrix.android.sdk.api.network.ssl.Fingerprint import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities @@ -69,6 +70,7 @@ private val A_LOADABLE_REGISTER_ACTION = RegisterAction.StartRegistration private val A_NON_LOADABLE_REGISTER_ACTION = RegisterAction.CheckIfEmailHasBeenValidated(delayMillis = -1L) private val A_RESULT_IGNORED_REGISTER_ACTION = RegisterAction.SendAgainThreePid private val A_HOMESERVER_CAPABILITIES = aHomeServerCapabilities(canChangeDisplayName = true, canChangeAvatar = true) +private val A_FINGERPRINT = Fingerprint(ByteArray(1), Fingerprint.HashType.SHA1) private val ANY_CONTINUING_REGISTRATION_RESULT = RegistrationActionHandler.Result.NextStage(Stage.Dummy(mandatory = true)) private val A_DIRECT_LOGIN = OnboardingAction.AuthenticateAction.LoginDirect("@a-user:id.org", "a-password", "a-device-name") private const val A_HOMESERVER_URL = "https://edited-homeserver.org" @@ -406,7 +408,7 @@ class OnboardingViewModelTest { @Test fun `given unavailable deeplink, when selecting homeserver, then emits failure with default homeserver as retry action`() = runTest { fakeContext.givenHasConnection() - fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, A_HOMESERVER_CONFIG) + fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprint = null, A_HOMESERVER_CONFIG) fakeStartAuthenticationFlowUseCase.givenHomeserverUnavailable(A_HOMESERVER_CONFIG) val test = viewModel.test() @@ -723,6 +725,25 @@ class OnboardingViewModelTest { .assertEvents(OnboardingViewEvents.OnPersonalizationComplete) .finish() } + + @Test + fun `given DirectLogin retry action, when accepting user certificate, then logs in directly`() = runTest { + fakeHomeServerConnectionConfigFactory.givenConfigFor("https://dummy.org", A_FINGERPRINT, A_HOMESERVER_CONFIG) + fakeDirectLoginUseCase.givenSuccessResult(A_DIRECT_LOGIN, config = A_HOMESERVER_CONFIG, result = fakeSession) + givenInitialisesSession(fakeSession) + val test = viewModel.test() + + viewModel.handle(OnboardingAction.UserAcceptCertificate(A_FINGERPRINT, A_DIRECT_LOGIN)) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(isLoading = false) } + ) + .assertEvents(OnboardingViewEvents.OnAccountSignedIn) + .finish() + } @Test fun `given can successfully start password reset, when resetting password, then emits confirmation email sent`() = runTest { @@ -991,15 +1012,19 @@ class OnboardingViewModelTest { fakeRegistrationActionHandler.givenResultsFor(results) } - private fun givenCanSuccessfullyUpdateHomeserver(homeserverUrl: String, resultingState: SelectedHomeserverState) { - fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, A_HOMESERVER_CONFIG) - fakeStartAuthenticationFlowUseCase.givenResult(A_HOMESERVER_CONFIG, StartAuthenticationResult(isHomeserverOutdated = false, resultingState)) + private fun givenCanSuccessfullyUpdateHomeserver( + homeserverUrl: String, + resultingState: SelectedHomeserverState, + config: HomeServerConnectionConfig = A_HOMESERVER_CONFIG + ) { + fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprint = null, config) + fakeStartAuthenticationFlowUseCase.givenResult(config, StartAuthenticationResult(isHomeserverOutdated = false, resultingState)) givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.StartRegistration) - fakeHomeServerHistoryService.expectUrlToBeAdded(A_HOMESERVER_CONFIG.homeServerUri.toString()) + fakeHomeServerHistoryService.expectUrlToBeAdded(config.homeServerUri.toString()) } private fun givenUpdatingHomeserverErrors(homeserverUrl: String, resultingState: SelectedHomeserverState, error: Throwable) { - fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, A_HOMESERVER_CONFIG) + fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprint = null, A_HOMESERVER_CONFIG) fakeStartAuthenticationFlowUseCase.givenResult(A_HOMESERVER_CONFIG, StartAuthenticationResult(isHomeserverOutdated = false, resultingState)) givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.Error(error)) fakeHomeServerHistoryService.expectUrlToBeAdded(A_HOMESERVER_CONFIG.homeServerUri.toString()) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeHomeServerConnectionConfigFactory.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeHomeServerConnectionConfigFactory.kt index 553a35ad8c..c0cfe5375b 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeHomeServerConnectionConfigFactory.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeHomeServerConnectionConfigFactory.kt @@ -20,11 +20,12 @@ import im.vector.app.features.login.HomeServerConnectionConfigFactory import io.mockk.every import io.mockk.mockk import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig +import org.matrix.android.sdk.api.network.ssl.Fingerprint class FakeHomeServerConnectionConfigFactory { val instance: HomeServerConnectionConfigFactory = mockk() - fun givenConfigFor(url: String, config: HomeServerConnectionConfig) { - every { instance.create(url) } returns config + fun givenConfigFor(url: String, fingerprint: Fingerprint? = null, config: HomeServerConnectionConfig) { + every { instance.create(url, fingerprint) } returns config } } From e4a08d1be14c07b7795708a306f3ff25e03d4e78 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 18 Aug 2022 10:59:02 +0100 Subject: [PATCH 045/270] recreating the homeserver config from the retry action when handle certificate accept action - adds unit tests around the edit/selection cases --- .../onboarding/OnboardingViewModel.kt | 20 +++---- .../onboarding/OnboardingViewModelTest.kt | 59 ++++++++++++++++++- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 0cd5437e5b..6228b95398 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -63,6 +63,7 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationWizard import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.isHomeserverUnavailable import org.matrix.android.sdk.api.failure.isUnrecognisedCertificate +import org.matrix.android.sdk.api.network.ssl.Fingerprint import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.util.BuildVersionSdkIntProvider import timber.log.Timber @@ -115,8 +116,6 @@ class OnboardingViewModel @AssistedInject constructor( } } - private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null - private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() private val defaultHomeserverUrl = matrixOrgUrl @@ -272,11 +271,7 @@ class OnboardingViewModel @AssistedInject constructor( // It happens when we get the login flow, or during direct authentication. // So alter the homeserver config and retrieve again the login flow when (action.retryAction) { - is OnboardingAction.HomeServerChange -> { - currentHomeServerConnectionConfig - ?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) } - ?.let { startAuthenticationFlow(action.retryAction, it, serverTypeOverride = null) } - } + is OnboardingAction.HomeServerChange -> handleHomeserverChange(action.retryAction, fingerprint = action.fingerprint) is AuthenticateAction.LoginDirect -> handleDirectLogin( action.retryAction, @@ -684,8 +679,13 @@ class OnboardingViewModel @AssistedInject constructor( } } - private fun handleHomeserverChange(action: OnboardingAction.HomeServerChange, serverTypeOverride: ServerType? = null, postAction: suspend () -> Unit = {}) { - val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl) + private fun handleHomeserverChange( + action: OnboardingAction.HomeServerChange, + serverTypeOverride: ServerType? = null, + fingerprint: Fingerprint? = null, + postAction: suspend () -> Unit = {}, + ) { + val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl, fingerprint) if (homeServerConnectionConfig == null) { // This is invalid _viewEvents.post(OnboardingViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig"))) @@ -700,8 +700,6 @@ class OnboardingViewModel @AssistedInject constructor( serverTypeOverride: ServerType?, postAction: suspend () -> Unit = {}, ) { - currentHomeServerConnectionConfig = homeServerConnectionConfig - currentJob = viewModelScope.launch { setState { copy(isLoading = true) } runCatching { startAuthenticationFlowUseCase.execute(homeServerConnectionConfig) }.fold( diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index f802c3e8f6..c612644576 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -725,7 +725,59 @@ class OnboardingViewModelTest { .assertEvents(OnboardingViewEvents.OnPersonalizationComplete) .finish() } - + + + @Test + fun `given in sign in mode, when accepting user certificate with SelectHomeserver retry action, then emits OnHomeserverEdited`() = runTest { + viewModelWith(initialState.copy(onboardingFlow = OnboardingFlow.SignIn)) + val test = viewModel.test() + fakeVectorFeatures.givenCombinedLoginEnabled() + givenCanSuccessfullyUpdateHomeserver( + A_HOMESERVER_URL, + SELECTED_HOMESERVER_STATE, + config = A_HOMESERVER_CONFIG.copy(allowedFingerprints = listOf(A_FINGERPRINT)), + fingerprint = A_FINGERPRINT, + ) + + viewModel.handle(OnboardingAction.UserAcceptCertificate(A_FINGERPRINT, OnboardingAction.HomeServerChange.SelectHomeServer(A_HOMESERVER_URL))) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(selectedHomeserver = SELECTED_HOMESERVER_STATE) }, + { copy(signMode = SignMode.SignIn) }, + { copy(isLoading = false) } + ) + .assertEvents(OnboardingViewEvents.OpenCombinedLogin) + .finish() + } + + @Test + fun `given in sign up mode, when accepting user certificate with EditHomeserver retry action, then emits OnHomeserverEdited`() = runTest { + viewModelWith(initialState.copy(onboardingFlow = OnboardingFlow.SignUp)) + givenCanSuccessfullyUpdateHomeserver( + A_HOMESERVER_URL, + SELECTED_HOMESERVER_STATE, + config = A_HOMESERVER_CONFIG.copy(allowedFingerprints = listOf(A_FINGERPRINT)), + fingerprint = A_FINGERPRINT, + ) + val test = viewModel.test() + + viewModel.handle(OnboardingAction.UserAcceptCertificate(A_FINGERPRINT, OnboardingAction.HomeServerChange.EditHomeServer(A_HOMESERVER_URL))) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(selectedHomeserver = SELECTED_HOMESERVER_STATE) }, + { copy(isLoading = false) } + + ) + .assertEvents(OnboardingViewEvents.OnHomeserverEdited) + .finish() + } + @Test fun `given DirectLogin retry action, when accepting user certificate, then logs in directly`() = runTest { fakeHomeServerConnectionConfigFactory.givenConfigFor("https://dummy.org", A_FINGERPRINT, A_HOMESERVER_CONFIG) @@ -1015,9 +1067,10 @@ class OnboardingViewModelTest { private fun givenCanSuccessfullyUpdateHomeserver( homeserverUrl: String, resultingState: SelectedHomeserverState, - config: HomeServerConnectionConfig = A_HOMESERVER_CONFIG + config: HomeServerConnectionConfig = A_HOMESERVER_CONFIG, + fingerprint: Fingerprint? = null, ) { - fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprint = null, config) + fakeHomeServerConnectionConfigFactory.givenConfigFor(homeserverUrl, fingerprint, config) fakeStartAuthenticationFlowUseCase.givenResult(config, StartAuthenticationResult(isHomeserverOutdated = false, resultingState)) givenRegistrationResultFor(RegisterAction.StartRegistration, RegistrationActionHandler.Result.StartRegistration) fakeHomeServerHistoryService.expectUrlToBeAdded(config.homeServerUri.toString()) From 91176eca2243b77984ab52dc544330b7bf480b44 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 18 Aug 2022 11:22:38 +0100 Subject: [PATCH 046/270] adding test cases around certificate errors being thrown and mapped --- .../onboarding/OnboardingViewModelTest.kt | 60 ++++++++++++++++++- .../FakeStartAuthenticationFlowUseCase.kt | 4 ++ .../app/test/fixtures/FailureFixture.kt | 3 + 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index c612644576..216cb76084 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -48,6 +48,7 @@ import im.vector.app.test.fakes.FakeVectorOverrides import im.vector.app.test.fakes.toTestString import im.vector.app.test.fixtures.a401ServerError import im.vector.app.test.fixtures.aHomeServerCapabilities +import im.vector.app.test.fixtures.anUnrecognisedCertificateError import im.vector.app.test.test import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBeEqualTo @@ -66,6 +67,7 @@ private const val A_DISPLAY_NAME = "a display name" private const val A_PICTURE_FILENAME = "a-picture.png" private val A_SERVER_ERROR = a401ServerError() private val AN_ERROR = RuntimeException("an error!") +private val AN_UNRECOGNISED_CERTIFICATE_ERROR = anUnrecognisedCertificateError() private val A_LOADABLE_REGISTER_ACTION = RegisterAction.StartRegistration private val A_NON_LOADABLE_REGISTER_ACTION = RegisterAction.CheckIfEmailHasBeenValidated(delayMillis = -1L) private val A_RESULT_IGNORED_REGISTER_ACTION = RegisterAction.SendAgainThreePid @@ -322,6 +324,25 @@ class OnboardingViewModelTest { .finish() } + @Test + fun `given has sign in with matrix id sign mode, when handling login or register action fails with certificate error, then emits error`() = runTest { + viewModelWith(initialState.copy(signMode = SignMode.SignInWithMatrixId)) + fakeDirectLoginUseCase.givenFailureResult(A_DIRECT_LOGIN, config = null, cause = AN_UNRECOGNISED_CERTIFICATE_ERROR) + givenInitialisesSession(fakeSession) + val test = viewModel.test() + + viewModel.handle(A_DIRECT_LOGIN) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(isLoading = false) } + ) + .assertEvents(OnboardingViewEvents.UnrecognisedCertificateFailure(A_DIRECT_LOGIN, AN_UNRECOGNISED_CERTIFICATE_ERROR)) + .finish() + } + @Test fun `when handling SignUp then sets sign mode to sign up and starts registration`() = runTest { givenRegistrationResultFor(RegisterAction.StartRegistration, ANY_CONTINUING_REGISTRATION_RESULT) @@ -550,6 +571,44 @@ class OnboardingViewModelTest { .finish() } + @Test + fun `when editing homeserver errors with certificate error, then emits error`() = runTest { + fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprint = null, A_HOMESERVER_CONFIG) + fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, AN_UNRECOGNISED_CERTIFICATE_ERROR) + val editAction = OnboardingAction.HomeServerChange.EditHomeServer(A_HOMESERVER_URL) + val test = viewModel.test() + + viewModel.handle(editAction) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(isLoading = false) } + ) + .assertEvents(OnboardingViewEvents.UnrecognisedCertificateFailure(editAction, AN_UNRECOGNISED_CERTIFICATE_ERROR)) + .finish() + } + + @Test + fun `when selecting homeserver errors with certificate error, then emits error`() = runTest { + fakeHomeServerConnectionConfigFactory.givenConfigFor(A_HOMESERVER_URL, fingerprint = null, A_HOMESERVER_CONFIG) + fakeStartAuthenticationFlowUseCase.givenErrors(A_HOMESERVER_CONFIG, AN_UNRECOGNISED_CERTIFICATE_ERROR) + val selectAction = OnboardingAction.HomeServerChange.SelectHomeServer(A_HOMESERVER_URL) + val test = viewModel.test() + + viewModel.handle(selectAction) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(isLoading = false) } + ) + .assertEvents(OnboardingViewEvents.UnrecognisedCertificateFailure(selectAction, AN_UNRECOGNISED_CERTIFICATE_ERROR)) + .finish() + } + @Test fun `given unavailable full matrix id, when a register username is entered, then emits availability error`() = runTest { viewModelWith(initialRegistrationState("ignored-url")) @@ -726,7 +785,6 @@ class OnboardingViewModelTest { .finish() } - @Test fun `given in sign in mode, when accepting user certificate with SelectHomeserver retry action, then emits OnHomeserverEdited`() = runTest { viewModelWith(initialState.copy(onboardingFlow = OnboardingFlow.SignIn)) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt index bfbef9e565..4b2709facc 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeStartAuthenticationFlowUseCase.kt @@ -31,6 +31,10 @@ class FakeStartAuthenticationFlowUseCase { coEvery { instance.execute(config) } returns result } + fun givenErrors(config: HomeServerConnectionConfig, error: Throwable) { + coEvery { instance.execute(config) } throws error + } + fun givenHomeserverUnavailable(config: HomeServerConnectionConfig) { coEvery { instance.execute(config) } throws aHomeserverUnavailableError() } diff --git a/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt index 0f44976ab3..8437401294 100644 --- a/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt +++ b/vector/src/test/java/im/vector/app/test/fixtures/FailureFixture.kt @@ -18,6 +18,7 @@ package im.vector.app.test.fixtures import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError +import org.matrix.android.sdk.api.network.ssl.Fingerprint import java.net.UnknownHostException import javax.net.ssl.HttpsURLConnection @@ -38,3 +39,5 @@ fun aLoginEmailUnknownError() = Failure.ServerError( ) fun aHomeserverUnavailableError() = Failure.NetworkConnection(UnknownHostException()) + +fun anUnrecognisedCertificateError() = Failure.UnrecognizedCertificateFailure("a-url", Fingerprint(ByteArray(1), Fingerprint.HashType.SHA1)) From e948fe05ca8a55b59ceb619a1750477548347481 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 18 Aug 2022 11:37:12 +0100 Subject: [PATCH 047/270] adding changelog entry --- changelog.d/6864.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6864.bugfix diff --git a/changelog.d/6864.bugfix b/changelog.d/6864.bugfix new file mode 100644 index 0000000000..6db3d7c074 --- /dev/null +++ b/changelog.d/6864.bugfix @@ -0,0 +1 @@ +Fixes server selection being unable to trust certificates From 2b382d12495f2fea7ee01c0d0ac841091980f297 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 16 Aug 2022 15:54:32 +0100 Subject: [PATCH 048/270] allowing the combined login flow to have state loss as the transaction occurs asynchronusly --- .../app/features/onboarding/ftueauth/FtueAuthVariant.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 150ab74ec2..97628f81d9 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -260,7 +260,7 @@ class FtueAuthVariant( } private fun onStartCombinedLogin() { - addRegistrationStageFragmentToBackstack(FtueAuthCombinedLoginFragment::class.java) + addRegistrationStageFragmentToBackstack(FtueAuthCombinedLoginFragment::class.java, allowStateLoss = true) } private fun openStartCombinedRegister() { @@ -519,13 +519,14 @@ class FtueAuthVariant( ) } - private fun addRegistrationStageFragmentToBackstack(fragmentClass: Class, params: Parcelable? = null) { + private fun addRegistrationStageFragmentToBackstack(fragmentClass: Class, params: Parcelable? = null, allowStateLoss: Boolean = false) { activity.addFragmentToBackstack( views.loginFragmentContainer, fragmentClass, params, tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption + option = commonOption, + allowStateLoss = allowStateLoss, ) } From 9a5b21d8f104caac2c0785e0a076950c8c0b1054 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 16 Aug 2022 16:15:35 +0100 Subject: [PATCH 049/270] allowing the combined registration flow to have state loss as the transaction occurs asynchronusly --- .../vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 97628f81d9..1f7a26b829 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -264,7 +264,7 @@ class FtueAuthVariant( } private fun openStartCombinedRegister() { - addRegistrationStageFragmentToBackstack(FtueAuthCombinedRegisterFragment::class.java) + addRegistrationStageFragmentToBackstack(FtueAuthCombinedRegisterFragment::class.java, allowStateLoss = true) } private fun displayFallbackWebDialog() { From 1d03460aee8471666b665adf389d1aa3af502fe9 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 17 Aug 2022 11:38:30 +0100 Subject: [PATCH 050/270] removing ability to shortcut registration to waiting for email if the app is destroyed - this behaviour puts the app in an invalid state as we've lost all the ViewState we've collect from the previous onboarding steps - the app already handles restoring the onboarding state via the system restoration --- .../features/onboarding/OnboardingViewModel.kt | 16 +--------------- .../onboarding/OnboardingViewModelTest.kt | 15 --------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 73288bd6d5..6106d84a8d 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -71,7 +71,7 @@ import java.util.concurrent.CancellationException * */ class OnboardingViewModel @AssistedInject constructor( - @Assisted initialState: OnboardingViewState, + @Assisted private val initialState: OnboardingViewState, private val applicationContext: Context, private val authenticationService: AuthenticationService, private val activeSessionHolder: ActiveSessionHolder, @@ -123,9 +123,6 @@ class OnboardingViewModel @AssistedInject constructor( private val registrationWizard: RegistrationWizard get() = authenticationService.getRegistrationWizard() - val currentThreePid: String? - get() = registrationWizard.getCurrentThreePid() - // True when login and password has been sent with success to the homeserver val isRegistrationStarted: Boolean get() = authenticationService.isRegistrationStarted() @@ -492,17 +489,6 @@ class OnboardingViewModel @AssistedInject constructor( private fun handleInitWith(action: OnboardingAction.InitWith) { loginConfig = action.loginConfig - // If there is a pending email validation continue on this step - try { - if (registrationWizard.isRegistrationStarted()) { - currentThreePid?.let { - handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnSendEmailSuccess(it, isRestoredSession = true))) - } - } - } catch (e: Throwable) { - // NOOP. API is designed to use wizards in a login/registration flow, - // but we need to check the state anyway. - } } private fun handleResetPassword(action: OnboardingAction.ResetPassword) { diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index b505d05944..93195e2f12 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -191,21 +191,6 @@ class OnboardingViewModelTest { .finish() } - @Test - fun `given registration started with currentThreePid, when handling InitWith, then emits restored session OnSendEmailSuccess`() = runTest { - val test = viewModel.test() - fakeAuthenticationService.givenRegistrationWizard(FakeRegistrationWizard().also { - it.givenRegistrationStarted(hasStarted = true) - it.givenCurrentThreePid(AN_EMAIL) - }) - - viewModel.handle(OnboardingAction.InitWith(LoginConfig(A_HOMESERVER_URL, identityServerUrl = null))) - - test - .assertEvents(OnboardingViewEvents.OnSendEmailSuccess(AN_EMAIL, isRestoredSession = true)) - .finish() - } - @Test fun `given registration not started, when handling InitWith, then does nothing`() = runTest { val test = viewModel.test() From ca10109a655d7f82383f2eacddf05fa3f7981451 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 17 Aug 2022 13:51:58 +0100 Subject: [PATCH 051/270] coverting captcha webview to a viewstub in order to catch errors when the system webview is missing or has been disabled --- .../ftueauth/FtueAuthCaptchaFragment.kt | 62 ++++++++++++++++++- .../layout/fragment_ftue_login_captcha.xml | 18 +++++- .../src/main/res/layout/view_stub_webview.xml | 4 ++ 3 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 vector/src/main/res/layout/view_stub_webview.xml diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt index 3720a41455..0562378ba5 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt @@ -16,15 +16,22 @@ package im.vector.app.features.onboarding.ftueauth +import android.os.Bundle import android.os.Parcelable import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.view.ViewStub import com.airbnb.mvrx.args +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import im.vector.app.R import im.vector.app.databinding.FragmentFtueLoginCaptchaBinding +import im.vector.app.databinding.ViewStubWebviewBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.RegisterAction import kotlinx.parcelize.Parcelize +import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject @Parcelize @@ -40,10 +47,32 @@ class FtueAuthCaptchaFragment @Inject constructor( ) : AbstractFtueAuthFragment() { private val params: FtueAuthCaptchaFragmentArgument by args() + private var webViewBinding: ViewStubWebviewBinding? = null private var isWebViewLoaded = false override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueLoginCaptchaBinding { - return FragmentFtueLoginCaptchaBinding.inflate(inflater, container, false) + return FragmentFtueLoginCaptchaBinding.inflate(inflater, container, false).also { + it.loginCaptchaWebViewStub.setOnInflateListener { _, inflated -> + webViewBinding = ViewStubWebviewBinding.bind(inflated) + } + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + inflateWebViewOrShowError() + } + + private fun inflateWebViewOrShowError() { + views.loginCaptchaWebViewStub.inflateWebView(onError = { + MaterialAlertDialogBuilder(requireActivity()) + .setTitle(R.string.dialog_title_error) + .setMessage(it.localizedMessage) + .setPositiveButton(R.string.ok) { _, _ -> + requireActivity().recreate() + } + .show() + }) } override fun resetViewModel() { @@ -51,11 +80,38 @@ class FtueAuthCaptchaFragment @Inject constructor( } override fun updateWithState(state: OnboardingViewState) { - if (!isWebViewLoaded) { - captchaWebview.setupWebView(this, views.loginCaptchaWevView, views.loginCaptchaProgress, params.siteKey, state) { + if (!isWebViewLoaded && webViewBinding != null) { + captchaWebview.setupWebView(this, webViewBinding!!.root, views.loginCaptchaProgress, params.siteKey, state) { viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.CaptchaDone(it))) } isWebViewLoaded = true } } } + +private fun ViewStub.inflateWebView(onError: (Throwable) -> Unit) { + try { + inflate() + } catch (e: Exception) { + val isMissingWebView = e.crawlCausesFor { it.message?.contains("MissingWebViewPackageException").orFalse() } + if (isMissingWebView) { + onError(MissingWebViewException(e)) + } else { + onError(e) + } + } +} + +private fun Throwable?.crawlCausesFor(predicate: (Throwable) -> Boolean): Boolean { + return when { + this == null -> false + else -> { + when (predicate(this)) { + true -> true + else -> this.cause.crawlCausesFor(predicate) + } + } + } +} + +private class MissingWebViewException(cause: Throwable) : IllegalStateException("Failed to load WebView provider: No WebView installed", cause) diff --git a/vector/src/main/res/layout/fragment_ftue_login_captcha.xml b/vector/src/main/res/layout/fragment_ftue_login_captcha.xml index 2f6970c785..fc93d0f990 100644 --- a/vector/src/main/res/layout/fragment_ftue_login_captcha.xml +++ b/vector/src/main/res/layout/fragment_ftue_login_captcha.xml @@ -64,15 +64,27 @@ android:id="@+id/titleContentSpacing" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintBottom_toTopOf="@id/loginCaptchaWevView" + app:layout_constraintBottom_toTopOf="@id/loginWebViewBarrier" app:layout_constraintHeight_percent="0.03" app:layout_constraintTop_toBottomOf="@id/captchaHeaderTitle" /> - + + + From a1a8ccae3821717b17e4de7fb78fd275ea800583 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 17 Aug 2022 14:15:35 +0100 Subject: [PATCH 052/270] reverting scope of init only variable --- .../im/vector/app/features/onboarding/OnboardingViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 6106d84a8d..d5ed20c89c 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -71,7 +71,7 @@ import java.util.concurrent.CancellationException * */ class OnboardingViewModel @AssistedInject constructor( - @Assisted private val initialState: OnboardingViewState, + @Assisted initialState: OnboardingViewState, private val applicationContext: Context, private val authenticationService: AuthenticationService, private val activeSessionHolder: ActiveSessionHolder, From cdeea219175d30cd5e2640343080bb05d6509196 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 17 Aug 2022 14:43:03 +0100 Subject: [PATCH 053/270] adding changelog entries --- changelog.d/6855.bugfix | 1 + changelog.d/6860.bugfix | 1 + changelog.d/6861.bugfix | 1 + 3 files changed, 3 insertions(+) create mode 100644 changelog.d/6855.bugfix create mode 100644 changelog.d/6860.bugfix create mode 100644 changelog.d/6861.bugfix diff --git a/changelog.d/6855.bugfix b/changelog.d/6855.bugfix new file mode 100644 index 0000000000..63a62de986 --- /dev/null +++ b/changelog.d/6855.bugfix @@ -0,0 +1 @@ +Fixes onboarding captcha crashing when no WebView is available by showing an error with information instead diff --git a/changelog.d/6860.bugfix b/changelog.d/6860.bugfix new file mode 100644 index 0000000000..22e287c0b3 --- /dev/null +++ b/changelog.d/6860.bugfix @@ -0,0 +1 @@ +Removes ability to continue registration after the app has been destroyed, fixes the next steps crashing due to missing information from the previous steps diff --git a/changelog.d/6861.bugfix b/changelog.d/6861.bugfix new file mode 100644 index 0000000000..508325acc6 --- /dev/null +++ b/changelog.d/6861.bugfix @@ -0,0 +1 @@ +Fixes crash when exiting the login or registration entry screens whilst they're loading From 8b70f3a3b98bb10f78ad55df7b056ca712aca32f Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 17 Aug 2022 16:16:44 +0100 Subject: [PATCH 054/270] extracting throwable crawling to extension --- .../vector/app/core/extensions/Throwable.kt | 34 +++++++++++++++++++ .../ftueauth/FtueAuthCaptchaFragment.kt | 13 +------ 2 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/core/extensions/Throwable.kt diff --git a/vector/src/main/java/im/vector/app/core/extensions/Throwable.kt b/vector/src/main/java/im/vector/app/core/extensions/Throwable.kt new file mode 100644 index 0000000000..e1688124fa --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/extensions/Throwable.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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.core.extensions + +/** + * Recursive through the throwable and its causes for the given predicate + * + * @return true when the predicate finds a match + */ +tailrec fun Throwable?.crawlCausesFor(predicate: (Throwable) -> Boolean): Boolean { + return when { + this == null -> false + else -> { + when (predicate(this)) { + true -> true + else -> this.cause.crawlCausesFor(predicate) + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt index 0562378ba5..1f44922b3b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt @@ -25,6 +25,7 @@ import android.view.ViewStub import com.airbnb.mvrx.args import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R +import im.vector.app.core.extensions.crawlCausesFor import im.vector.app.databinding.FragmentFtueLoginCaptchaBinding import im.vector.app.databinding.ViewStubWebviewBinding import im.vector.app.features.onboarding.OnboardingAction @@ -102,16 +103,4 @@ private fun ViewStub.inflateWebView(onError: (Throwable) -> Unit) { } } -private fun Throwable?.crawlCausesFor(predicate: (Throwable) -> Boolean): Boolean { - return when { - this == null -> false - else -> { - when (predicate(this)) { - true -> true - else -> this.cause.crawlCausesFor(predicate) - } - } - } -} - private class MissingWebViewException(cause: Throwable) : IllegalStateException("Failed to load WebView provider: No WebView installed", cause) From 106fa1b1d5b3be24a340af4c8d7404150ca349f5 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 18 Aug 2022 11:51:23 +0100 Subject: [PATCH 055/270] adding missing fullstops in to docs --- .../src/main/java/im/vector/app/core/extensions/Throwable.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/extensions/Throwable.kt b/vector/src/main/java/im/vector/app/core/extensions/Throwable.kt index e1688124fa..0aa9039dcb 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Throwable.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Throwable.kt @@ -17,9 +17,9 @@ package im.vector.app.core.extensions /** - * Recursive through the throwable and its causes for the given predicate + * Recursive through the throwable and its causes for the given predicate. * - * @return true when the predicate finds a match + * @return true when the predicate finds a match. */ tailrec fun Throwable?.crawlCausesFor(predicate: (Throwable) -> Boolean): Boolean { return when { From 2fb794dd59f7cf02ca1fcc0b74bff0a658298fbc Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 14:09:22 +0200 Subject: [PATCH 056/270] Fixes space header showing "Empty Space" after switching to newly created space --- vector/src/main/java/im/vector/app/SpaceStateHandler.kt | 2 ++ .../src/main/java/im/vector/app/SpaceStateHandlerImpl.kt | 5 ++++- .../java/im/vector/app/features/home/HomeActivity.kt | 9 ++++++++- .../vector/app/features/navigation/DefaultNavigator.kt | 9 +++++++-- .../java/im/vector/app/features/navigation/Navigator.kt | 7 ++++++- .../vector/app/features/spaces/SpaceCreationActivity.kt | 6 ++++++ .../app/features/spaces/create/CreateSpaceEvents.kt | 2 +- .../app/features/spaces/create/CreateSpaceViewModel.kt | 2 ++ 8 files changed, 36 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt index b8f90471e8..2651d62f1a 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt @@ -42,12 +42,14 @@ interface SpaceStateHandler : DefaultLifecycleObserver { * @param session the current active session * @param persistNow if true, the current space will immediately be persisted in shared prefs * @param isForwardNavigation whether this navigation is a forward action to properly handle backstack + * @param overriddenSpaceName overrides the display name of the space being set */ fun setCurrentSpace( spaceId: String?, session: Session? = null, persistNow: Boolean = false, isForwardNavigation: Boolean = true, + overriddenSpaceName: String? = null, ) /** diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index c36b6de17b..7bd0ac70a6 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -72,10 +72,13 @@ class SpaceStateHandlerImpl @Inject constructor( session: Session?, persistNow: Boolean, isForwardNavigation: Boolean, + overriddenSpaceName: String?, ) { val activeSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return val spaceToLeave = selectedSpaceDataSource.currentValue?.orNull() - val spaceToSet = spaceId?.let { activeSession.getRoomSummary(spaceId) } + val spaceToSet = spaceId?.let { activeSession.getRoomSummary(spaceId) }?.let { + if (overriddenSpaceName != null) it.copy(displayName = overriddenSpaceName) else it + } val sameSpaceSelected = spaceId == spaceToLeave?.roomId if (sameSpaceSelected) { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 12cdaecdf9..4b86c739a0 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -55,6 +55,8 @@ import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.disclaimer.showDisclaimerDialog +import im.vector.app.features.home.room.list.actions.RoomListSharedAction +import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel import im.vector.app.features.matrixto.MatrixToBottomSheet import im.vector.app.features.matrixto.OriginOfMatrixTo import im.vector.app.features.navigation.Navigator @@ -110,6 +112,7 @@ class HomeActivity : VectorMenuProvider { private lateinit var sharedActionViewModel: HomeSharedActionViewModel + private lateinit var roomListSharedActionViewModel: RoomListSharedActionViewModel private val homeActivityViewModel: HomeActivityViewModel by viewModel() @@ -139,6 +142,7 @@ class HomeActivity : private val createSpaceResultLauncher = registerStartForActivityResult { activityResult -> if (activityResult.resultCode == Activity.RESULT_OK) { val spaceId = SpaceCreationActivity.getCreatedSpaceId(activityResult.data) + val spaceName = SpaceCreationActivity.getCreatedSpaceName(activityResult.data) val defaultRoomId = SpaceCreationActivity.getDefaultRoomId(activityResult.data) val isJustMe = SpaceCreationActivity.isJustMeSpace(activityResult.data) views.drawerLayout.closeDrawer(GravityCompat.START) @@ -155,8 +159,10 @@ class HomeActivity : navigator.switchToSpace( context = this, spaceId = spaceId, - postSwitchOption + postSwitchOption, + overriddenSpaceName = spaceName, ) + roomListSharedActionViewModel.post(RoomListSharedAction.CloseBottomSheet) } } } @@ -205,6 +211,7 @@ class HomeActivity : } } sharedActionViewModel = viewModelProvider[HomeSharedActionViewModel::class.java] + roomListSharedActionViewModel = viewModelProvider[RoomListSharedActionViewModel::class.java] views.drawerLayout.addDrawerListener(drawerListener) if (isFirstCreation()) { if (vectorFeatures.isNewAppLayoutEnabled()) { diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 38db642287..c661a66767 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -177,12 +177,17 @@ class DefaultNavigator @Inject constructor( startActivity(context, intent, buildTask) } - override fun switchToSpace(context: Context, spaceId: String, postSwitchSpaceAction: Navigator.PostSwitchSpaceAction) { + override fun switchToSpace( + context: Context, + spaceId: String, + postSwitchSpaceAction: Navigator.PostSwitchSpaceAction, + overriddenSpaceName: String?, + ) { if (sessionHolder.getSafeActiveSession()?.getRoomSummary(spaceId) == null) { fatalError("Trying to open an unknown space $spaceId", vectorPreferences.failFast()) return } - spaceStateHandler.setCurrentSpace(spaceId) + spaceStateHandler.setCurrentSpace(spaceId, overriddenSpaceName = overriddenSpaceName) when (postSwitchSpaceAction) { Navigator.PostSwitchSpaceAction.None -> { // go back to home if we are showing room details? diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index 8e01b3ed50..bb59c84555 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -68,7 +68,12 @@ interface Navigator { data class OpenDefaultRoom(val roomId: String, val showShareSheet: Boolean) : PostSwitchSpaceAction() } - fun switchToSpace(context: Context, spaceId: String, postSwitchSpaceAction: PostSwitchSpaceAction) + fun switchToSpace( + context: Context, + spaceId: String, + postSwitchSpaceAction: PostSwitchSpaceAction, + overriddenSpaceName: String? = null, + ) fun openSpacePreview(context: Context, spaceId: String) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt index 9fa4a53efc..aeca7021eb 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt @@ -104,6 +104,7 @@ class SpaceCreationActivity : SimpleFragmentActivity() { is CreateSpaceEvents.FinishSuccess -> { setResult(RESULT_OK, Intent().apply { putExtra(RESULT_DATA_CREATED_SPACE_ID, it.spaceId) + putExtra(RESULT_DATA_CREATED_SPACE_NAME, it.spaceName) putExtra(RESULT_DATA_DEFAULT_ROOM_ID, it.defaultRoomId) putExtra(RESULT_DATA_CREATED_SPACE_IS_JUST_ME, it.topology == SpaceTopology.JustMe) }) @@ -159,6 +160,7 @@ class SpaceCreationActivity : SimpleFragmentActivity() { companion object { private const val RESULT_DATA_CREATED_SPACE_ID = "RESULT_DATA_CREATED_SPACE_ID" + private const val RESULT_DATA_CREATED_SPACE_NAME = "RESULT_DATA_CREATED_SPACE_NAME" private const val RESULT_DATA_DEFAULT_ROOM_ID = "RESULT_DATA_DEFAULT_ROOM_ID" private const val RESULT_DATA_CREATED_SPACE_IS_JUST_ME = "RESULT_DATA_CREATED_SPACE_IS_JUST_ME" @@ -172,6 +174,10 @@ class SpaceCreationActivity : SimpleFragmentActivity() { return data?.extras?.getString(RESULT_DATA_CREATED_SPACE_ID) } + fun getCreatedSpaceName(data: Intent?): String? { + return data?.extras?.getString(RESULT_DATA_CREATED_SPACE_NAME) + } + fun getDefaultRoomId(data: Intent?): String? { return data?.extras?.getString(RESULT_DATA_DEFAULT_ROOM_ID) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt index eeb2ca30ff..45d1700352 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt @@ -25,7 +25,7 @@ sealed class CreateSpaceEvents : VectorViewEvents { object NavigateToAdd3Pid : CreateSpaceEvents() object NavigateToChoosePrivateType : CreateSpaceEvents() object Dismiss : CreateSpaceEvents() - data class FinishSuccess(val spaceId: String, val defaultRoomId: String?, val topology: SpaceTopology?) : CreateSpaceEvents() + data class FinishSuccess(val spaceId: String, val spaceName: String, val defaultRoomId: String?, val topology: SpaceTopology?) : CreateSpaceEvents() data class ShowModalError(val errorMessage: String) : CreateSpaceEvents() object HideModalLoading : CreateSpaceEvents() data class ShowModalLoading(val message: String?) : CreateSpaceEvents() diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt index b680f77df2..761f0f791b 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt @@ -380,6 +380,7 @@ class CreateSpaceViewModel @AssistedInject constructor( _viewEvents.post( CreateSpaceEvents.FinishSuccess( result.spaceId, + spaceName, result.childIds.firstOrNull(), state.spaceTopology ) @@ -393,6 +394,7 @@ class CreateSpaceViewModel @AssistedInject constructor( _viewEvents.post( CreateSpaceEvents.FinishSuccess( result.spaceId, + spaceName, result.childIds.firstOrNull(), state.spaceTopology ) From ec3512fd5b8c94c964eb16dc14933f775afaf0d6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Aug 2022 14:58:19 +0200 Subject: [PATCH 057/270] Increase some log level --- .../android/sdk/internal/util/BackgroundDetectionObserver.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt index 901d0eca8f..dea5f131b9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt @@ -49,13 +49,13 @@ internal class DefaultBackgroundDetectionObserver : BackgroundDetectionObserver } override fun onStart(owner: LifecycleOwner) { - Timber.v("App returning to foreground…") + Timber.d("App returning to foreground…") isInBackground = false listeners.forEach { it.onMoveToForeground() } } override fun onStop(owner: LifecycleOwner) { - Timber.v("App going to background…") + Timber.d("App going to background…") isInBackground = true listeners.forEach { it.onMoveToBackground() } } From 4ffab7fc130c1600571cade42b5d336c4f415648 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Aug 2022 15:09:48 +0200 Subject: [PATCH 058/270] API: return String instead of printing out to logcat. --- .../org/matrix/android/sdk/api/debug/DebugService.kt | 4 ++-- .../java/org/matrix/android/sdk/api/session/Session.kt | 4 ++-- .../sdk/internal/database/tools/RealmDebugTools.kt | 8 +++----- .../android/sdk/internal/debug/DefaultDebugService.kt | 8 ++++---- .../android/sdk/internal/session/DefaultSession.kt | 10 +++++----- .../im/vector/app/features/rageshake/BugReporter.kt | 7 ++++++- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt index d0cee08831..7f5e4f2ee7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/debug/DebugService.kt @@ -28,7 +28,7 @@ interface DebugService { fun getAllRealmConfigurations(): List /** - * Prints out info on DB size to logcat. + * Get info on DB size. */ - fun logDbUsageInfo() + fun getDbUsageInfo(): String } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index 63c1c25130..13993149f4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -323,9 +323,9 @@ interface Session { fun getUiaSsoFallbackUrl(authenticationSessionId: String): String /** - * Debug API, will print out info on DB size to logcat. + * Debug API, will return info about the DB. */ - fun logDbUsageInfo() + fun getDbUsageInfo(): String /** * Debug API, return the list of all RealmConfiguration used by this session. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt index dc20549eb3..2e9c3303d4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt @@ -19,16 +19,15 @@ package org.matrix.android.sdk.internal.database.tools import io.realm.Realm import io.realm.RealmConfiguration import org.matrix.android.sdk.BuildConfig -import timber.log.Timber internal class RealmDebugTools( private val realmConfiguration: RealmConfiguration ) { /** - * Log info about the DB. + * Get info about the DB. */ - fun logInfo(baseName: String) { - buildString { + fun getInfo(baseName: String): String { + return buildString { append("\n$baseName Realm located at : ${realmConfiguration.realmDirectory}/${realmConfiguration.realmFileName}") if (BuildConfig.LOG_PRIVATE_DATA) { @@ -54,7 +53,6 @@ internal class RealmDebugTools( separator() } } - .let { Timber.i(it) } } private fun StringBuilder.separator() = append("\n==============================================") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt index 3f2e6fafc8..46479c3db6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/debug/DefaultDebugService.kt @@ -36,9 +36,9 @@ internal class DefaultDebugService @Inject constructor( realmConfigurationGlobal } - override fun logDbUsageInfo() { - RealmDebugTools(realmConfigurationAuth).logInfo("Auth") - RealmDebugTools(realmConfigurationGlobal).logInfo("Global") - sessionManager.getLastSession()?.logDbUsageInfo() + override fun getDbUsageInfo() = buildString { + append(RealmDebugTools(realmConfigurationAuth).getInfo("Auth")) + append(RealmDebugTools(realmConfigurationGlobal).getInfo("Global")) + append(sessionManager.getLastSession()?.getDbUsageInfo()) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index 57db187bdc..679c5085ef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -263,11 +263,11 @@ internal class DefaultSession @Inject constructor( } } - override fun logDbUsageInfo() { - RealmDebugTools(realmConfiguration).logInfo("Session") - RealmDebugTools(realmConfigurationCrypto).logInfo("Crypto") - RealmDebugTools(realmConfigurationIdentity).logInfo("Identity") - RealmDebugTools(realmConfigurationContentScanner).logInfo("ContentScanner") + override fun getDbUsageInfo() = buildString { + append(RealmDebugTools(realmConfiguration).getInfo("Session")) + append(RealmDebugTools(realmConfigurationCrypto).getInfo("Crypto")) + append(RealmDebugTools(realmConfigurationIdentity).getInfo("Identity")) + append(RealmDebugTools(realmConfigurationContentScanner).getInfo("ContentScanner")) } override fun getRealmConfigurations(): List { diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index ad09593ebd..50bb1f8368 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -499,10 +499,15 @@ class BugReporter @Inject constructor( */ fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) { screenshot = takeScreenshot(activity) - matrix.debugService().logDbUsageInfo() + logDbInfo() activity.startActivity(BugReportActivity.intent(activity, reportType)) } + private fun logDbInfo() { + val dbInfo = matrix.debugService().getDbUsageInfo() + Timber.i(dbInfo) + } + private fun rageShakeAppNameForReport(reportType: ReportType): String { // As per https://github.com/matrix-org/rageshake // app: Identifier for the application (eg 'riot-web'). From 03d83b2aff1470825dac243d67be34d5dc5ebd67 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Aug 2022 15:52:19 +0200 Subject: [PATCH 059/270] Log info about process and thread in the Rageshake --- .../app/features/rageshake/BugReporter.kt | 7 ++ .../app/features/rageshake/ProcessInfo.kt | 71 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/rageshake/ProcessInfo.kt diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index 50bb1f8368..44fa4137e1 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -78,6 +78,7 @@ class BugReporter @Inject constructor( private val systemLocaleProvider: SystemLocaleProvider, private val matrix: Matrix, private val buildMeta: BuildMeta, + private val processInfo: ProcessInfo, private val sdkIntProvider: BuildVersionSdkIntProvider, ) { var inMultiWindowMode = false @@ -500,6 +501,7 @@ class BugReporter @Inject constructor( fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) { screenshot = takeScreenshot(activity) logDbInfo() + logProcessInfo() activity.startActivity(BugReportActivity.intent(activity, reportType)) } @@ -508,6 +510,11 @@ class BugReporter @Inject constructor( Timber.i(dbInfo) } + private fun logProcessInfo() { + val pInfo = processInfo.getInfo() + Timber.i(pInfo) + } + private fun rageShakeAppNameForReport(reportType: ReportType): String { // As per https://github.com/matrix-org/rageshake // app: Identifier for the application (eg 'riot-web'). diff --git a/vector/src/main/java/im/vector/app/features/rageshake/ProcessInfo.kt b/vector/src/main/java/im/vector/app/features/rageshake/ProcessInfo.kt new file mode 100644 index 0000000000..78e49a2e65 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/rageshake/ProcessInfo.kt @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 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.rageshake + +import android.annotation.SuppressLint +import android.app.Application +import android.os.Build +import android.os.Process +import java.lang.reflect.Method +import javax.inject.Inject + +class ProcessInfo @Inject constructor() { + fun getInfo() = buildString { + append("===========================================\n") + append("* PROCESS INFO *\n") + append("===========================================\n") + val processId = Process.myPid() + append("ProcessId: $processId\n") + append("ProcessName: ${getProcessName()}\n") + append(getThreadInfo()) + append("===========================================\n") + } + + @SuppressLint("PrivateApi") + private fun getProcessName(): String? { + return if (Build.VERSION.SDK_INT >= 28) { + Application.getProcessName() + } else { + try { + val activityThread = Class.forName("android.app.ActivityThread") + val getProcessName: Method = activityThread.getDeclaredMethod("currentProcessName") + getProcessName.invoke(null) as? String + } catch (t: Throwable) { + null + } + } + } + + private fun getThreadInfo() = buildString { + append("Thread activeCount: ${Thread.activeCount()}\n") + Thread.getAllStackTraces().keys + .sortedBy { it.name } + .forEach { thread -> append(thread.getInfo()) } + } +} + +private fun Thread.getInfo() = buildString { + append("Thread '$name':") + append(" id: $id") + append(" priority: $priority") + append(" group name: ${threadGroup?.name ?: "null"}") + append(" state: $state") + append(" isAlive: $isAlive") + append(" isDaemon: $isDaemon") + append(" isInterrupted: $isInterrupted") + append("\n") +} From f5104c7511e08e896b52f6d797187e7869b670fb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Aug 2022 16:44:04 +0200 Subject: [PATCH 060/270] Log parameter --- vector/src/main/java/im/vector/app/core/extensions/Session.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt index caed413e2b..cb1d46efce 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt @@ -28,7 +28,7 @@ import org.matrix.android.sdk.api.session.sync.FilterService import timber.log.Timber fun Session.configureAndStart(context: Context, startSyncing: Boolean = true) { - Timber.i("Configure and start session for $myUserId") + Timber.i("Configure and start session for $myUserId. startSyncing: $startSyncing") open() filterService().setFilter(FilterService.FilterPreset.ElementFilter) if (startSyncing) { From 789dffe4df41b75a75ab1b3c93ace568e12d03cf Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 16:51:54 +0200 Subject: [PATCH 061/270] Adds tests related to backstack --- .../java/im/vector/app/SpaceStateHandler.kt | 2 +- .../im/vector/app/SpaceStateHandlerImpl.kt | 14 ++++---- .../features/settings/VectorPreferences.kt | 4 +-- .../app/features/spaces/SpaceListViewModel.kt | 2 +- .../vector/app/SpaceStateHandlerImplTest.kt | 33 ++++++++++++------- .../app/test/fakes/FakeVectorPreferences.kt | 11 ++++++- 6 files changed, 42 insertions(+), 24 deletions(-) diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt index 2651d62f1a..acc2279d1a 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt @@ -59,7 +59,7 @@ interface SpaceStateHandler : DefaultLifecycleObserver { */ fun popSpaceBackstack(): String? - fun getPersistedSpaceBackstack(): List + fun getSpaceBackstack(): List /** * Gets a flow of the selected space for clients to react immediately to space changes. diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index 7bd0ac70a6..d2b3abba59 100644 --- a/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -109,13 +109,13 @@ class SpaceStateHandlerImpl @Inject constructor( } private fun addToBackstack(spaceToLeave: RoomSummary?, spaceToSet: RoomSummary?) { - // Only add to the persisted backstack if the space to set is not All Chats, else reset the persisted stack + // Only add to the backstack if the space to set is not All Chats, else clear the backstack if (spaceToSet != null) { - val currentPersistedBackstack = vectorPreferences.getPersistedSpaceBackstack().toMutableList() + val currentPersistedBackstack = vectorPreferences.getSpaceBackstack().toMutableList() currentPersistedBackstack.add(spaceToLeave?.roomId) - vectorPreferences.setPersistedSpaceBackstack(currentPersistedBackstack) + vectorPreferences.setSpaceBackstack(currentPersistedBackstack) } else { - vectorPreferences.setPersistedSpaceBackstack(emptyList()) + vectorPreferences.setSpaceBackstack(emptyList()) } } @@ -143,14 +143,14 @@ class SpaceStateHandlerImpl @Inject constructor( } override fun popSpaceBackstack(): String? { - vectorPreferences.getPersistedSpaceBackstack().toMutableList().apply { + vectorPreferences.getSpaceBackstack().toMutableList().apply { val poppedSpaceId = removeLast() - vectorPreferences.setPersistedSpaceBackstack(this) + vectorPreferences.setSpaceBackstack(this) return poppedSpaceId } } - override fun getPersistedSpaceBackstack() = vectorPreferences.getPersistedSpaceBackstack() + override fun getSpaceBackstack() = vectorPreferences.getSpaceBackstack() override fun getSelectedSpaceFlow() = selectedSpaceFlow diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index cb571da9d3..d973609009 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -1120,7 +1120,7 @@ class VectorPreferences @Inject constructor( * * Only the IDs of the spaces are stored */ - fun setPersistedSpaceBackstack(spaceBackstack: List) { + fun setSpaceBackstack(spaceBackstack: List) { val spaceIdsJoined = spaceBackstack.takeIf { it.isNotEmpty() }?.joinToString(",") defaultPrefs.edit().putString(SETTINGS_PERSISTED_SPACE_BACKSTACK, spaceIdsJoined).apply() } @@ -1128,7 +1128,7 @@ class VectorPreferences @Inject constructor( /** * Gets the space backstack used for up navigation */ - fun getPersistedSpaceBackstack(): List { + fun getSpaceBackstack(): List { val spaceIdsJoined = defaultPrefs.getString(SETTINGS_PERSISTED_SPACE_BACKSTACK, null) return spaceIdsJoined?.takeIf { it.isNotEmpty() }?.split(",").orEmpty() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt index fdec36add0..d8e5d49ddf 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt @@ -85,7 +85,7 @@ class SpaceListViewModel @AssistedInject constructor( } observeSpaceSummaries() - val spaceHistory = spaceStateHandler.getPersistedSpaceBackstack() + val spaceHistory = spaceStateHandler.getSpaceBackstack() .map { it to it?.let { session.roomService().getRoomSummary(it)?.displayName }.orEmpty() } spaceStateHandler.getSelectedSpaceFlow() .distinctUntilChanged() diff --git a/vector/src/test/java/im/vector/app/SpaceStateHandlerImplTest.kt b/vector/src/test/java/im/vector/app/SpaceStateHandlerImplTest.kt index 36d372cfac..3a01054db2 100644 --- a/vector/src/test/java/im/vector/app/SpaceStateHandlerImplTest.kt +++ b/vector/src/test/java/im/vector/app/SpaceStateHandlerImplTest.kt @@ -21,11 +21,13 @@ import im.vector.app.test.fakes.FakeActiveSessionHolder import im.vector.app.test.fakes.FakeAnalyticsTracker import im.vector.app.test.fakes.FakeSession import im.vector.app.test.fakes.FakeUiStateRepository +import im.vector.app.test.fakes.FakeVectorPreferences import im.vector.app.test.fixtures.RoomSummaryFixture.aRoomSummary import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeEqualTo +import org.junit.Before import org.junit.Test internal class SpaceStateHandlerImplTest { @@ -38,14 +40,21 @@ internal class SpaceStateHandlerImplTest { private val uiStateRepository = FakeUiStateRepository() private val activeSessionHolder = FakeActiveSessionHolder(session) private val analyticsTracker = FakeAnalyticsTracker() + private val vectorPreferences = FakeVectorPreferences() private val spaceStateHandler = SpaceStateHandlerImpl( sessionDataSource.instance, uiStateRepository, activeSessionHolder.instance, analyticsTracker, + vectorPreferences.instance, ) + @Before + fun setup() { + vectorPreferences.givenSpaceBackstack(emptyList()) + } + @Test fun `given selected space doesn't exist, when getCurrentSpace, then return null`() { val currentSpace = spaceStateHandler.getCurrentSpace() @@ -77,33 +86,33 @@ internal class SpaceStateHandlerImplTest { } @Test - fun `given is forward navigation and no current space, when setCurrentSpace, then null added to backstack`() { + fun `given not in space and is forward navigation, when setCurrentSpace, then null added to backstack`() { spaceStateHandler.setCurrentSpace(spaceId, session, isForwardNavigation = true) - val backstack = spaceStateHandler.getSpaceBackstack() - - backstack.size shouldBe 1 - backstack.first() shouldBe null + vectorPreferences.verifySetSpaceBackstack(listOf(null)) } @Test - fun `given is forward navigation and is in space, when setCurrentSpace, then previous space added to backstack`() { + fun `given in space and is forward navigation, when setCurrentSpace, then previous space added to backstack`() { spaceStateHandler.setCurrentSpace(spaceId, session, isForwardNavigation = true) spaceStateHandler.setCurrentSpace("secondSpaceId", session, isForwardNavigation = true) - val backstack = spaceStateHandler.getSpaceBackstack() - - backstack.size shouldBe 2 - backstack shouldBeEqualTo listOf(null, spaceId) + vectorPreferences.verifySetSpaceBackstack(listOf(spaceId)) } @Test fun `given is not forward navigation, when setCurrentSpace, then previous space not added to backstack`() { spaceStateHandler.setCurrentSpace(spaceId, session, isForwardNavigation = false) - val backstack = spaceStateHandler.getSpaceBackstack() + vectorPreferences.verifySetSpaceBackstack(listOf(spaceId), inverse = true) + } - backstack.size shouldBe 0 + @Test + fun `given navigating to all chats, when setCurrentSpace, then backstack cleared`() { + spaceStateHandler.setCurrentSpace(spaceId, session) + spaceStateHandler.setCurrentSpace(null, session) + + vectorPreferences.verifySetSpaceBackstack(emptyList()) } @Test diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt index eb8f9ac413..bc761d9016 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeVectorPreferences.kt @@ -19,12 +19,21 @@ package im.vector.app.test.fakes import im.vector.app.features.settings.VectorPreferences import io.mockk.every import io.mockk.mockk +import io.mockk.verify class FakeVectorPreferences { - val instance = mockk() + val instance = mockk(relaxUnitFun = true) fun givenUseCompleteNotificationFormat(value: Boolean) { every { instance.useCompleteNotificationFormat() } returns value } + + fun givenSpaceBackstack(value: List) { + every { instance.getSpaceBackstack() } returns value + } + + fun verifySetSpaceBackstack(value: List, inverse: Boolean = false) { + verify(inverse = inverse) { instance.setSpaceBackstack(value) } + } } From 58e1fe4c01c02e8b9e418f5070be40a291c1d1fc Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 17:15:12 +0200 Subject: [PATCH 062/270] Adds DefaultNavigatorTest --- .../features/navigation/DefaultNavigator.kt | 14 +++- .../navigation/DefaultNavigatorTest.kt | 77 +++++++++++++++++++ .../vector/app/test/fakes/FakeRoomService.kt | 6 ++ .../im/vector/app/test/fakes/FakeSession.kt | 2 +- .../app/test/fakes/FakeSpaceStateHandler.kt | 28 +++++++ ...akeSupportedVerificationMethodsProvider.kt | 25 ++++++ .../app/test/fakes/FakeWidgetArgsBuilder.kt | 25 ++++++ 7 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/features/navigation/DefaultNavigatorTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeSpaceStateHandler.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeSupportedVerificationMethodsProvider.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeWidgetArgsBuilder.kt diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index c661a66767..0282556900 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -188,7 +188,15 @@ class DefaultNavigator @Inject constructor( return } spaceStateHandler.setCurrentSpace(spaceId, overriddenSpaceName = overriddenSpaceName) - when (postSwitchSpaceAction) { + handlePostSwitchAction(context, spaceId, postSwitchSpaceAction) + } + + private fun handlePostSwitchAction( + context: Context, + spaceId: String, + action: Navigator.PostSwitchSpaceAction, + ) { + when (action) { Navigator.PostSwitchSpaceAction.None -> { // go back to home if we are showing room details? // This is a bit ugly, but the navigator is supposed to know about the activity stack @@ -204,9 +212,9 @@ class DefaultNavigator @Inject constructor( } is Navigator.PostSwitchSpaceAction.OpenDefaultRoom -> { val args = TimelineArgs( - postSwitchSpaceAction.roomId, + action.roomId, eventId = null, - openShareSpaceForId = spaceId.takeIf { postSwitchSpaceAction.showShareSheet } + openShareSpaceForId = spaceId.takeIf { action.showShareSheet } ) val intent = RoomDetailActivity.newIntent(context, args, false) startActivity(context, intent, false) diff --git a/vector/src/test/java/im/vector/app/features/navigation/DefaultNavigatorTest.kt b/vector/src/test/java/im/vector/app/features/navigation/DefaultNavigatorTest.kt new file mode 100644 index 0000000000..79c514083c --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/navigation/DefaultNavigatorTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 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.navigation + +import im.vector.app.test.fakes.FakeActiveSessionHolder +import im.vector.app.test.fakes.FakeAnalyticsTracker +import im.vector.app.test.fakes.FakeContext +import im.vector.app.test.fakes.FakeSpaceStateHandler +import im.vector.app.test.fakes.FakeSupportedVerificationMethodsProvider +import im.vector.app.test.fakes.FakeVectorFeatures +import im.vector.app.test.fakes.FakeVectorPreferences +import im.vector.app.test.fakes.FakeWidgetArgsBuilder +import im.vector.app.test.fixtures.RoomSummaryFixture.aRoomSummary +import org.junit.Test + +internal class DefaultNavigatorTest { + + private val sessionHolder = FakeActiveSessionHolder() + private val vectorPreferences = FakeVectorPreferences() + private val widgetArgsBuilder = FakeWidgetArgsBuilder() + private val spaceStateHandler = FakeSpaceStateHandler() + private val supportedVerificationMethodsProvider = FakeSupportedVerificationMethodsProvider() + private val features = FakeVectorFeatures() + private val analyticsTracker = FakeAnalyticsTracker() + + private val navigator = DefaultNavigator( + sessionHolder.instance, + vectorPreferences.instance, + widgetArgsBuilder.instance, + spaceStateHandler, + supportedVerificationMethodsProvider.instance, + features, + analyticsTracker, + ) + + /** + * The below tests are by no means all that we want to test in [DefaultNavigator] + * Please add relevant tests as you make changes to or related to other functions in the class + */ + + @Test + fun `when switchToSpace, then current space set`() { + val spaceId = "space-id" + val spaceSummary = aRoomSummary(spaceId) + sessionHolder.fakeSession.fakeRoomService.getRoomSummaryReturns(spaceSummary) + + navigator.switchToSpace(FakeContext().instance, spaceId, Navigator.PostSwitchSpaceAction.None) + + spaceStateHandler.verifySetCurrentSpace(spaceId) + } + + @Test + fun `given non-null overriddenSpaceName, when switchToSpace, then current space set`() { + val spaceId = "space-id" + val spaceSummary = aRoomSummary(spaceId) + sessionHolder.fakeSession.fakeRoomService.getRoomSummaryReturns(spaceSummary) + val overriddenSpaceName = "new-space-name" + + navigator.switchToSpace(FakeContext().instance, spaceId, Navigator.PostSwitchSpaceAction.None, overriddenSpaceName) + + spaceStateHandler.verifySetCurrentSpace(spaceId, overriddenSpaceName = overriddenSpaceName) + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt index b09256f747..506e96ba11 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt @@ -16,12 +16,18 @@ package im.vector.app.test.fakes +import io.mockk.every import io.mockk.mockk import org.matrix.android.sdk.api.session.room.RoomService +import org.matrix.android.sdk.api.session.room.model.RoomSummary class FakeRoomService( private val fakeRoom: FakeRoom = FakeRoom() ) : RoomService by mockk() { override fun getRoom(roomId: String) = fakeRoom + + fun getRoomSummaryReturns(roomSummary: RoomSummary?) { + every { getRoomSummary(any()) } returns roomSummary + } } diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt index 18af88ba0f..ee016ecae3 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt @@ -37,7 +37,7 @@ class FakeSession( val fakeProfileService: FakeProfileService = FakeProfileService(), val fakeHomeServerCapabilitiesService: FakeHomeServerCapabilitiesService = FakeHomeServerCapabilitiesService(), val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService(), - private val fakeRoomService: FakeRoomService = FakeRoomService(), + val fakeRoomService: FakeRoomService = FakeRoomService(), private val fakeEventService: FakeEventService = FakeEventService(), ) : Session by mockk(relaxed = true) { diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSpaceStateHandler.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSpaceStateHandler.kt new file mode 100644 index 0000000000..04358d6a1f --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSpaceStateHandler.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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.test.fakes + +import im.vector.app.SpaceStateHandler +import io.mockk.mockk +import io.mockk.verify + +class FakeSpaceStateHandler : SpaceStateHandler by mockk(relaxUnitFun = true) { + + fun verifySetCurrentSpace(spaceId: String, overriddenSpaceName: String? = null) { + verify { setCurrentSpace(spaceId, overriddenSpaceName = overriddenSpaceName) } + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSupportedVerificationMethodsProvider.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSupportedVerificationMethodsProvider.kt new file mode 100644 index 0000000000..ecb7c3289b --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSupportedVerificationMethodsProvider.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 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.test.fakes + +import im.vector.app.features.crypto.verification.SupportedVerificationMethodsProvider +import io.mockk.mockk + +class FakeSupportedVerificationMethodsProvider { + + val instance = mockk() +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeWidgetArgsBuilder.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeWidgetArgsBuilder.kt new file mode 100644 index 0000000000..3a810b2c23 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeWidgetArgsBuilder.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 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.test.fakes + +import im.vector.app.features.widgets.WidgetArgsBuilder +import io.mockk.mockk + +class FakeWidgetArgsBuilder { + + val instance = mockk() +} From e17e3fe00a130e5dee869d001949c64c1ef439c4 Mon Sep 17 00:00:00 2001 From: ericdecanini Date: Thu, 18 Aug 2022 17:22:19 +0200 Subject: [PATCH 063/270] Adds changelog file --- changelog.d/6877.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6877.wip diff --git a/changelog.d/6877.wip b/changelog.d/6877.wip new file mode 100644 index 0000000000..415749a297 --- /dev/null +++ b/changelog.d/6877.wip @@ -0,0 +1 @@ +[New Layout] Adds space backstack for back navigation and space sheet header From 0b1b22852415ff11c42262faa9ed1ce9d89f524c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 18 Aug 2022 16:56:08 +0200 Subject: [PATCH 064/270] Fix #6782. Ensure SyncThread is started --- .../android/sdk/api/session/sync/SyncService.kt | 5 +++++ .../internal/session/sync/DefaultSyncService.kt | 2 ++ .../im/vector/app/core/di/ActiveSessionHolder.kt | 15 +++++++++++---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt index 71f7ab8494..6640b8a9af 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt @@ -53,6 +53,11 @@ interface SyncService { */ fun getSyncState(): SyncState + /** + * This method returns true if the sync thread is alive, i.e. started. + */ + fun isSyncThreadAlive(): Boolean + /** * This method allows to listen the sync state. * @return a [LiveData] of [SyncState]. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt index 691dd7b20d..76c3c38abf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt @@ -73,6 +73,8 @@ internal class DefaultSyncService @Inject constructor( override fun getSyncState() = getSyncThread().currentState() + override fun isSyncThreadAlive() = getSyncThread().isAlive + override fun getSyncRequestStateFlow() = syncRequestStateTracker.syncRequestState override fun hasAlreadySynced(): Boolean { diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt index 7a1d613ab9..bb2ca97aad 100644 --- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt +++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt @@ -20,6 +20,7 @@ import android.content.Context import arrow.core.Option import im.vector.app.ActiveSessionDataSource import im.vector.app.core.extensions.configureAndStart +import im.vector.app.core.extensions.startSyncing import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.services.GuardServiceStarter import im.vector.app.features.call.webrtc.WebRtcCallManager @@ -100,10 +101,16 @@ class ActiveSessionHolder @Inject constructor( } suspend fun getOrInitializeSession(startSync: Boolean): Session? { - return activeSessionReference.get() ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session -> - setActiveSession(session) - session.configureAndStart(applicationContext, startSyncing = startSync) - } + return activeSessionReference.get() + ?.also { + if (startSync && !it.syncService().isSyncThreadAlive()) { + it.startSyncing(applicationContext) + } + } + ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session -> + setActiveSession(session) + session.configureAndStart(applicationContext, startSyncing = startSync) + } } fun isWaitingForSessionInitialization() = activeSessionReference.get() == null && authenticationService.hasAuthenticatedSessions() From eeeb569ae086b06cdc3fdfb8d6f4320c22b47536 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Aug 2022 10:07:34 +0200 Subject: [PATCH 065/270] Add prefix to the name of the Thread the app is creating --- .../android/sdk/internal/database/RealmLiveEntityObserver.kt | 2 +- .../java/org/matrix/android/sdk/internal/di/MatrixModule.kt | 2 +- .../sdk/internal/session/room/timeline/DefaultTimeline.kt | 2 +- vector/src/main/java/im/vector/app/VectorApplication.kt | 2 +- .../home/room/detail/timeline/helper/TimelineAsyncHelper.kt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt index f2f88e216b..020b42b3b8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt @@ -38,7 +38,7 @@ internal abstract class RealmLiveEntityObserver(protected val r LiveEntityObserver, RealmChangeListener> { private companion object { - val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND") + val BACKGROUND_HANDLER = createBackgroundHandler("Matrix-LIVE_ENTITY_BACKGROUND") } protected val observerScope = CoroutineScope(SupervisorJob() + BACKGROUND_HANDLER.asCoroutineDispatcher()) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt index 49713a1d7f..f2f8a5dc04 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixModule.kt @@ -40,7 +40,7 @@ internal object MatrixModule { io = Dispatchers.IO, computation = Dispatchers.Default, main = Dispatchers.Main, - crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(), + crypto = createBackgroundHandler("Matrix-Crypto_Thread").asCoroutineDispatcher(), dmVerif = Executors.newSingleThreadExecutor().asCoroutineDispatcher() ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 4eaac67e5a..c380ccf14f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -76,7 +76,7 @@ internal class DefaultTimeline( ) : Timeline { companion object { - val BACKGROUND_HANDLER = createBackgroundHandler("DefaultTimeline_Thread") + val BACKGROUND_HANDLER = createBackgroundHandler("Matrix-DefaultTimeline_Thread") } override val timelineID = UUID.randomUUID().toString() diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index 4655de7377..46cb6ec79b 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -266,7 +266,7 @@ class VectorApplication : } private fun createFontThreadHandler(): Handler { - val handlerThread = HandlerThread("fonts") + val handlerThread = HandlerThread("Vector-fonts") handlerThread.start() return Handler(handlerThread.looper) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt index 655d46194d..87c6a1efda 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineAsyncHelper.kt @@ -19,7 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.helper import android.os.Handler import android.os.HandlerThread -private const val THREAD_NAME = "Timeline_Building_Thread" +private const val THREAD_NAME = "Vector-Timeline_Building_Thread" object TimelineAsyncHelper { From f75b2e6ef15c492ad6d36aafa4e346fcc6a54963 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Aug 2022 10:11:31 +0200 Subject: [PATCH 066/270] Changelog files. --- changelog.d/6884.bugfix | 1 + changelog.d/6884.sdk | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog.d/6884.bugfix create mode 100644 changelog.d/6884.sdk diff --git a/changelog.d/6884.bugfix b/changelog.d/6884.bugfix new file mode 100644 index 0000000000..6c6b286688 --- /dev/null +++ b/changelog.d/6884.bugfix @@ -0,0 +1 @@ +Ensure SyncThread is started when the app is launched after a Push has been received. diff --git a/changelog.d/6884.sdk b/changelog.d/6884.sdk new file mode 100644 index 0000000000..0de43420f0 --- /dev/null +++ b/changelog.d/6884.sdk @@ -0,0 +1 @@ +Rename `DebugService.logDbUsageInfo` (resp. `Session.logDbUsageInfo`) to `DebugService.getDbUsageInfo` (resp. `Session.getDbUsageInfo`) and return a String instead of logging. The caller may want to log the String. From 37d46ca729cebb6ea6a977e201ec525b18db8eea Mon Sep 17 00:00:00 2001 From: Fork Liang Date: Fri, 19 Aug 2022 08:42:06 +0000 Subject: [PATCH 067/270] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/ --- vector/src/main/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml index c52edec4bd..cf6e412ad2 100644 --- a/vector/src/main/res/values-zh-rCN/strings.xml +++ b/vector/src/main/res/values-zh-rCN/strings.xml @@ -104,7 +104,7 @@ 你把房间名称改为:%1$s 你发起了一次视频通话。 你发起了一次语音通话。 - %s 发送了数据以建立通话。 + %s 发送了数据以设置并建立通话。 你发送了数据以建立通话。 你接听了通话。 你结束了通话。 From 6009578829a215c74c21fd4eca151b95e1572ed2 Mon Sep 17 00:00:00 2001 From: phardyle Date: Fri, 19 Aug 2022 07:25:24 +0000 Subject: [PATCH 068/270] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2330 of 2330 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/ --- vector/src/main/res/values-zh-rCN/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml index cf6e412ad2..d167c76683 100644 --- a/vector/src/main/res/values-zh-rCN/strings.xml +++ b/vector/src/main/res/values-zh-rCN/strings.xml @@ -1409,7 +1409,7 @@ \n \n你也可以通过设置菜单来建立保护备份以及管理你的密钥。 加密已开启 - 本房间信息已经端到端加密。验证成员时,请查看其个人档案以了解更多信息。 + 本房间的消息端到端加密。在成员用户资料中了解更多信息与验证成员。 加密未开启 不支持本房间使用的加密方式 %s 创建并配置了房间。 @@ -1670,7 +1670,7 @@ 手动发布新地址 其它发布的地址: 这是主要地址 - 发布的地址可以被任何服务器上的任何人用来加入你的房间。要发布一个地址,它必须先被设为一个本地地址。 + 任何服务器上的任何人都可用发布的地址加入你的房间。一个地址必须先设置为本地地址才可发布。 发布的地址 查看和管理此房间的地址,以及它在房间目录中的可见性。 房间地址 From 4552a3c68d3f9862efc5282c333c9032959ccae6 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 19 Aug 2022 12:24:45 +0300 Subject: [PATCH 069/270] Add required resources. --- .../main/res/drawable/bg_current_session.xml | 13 +++ .../src/main/res/drawable/bg_device_type.xml | 7 ++ .../res/drawable/ic_device_type_desktop.xml | 9 ++ .../res/drawable/ic_device_type_mobile.xml | 9 ++ .../main/res/drawable/ic_device_type_web.xml | 9 ++ .../main/res/layout/view_current_session.xml | 99 +++++++++++++++++++ 6 files changed, 146 insertions(+) create mode 100644 vector/src/main/res/drawable/bg_current_session.xml create mode 100644 vector/src/main/res/drawable/bg_device_type.xml create mode 100644 vector/src/main/res/drawable/ic_device_type_desktop.xml create mode 100644 vector/src/main/res/drawable/ic_device_type_mobile.xml create mode 100644 vector/src/main/res/drawable/ic_device_type_web.xml create mode 100644 vector/src/main/res/layout/view_current_session.xml diff --git a/vector/src/main/res/drawable/bg_current_session.xml b/vector/src/main/res/drawable/bg_current_session.xml new file mode 100644 index 0000000000..02728b022f --- /dev/null +++ b/vector/src/main/res/drawable/bg_current_session.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/vector/src/main/res/drawable/bg_device_type.xml b/vector/src/main/res/drawable/bg_device_type.xml new file mode 100644 index 0000000000..88a90ccbe6 --- /dev/null +++ b/vector/src/main/res/drawable/bg_device_type.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/vector/src/main/res/drawable/ic_device_type_desktop.xml b/vector/src/main/res/drawable/ic_device_type_desktop.xml new file mode 100644 index 0000000000..2230ee36bd --- /dev/null +++ b/vector/src/main/res/drawable/ic_device_type_desktop.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/drawable/ic_device_type_mobile.xml b/vector/src/main/res/drawable/ic_device_type_mobile.xml new file mode 100644 index 0000000000..fd825c77f0 --- /dev/null +++ b/vector/src/main/res/drawable/ic_device_type_mobile.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/drawable/ic_device_type_web.xml b/vector/src/main/res/drawable/ic_device_type_web.xml new file mode 100644 index 0000000000..722023c96f --- /dev/null +++ b/vector/src/main/res/drawable/ic_device_type_web.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/layout/view_current_session.xml b/vector/src/main/res/layout/view_current_session.xml new file mode 100644 index 0000000000..c3769f532a --- /dev/null +++ b/vector/src/main/res/layout/view_current_session.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + +