mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
Merge remote-tracking branch 'origin/develop' into bugfix/eric/landscape-bottom-sheet-peek
# Conflicts: # vector/src/main/java/im/vector/app/features/home/room/list/home/NewChatBottomSheet.kt
This commit is contained in:
commit
50b042ee98
1
changelog.d/7077.wip
Normal file
1
changelog.d/7077.wip
Normal file
@ -0,0 +1 @@
|
|||||||
|
[Device management] Session details screen
|
1
changelog.d/7102.bugfix
Normal file
1
changelog.d/7102.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Fixes crash when quickly double clicking FABs in the new app layout
|
@ -22,7 +22,7 @@ def markwon = "4.6.2"
|
|||||||
def moshi = "1.13.0"
|
def moshi = "1.13.0"
|
||||||
def lifecycle = "2.5.1"
|
def lifecycle = "2.5.1"
|
||||||
def flowBinding = "1.2.0"
|
def flowBinding = "1.2.0"
|
||||||
def flipper = "0.163.0"
|
def flipper = "0.164.0"
|
||||||
def epoxy = "4.6.2"
|
def epoxy = "4.6.2"
|
||||||
def mavericks = "2.7.0"
|
def mavericks = "2.7.0"
|
||||||
def glide = "4.13.2"
|
def glide = "4.13.2"
|
||||||
|
@ -320,7 +320,7 @@
|
|||||||
<string name="settings_theme">السمة</string>
|
<string name="settings_theme">السمة</string>
|
||||||
<string name="encryption_information_decryption_error">خطأ في فكّ التعمية</string>
|
<string name="encryption_information_decryption_error">خطأ في فكّ التعمية</string>
|
||||||
<string name="encryption_information_device_name">اسم الجهاز</string>
|
<string name="encryption_information_device_name">اسم الجهاز</string>
|
||||||
<string name="encryption_information_device_id">معرّف الجهاز</string>
|
<string name="device_manager_session_details_session_id">معرّف الجهاز</string>
|
||||||
<string name="encryption_information_device_key">مفتاح الجهاز</string>
|
<string name="encryption_information_device_key">مفتاح الجهاز</string>
|
||||||
<string name="encryption_export_room_keys">صدّر مفاتيح الغرفة</string>
|
<string name="encryption_export_room_keys">صدّر مفاتيح الغرفة</string>
|
||||||
<string name="encryption_export_room_keys_summary">صدّر المفاتيح إلى ملف محلي</string>
|
<string name="encryption_export_room_keys_summary">صدّر المفاتيح إلى ملف محلي</string>
|
||||||
|
@ -396,7 +396,7 @@
|
|||||||
<string name="settings_theme">Тема</string>
|
<string name="settings_theme">Тема</string>
|
||||||
<string name="encryption_information_decryption_error">Грешка при разшифроване</string>
|
<string name="encryption_information_decryption_error">Грешка при разшифроване</string>
|
||||||
<string name="encryption_information_device_name">Публично име</string>
|
<string name="encryption_information_device_name">Публично име</string>
|
||||||
<string name="encryption_information_device_id">Сесийно ID</string>
|
<string name="device_manager_session_details_session_id">Сесийно ID</string>
|
||||||
<string name="encryption_information_device_key">Ключ на устройство</string>
|
<string name="encryption_information_device_key">Ключ на устройство</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Експортирай E2E ключове за стая</string>
|
<string name="encryption_export_e2e_room_keys">Експортирай E2E ключове за стая</string>
|
||||||
<string name="encryption_export_room_keys">Експортиране на ключове за стая</string>
|
<string name="encryption_export_room_keys">Експортиране на ключове за стая</string>
|
||||||
|
@ -789,7 +789,7 @@
|
|||||||
<string name="encryption_export_room_keys">রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
<string name="encryption_export_room_keys">রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
||||||
<string name="encryption_export_e2e_room_keys">শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
<string name="encryption_export_e2e_room_keys">শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
||||||
<string name="encryption_information_device_key">সেশানের কুঞ্জি</string>
|
<string name="encryption_information_device_key">সেশানের কুঞ্জি</string>
|
||||||
<string name="encryption_information_device_id">আইডি</string>
|
<string name="device_manager_session_details_session_id">আইডি</string>
|
||||||
<string name="encryption_information_device_name">সর্বজনীন নাম</string>
|
<string name="encryption_information_device_name">সর্বজনীন নাম</string>
|
||||||
<string name="encryption_information_decryption_error">ডিক্রিপশন সমস্যা</string>
|
<string name="encryption_information_decryption_error">ডিক্রিপশন সমস্যা</string>
|
||||||
<string name="settings_theme">থিম</string>
|
<string name="settings_theme">থিম</string>
|
||||||
|
@ -693,7 +693,7 @@
|
|||||||
<string name="encryption_information_decryption_error">ডিক্রিপশন সমস্যা</string>
|
<string name="encryption_information_decryption_error">ডিক্রিপশন সমস্যা</string>
|
||||||
|
|
||||||
<string name="encryption_information_device_name">সর্বজনীন নাম</string>
|
<string name="encryption_information_device_name">সর্বজনীন নাম</string>
|
||||||
<string name="encryption_information_device_id">আইডি</string>
|
<string name="device_manager_session_details_session_id">আইডি</string>
|
||||||
<string name="encryption_information_device_key">সেশানের কুঞ্জি</string>
|
<string name="encryption_information_device_key">সেশানের কুঞ্জি</string>
|
||||||
|
|
||||||
<string name="encryption_export_e2e_room_keys">শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
<string name="encryption_export_e2e_room_keys">শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
||||||
|
@ -448,7 +448,7 @@
|
|||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
<string name="encryption_information_decryption_error">Error al desxifrar</string>
|
<string name="encryption_information_decryption_error">Error al desxifrar</string>
|
||||||
<string name="encryption_information_device_name">Nom públic</string>
|
<string name="encryption_information_device_name">Nom públic</string>
|
||||||
<string name="encryption_information_device_id">ID de sessió</string>
|
<string name="device_manager_session_details_session_id">ID de sessió</string>
|
||||||
<string name="encryption_information_device_key">Clau de sessió</string>
|
<string name="encryption_information_device_key">Clau de sessió</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exporta les claus de la sala E2E</string>
|
<string name="encryption_export_e2e_room_keys">Exporta les claus de la sala E2E</string>
|
||||||
<string name="encryption_export_room_keys">Exporta les claus de la sala</string>
|
<string name="encryption_export_room_keys">Exporta les claus de la sala</string>
|
||||||
|
@ -635,7 +635,7 @@
|
|||||||
<string name="settings_theme">Motiv vzhledu</string>
|
<string name="settings_theme">Motiv vzhledu</string>
|
||||||
<string name="encryption_information_decryption_error">Chyba dešifrování</string>
|
<string name="encryption_information_decryption_error">Chyba dešifrování</string>
|
||||||
<string name="encryption_information_device_name">Veřejné jméno</string>
|
<string name="encryption_information_device_name">Veřejné jméno</string>
|
||||||
<string name="encryption_information_device_id">ID relace</string>
|
<string name="device_manager_session_details_session_id">ID relace</string>
|
||||||
<string name="encryption_information_device_key">Klíč relace</string>
|
<string name="encryption_information_device_key">Klíč relace</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Export E2E klíčů místností</string>
|
<string name="encryption_export_e2e_room_keys">Export E2E klíčů místností</string>
|
||||||
<string name="encryption_export_room_keys">Export klíčů místností</string>
|
<string name="encryption_export_room_keys">Export klíčů místností</string>
|
||||||
|
@ -418,7 +418,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Als Hauptadresse aufheben</string>
|
<string name="room_settings_unset_main_address">Als Hauptadresse aufheben</string>
|
||||||
<string name="encryption_information_decryption_error">Entschlüsselungsfehler</string>
|
<string name="encryption_information_decryption_error">Entschlüsselungsfehler</string>
|
||||||
<string name="encryption_information_device_name">Öffentlicher Name</string>
|
<string name="encryption_information_device_name">Öffentlicher Name</string>
|
||||||
<string name="encryption_information_device_id">Sitzungs-ID</string>
|
<string name="device_manager_session_details_session_id">Sitzungs-ID</string>
|
||||||
<string name="encryption_information_device_key">Sitzungsschlüssel</string>
|
<string name="encryption_information_device_key">Sitzungsschlüssel</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Ende-zu-Ende-Raumschlüssel exportieren</string>
|
<string name="encryption_export_e2e_room_keys">Ende-zu-Ende-Raumschlüssel exportieren</string>
|
||||||
<string name="encryption_export_room_keys">Raumschlüssel exportieren</string>
|
<string name="encryption_export_room_keys">Raumschlüssel exportieren</string>
|
||||||
@ -2622,4 +2622,4 @@
|
|||||||
<string name="device_manager_other_sessions_description_unverified">Nicht verifiziert · Letzte Aktivität %1$s</string>
|
<string name="device_manager_other_sessions_description_unverified">Nicht verifiziert · Letzte Aktivität %1$s</string>
|
||||||
<string name="device_manager_verification_status_detail_unverified">Verifiziere deine aktuelle Sitzung für besonders sichere Nachrichtenübertragung.</string>
|
<string name="device_manager_verification_status_detail_unverified">Verifiziere deine aktuelle Sitzung für besonders sichere Nachrichtenübertragung.</string>
|
||||||
<string name="device_manager_verification_status_unverified">Nicht verifizierte Sitzung</string>
|
<string name="device_manager_verification_status_unverified">Nicht verifizierte Sitzung</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -172,7 +172,7 @@
|
|||||||
<string name="settings_theme">Θέμα</string>
|
<string name="settings_theme">Θέμα</string>
|
||||||
<string name="encryption_information_decryption_error">Σφάλμα αποκρυπτογράφησης</string>
|
<string name="encryption_information_decryption_error">Σφάλμα αποκρυπτογράφησης</string>
|
||||||
<string name="encryption_information_device_name">Όνομα συσκευής</string>
|
<string name="encryption_information_device_name">Όνομα συσκευής</string>
|
||||||
<string name="encryption_information_device_id">Αναγνωριστικό συσκευής</string>
|
<string name="device_manager_session_details_session_id">Αναγνωριστικό συσκευής</string>
|
||||||
<string name="encryption_export_export">Εξαγωγή</string>
|
<string name="encryption_export_export">Εξαγωγή</string>
|
||||||
<string name="encryption_import_import">Εισαγωγή</string>
|
<string name="encryption_import_import">Εισαγωγή</string>
|
||||||
<string name="select_room_directory">Επιλέξτε ένα ευρετήριο δωματίων</string>
|
<string name="select_room_directory">Επιλέξτε ένα ευρετήριο δωματίων</string>
|
||||||
|
@ -1084,7 +1084,7 @@
|
|||||||
<string name="encryption_export_room_keys">Elporti ŝlosilojn de ĉambroj</string>
|
<string name="encryption_export_room_keys">Elporti ŝlosilojn de ĉambroj</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Elporti tutvoje ĉifrajn ŝlosilojn de ĉambroj</string>
|
<string name="encryption_export_e2e_room_keys">Elporti tutvoje ĉifrajn ŝlosilojn de ĉambroj</string>
|
||||||
<string name="encryption_information_device_key">Ŝlosilo de salutaĵo</string>
|
<string name="encryption_information_device_key">Ŝlosilo de salutaĵo</string>
|
||||||
<string name="encryption_information_device_id">Identigilo de salutaĵo</string>
|
<string name="device_manager_session_details_session_id">Identigilo de salutaĵo</string>
|
||||||
<string name="encryption_information_device_name">Publika nomo</string>
|
<string name="encryption_information_device_name">Publika nomo</string>
|
||||||
<string name="encryption_information_decryption_error">Eraris malĉifrado</string>
|
<string name="encryption_information_decryption_error">Eraris malĉifrado</string>
|
||||||
<string name="settings_theme">Haŭto</string>
|
<string name="settings_theme">Haŭto</string>
|
||||||
|
@ -249,7 +249,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Desescojer como Dirección Principal</string>
|
<string name="room_settings_unset_main_address">Desescojer como Dirección Principal</string>
|
||||||
<string name="encryption_information_decryption_error">Error en descifrar</string>
|
<string name="encryption_information_decryption_error">Error en descifrar</string>
|
||||||
<string name="encryption_information_device_name">Nombre del dispositivo</string>
|
<string name="encryption_information_device_name">Nombre del dispositivo</string>
|
||||||
<string name="encryption_information_device_id">Identificación del dispositivo</string>
|
<string name="device_manager_session_details_session_id">Identificación del dispositivo</string>
|
||||||
<string name="encryption_information_device_key">Clave del dispositivo</string>
|
<string name="encryption_information_device_key">Clave del dispositivo</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exportar claves de cifrado de extremo-a-extremo de salas</string>
|
<string name="encryption_export_e2e_room_keys">Exportar claves de cifrado de extremo-a-extremo de salas</string>
|
||||||
<string name="encryption_export_room_keys">Exportar claves de salas</string>
|
<string name="encryption_export_room_keys">Exportar claves de salas</string>
|
||||||
|
@ -415,7 +415,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Dejar de Establecer como dirección principal</string>
|
<string name="room_settings_unset_main_address">Dejar de Establecer como dirección principal</string>
|
||||||
<string name="encryption_information_decryption_error">Error de descifrado</string>
|
<string name="encryption_information_decryption_error">Error de descifrado</string>
|
||||||
<string name="encryption_information_device_name">Nombre público</string>
|
<string name="encryption_information_device_name">Nombre público</string>
|
||||||
<string name="encryption_information_device_id">ID de sesión</string>
|
<string name="device_manager_session_details_session_id">ID de sesión</string>
|
||||||
<string name="encryption_information_device_key">Clave de sesión</string>
|
<string name="encryption_information_device_key">Clave de sesión</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exportar claves de salas con cifrado Extremo-a-Extremo</string>
|
<string name="encryption_export_e2e_room_keys">Exportar claves de salas con cifrado Extremo-a-Extremo</string>
|
||||||
<string name="encryption_export_room_keys">Exportar claves de sala</string>
|
<string name="encryption_export_room_keys">Exportar claves de sala</string>
|
||||||
|
@ -612,7 +612,7 @@
|
|||||||
<string name="room_settings_labs_warning_message">Need on alles katsejärgus olevad funktsionaalsused. Ole kasutamisel ettevaatlik.</string>
|
<string name="room_settings_labs_warning_message">Need on alles katsejärgus olevad funktsionaalsused. Ole kasutamisel ettevaatlik.</string>
|
||||||
<string name="encryption_information_decryption_error">Dekrüptimise viga</string>
|
<string name="encryption_information_decryption_error">Dekrüptimise viga</string>
|
||||||
<string name="encryption_information_device_name">Avalik nimi</string>
|
<string name="encryption_information_device_name">Avalik nimi</string>
|
||||||
<string name="encryption_information_device_id">Sessiooni tunnus</string>
|
<string name="device_manager_session_details_session_id">Sessiooni tunnus</string>
|
||||||
<string name="encryption_information_device_key">Sessiooni võti</string>
|
<string name="encryption_information_device_key">Sessiooni võti</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Ekspordi jututubade läbiva krüptimise võtmed</string>
|
<string name="encryption_export_e2e_room_keys">Ekspordi jututubade läbiva krüptimise võtmed</string>
|
||||||
<string name="encryption_export_room_keys">Ekspordi jututoa võtmed</string>
|
<string name="encryption_export_room_keys">Ekspordi jututoa võtmed</string>
|
||||||
|
@ -406,7 +406,7 @@ Kontuan izan ekintza honek aplikazioa berrabiaraziko duela eta denbora bat behar
|
|||||||
<string name="encryption_information_decryption_error">Deszifratze errorea</string>
|
<string name="encryption_information_decryption_error">Deszifratze errorea</string>
|
||||||
|
|
||||||
<string name="encryption_information_device_name">Izen publikoa</string>
|
<string name="encryption_information_device_name">Izen publikoa</string>
|
||||||
<string name="encryption_information_device_id">IDa</string>
|
<string name="device_manager_session_details_session_id">IDa</string>
|
||||||
<string name="encryption_information_device_key">Saioaren gakoa</string>
|
<string name="encryption_information_device_key">Saioaren gakoa</string>
|
||||||
|
|
||||||
<string name="encryption_export_e2e_room_keys">Esportatu E2E geletako gakoak</string>
|
<string name="encryption_export_e2e_room_keys">Esportatu E2E geletako gakoak</string>
|
||||||
|
@ -678,7 +678,7 @@
|
|||||||
<string name="room_settings_labs_warning_message">اینها ویژگیهای آزمایشیای هستند که ممکن است به روشهای نامنتظرهای حراب شوندا. با احتیاط استفاده کنید.</string>
|
<string name="room_settings_labs_warning_message">اینها ویژگیهای آزمایشیای هستند که ممکن است به روشهای نامنتظرهای حراب شوندا. با احتیاط استفاده کنید.</string>
|
||||||
<string name="room_settings_set_main_address">تنظیم به عنوان نشانی اصلی</string>
|
<string name="room_settings_set_main_address">تنظیم به عنوان نشانی اصلی</string>
|
||||||
<string name="encryption_information_device_name">نام عمومی</string>
|
<string name="encryption_information_device_name">نام عمومی</string>
|
||||||
<string name="encryption_information_device_id">شناسهٔ نشست</string>
|
<string name="device_manager_session_details_session_id">شناسهٔ نشست</string>
|
||||||
<string name="encryption_information_device_key">کلید نشست</string>
|
<string name="encryption_information_device_key">کلید نشست</string>
|
||||||
<string name="encryption_export_e2e_room_keys">برونریزی کلیدهای اتاقهای سرتاسری</string>
|
<string name="encryption_export_e2e_room_keys">برونریزی کلیدهای اتاقهای سرتاسری</string>
|
||||||
<string name="encryption_export_room_keys">برونریزی کلیدهای اتاقها</string>
|
<string name="encryption_export_room_keys">برونریزی کلیدهای اتاقها</string>
|
||||||
|
@ -366,7 +366,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Kumoa pääosoitteeksi asettaminen</string>
|
<string name="room_settings_unset_main_address">Kumoa pääosoitteeksi asettaminen</string>
|
||||||
<string name="encryption_information_decryption_error">Salauksenpurkuvirhe</string>
|
<string name="encryption_information_decryption_error">Salauksenpurkuvirhe</string>
|
||||||
<string name="encryption_information_device_name">Julkinen nimi</string>
|
<string name="encryption_information_device_name">Julkinen nimi</string>
|
||||||
<string name="encryption_information_device_id">Istunnon tunnus</string>
|
<string name="device_manager_session_details_session_id">Istunnon tunnus</string>
|
||||||
<string name="encryption_information_device_key">Istunnon avain</string>
|
<string name="encryption_information_device_key">Istunnon avain</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Vie salatun huoneen avaimet</string>
|
<string name="encryption_export_e2e_room_keys">Vie salatun huoneen avaimet</string>
|
||||||
<string name="encryption_export_room_keys">Vie huoneen avaimet</string>
|
<string name="encryption_export_room_keys">Vie huoneen avaimet</string>
|
||||||
|
@ -778,7 +778,7 @@
|
|||||||
<string name="encryption_export_room_keys">Exporter les clés des salons</string>
|
<string name="encryption_export_room_keys">Exporter les clés des salons</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exporter les clés E2E des salons</string>
|
<string name="encryption_export_e2e_room_keys">Exporter les clés E2E des salons</string>
|
||||||
<string name="encryption_information_device_key">Clé de la session</string>
|
<string name="encryption_information_device_key">Clé de la session</string>
|
||||||
<string name="encryption_information_device_id">Identifiant de session</string>
|
<string name="device_manager_session_details_session_id">Identifiant de session</string>
|
||||||
<string name="encryption_information_device_name">Nom public</string>
|
<string name="encryption_information_device_name">Nom public</string>
|
||||||
<string name="encryption_information_decryption_error">Erreur de déchiffrement</string>
|
<string name="encryption_information_decryption_error">Erreur de déchiffrement</string>
|
||||||
<string name="settings_theme">Thème</string>
|
<string name="settings_theme">Thème</string>
|
||||||
|
@ -346,7 +346,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Désactiver comme adresse principale</string>
|
<string name="room_settings_unset_main_address">Désactiver comme adresse principale</string>
|
||||||
<string name="encryption_information_decryption_error">Erreur de déchiffrement</string>
|
<string name="encryption_information_decryption_error">Erreur de déchiffrement</string>
|
||||||
<string name="encryption_information_device_name">Nom public</string>
|
<string name="encryption_information_device_name">Nom public</string>
|
||||||
<string name="encryption_information_device_id">Identifiant de session</string>
|
<string name="device_manager_session_details_session_id">Identifiant de session</string>
|
||||||
<string name="encryption_information_device_key">Clé de la session</string>
|
<string name="encryption_information_device_key">Clé de la session</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exporter les clés E2E des salons</string>
|
<string name="encryption_export_e2e_room_keys">Exporter les clés E2E des salons</string>
|
||||||
<string name="encryption_export_room_keys">Exporter les clés des salons</string>
|
<string name="encryption_export_room_keys">Exporter les clés des salons</string>
|
||||||
|
@ -380,7 +380,7 @@
|
|||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
<string name="encryption_information_decryption_error">Fallo ao descifrar</string>
|
<string name="encryption_information_decryption_error">Fallo ao descifrar</string>
|
||||||
<string name="encryption_information_device_name">Nome do dispositivo</string>
|
<string name="encryption_information_device_name">Nome do dispositivo</string>
|
||||||
<string name="encryption_information_device_id">ID de sesión</string>
|
<string name="device_manager_session_details_session_id">ID de sesión</string>
|
||||||
<string name="encryption_information_device_key">Chave do dispositivo</string>
|
<string name="encryption_information_device_key">Chave do dispositivo</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exportar chaves E2E da sala</string>
|
<string name="encryption_export_e2e_room_keys">Exportar chaves E2E da sala</string>
|
||||||
<string name="encryption_export_room_keys">Exportar chaves da sala</string>
|
<string name="encryption_export_room_keys">Exportar chaves da sala</string>
|
||||||
|
@ -572,7 +572,7 @@
|
|||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
<string name="encryption_information_decryption_error">Greška u dešifriranju</string>
|
<string name="encryption_information_decryption_error">Greška u dešifriranju</string>
|
||||||
<string name="encryption_information_device_name">Javni naziv</string>
|
<string name="encryption_information_device_name">Javni naziv</string>
|
||||||
<string name="encryption_information_device_id">Identitet</string>
|
<string name="device_manager_session_details_session_id">Identitet</string>
|
||||||
<string name="encryption_information_device_key">Ključ sesije</string>
|
<string name="encryption_information_device_key">Ključ sesije</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Izvezi sobne ključeve za E2E</string>
|
<string name="encryption_export_e2e_room_keys">Izvezi sobne ključeve za E2E</string>
|
||||||
<string name="encryption_export_room_keys">Izvezi sobne ključeve</string>
|
<string name="encryption_export_room_keys">Izvezi sobne ključeve</string>
|
||||||
|
@ -351,7 +351,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Kiszedés fő címek közül</string>
|
<string name="room_settings_unset_main_address">Kiszedés fő címek közül</string>
|
||||||
<string name="encryption_information_decryption_error">Visszafejtés hiba</string>
|
<string name="encryption_information_decryption_error">Visszafejtés hiba</string>
|
||||||
<string name="encryption_information_device_name">Nyilvános név</string>
|
<string name="encryption_information_device_name">Nyilvános név</string>
|
||||||
<string name="encryption_information_device_id">Munkamenet-azonosító</string>
|
<string name="device_manager_session_details_session_id">Munkamenet-azonosító</string>
|
||||||
<string name="encryption_information_device_key">Munkamenet kulcs</string>
|
<string name="encryption_information_device_key">Munkamenet kulcs</string>
|
||||||
<string name="encryption_export_e2e_room_keys">E2E szoba kulcsok exportálása</string>
|
<string name="encryption_export_e2e_room_keys">E2E szoba kulcsok exportálása</string>
|
||||||
<string name="encryption_export_room_keys">Szoba kulcsok exportálása</string>
|
<string name="encryption_export_room_keys">Szoba kulcsok exportálása</string>
|
||||||
|
@ -301,7 +301,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan.</string>
|
|||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
<string name="encryption_information_decryption_error">Kesalahan dekripsi</string>
|
<string name="encryption_information_decryption_error">Kesalahan dekripsi</string>
|
||||||
<string name="encryption_information_device_name">Nama perangkat</string>
|
<string name="encryption_information_device_name">Nama perangkat</string>
|
||||||
<string name="encryption_information_device_id">ID Sesi</string>
|
<string name="device_manager_session_details_session_id">ID Sesi</string>
|
||||||
<string name="encryption_information_device_key">Kunci perangkat</string>
|
<string name="encryption_information_device_key">Kunci perangkat</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Ekspor kunci ruangan terenkripsi</string>
|
<string name="encryption_export_e2e_room_keys">Ekspor kunci ruangan terenkripsi</string>
|
||||||
<string name="encryption_export_room_keys">Ekspor ruangan kunci</string>
|
<string name="encryption_export_room_keys">Ekspor ruangan kunci</string>
|
||||||
|
@ -193,7 +193,7 @@
|
|||||||
<string name="settings_theme">Þema</string>
|
<string name="settings_theme">Þema</string>
|
||||||
<string name="encryption_information_decryption_error">Afkóðunarvilla</string>
|
<string name="encryption_information_decryption_error">Afkóðunarvilla</string>
|
||||||
<string name="encryption_information_device_name">Heiti tækis</string>
|
<string name="encryption_information_device_name">Heiti tækis</string>
|
||||||
<string name="encryption_information_device_id">Auðkenni setu</string>
|
<string name="device_manager_session_details_session_id">Auðkenni setu</string>
|
||||||
<string name="encryption_information_device_key">Dulritunarlykill setu</string>
|
<string name="encryption_information_device_key">Dulritunarlykill setu</string>
|
||||||
<string name="encryption_export_export">Flytja út</string>
|
<string name="encryption_export_export">Flytja út</string>
|
||||||
<string name="passphrase_enter_passphrase">Settu inn lykilsetningu</string>
|
<string name="passphrase_enter_passphrase">Settu inn lykilsetningu</string>
|
||||||
|
@ -430,7 +430,7 @@
|
|||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
<string name="encryption_information_decryption_error">Errore di decriptazione</string>
|
<string name="encryption_information_decryption_error">Errore di decriptazione</string>
|
||||||
<string name="encryption_information_device_name">Nome pubblico</string>
|
<string name="encryption_information_device_name">Nome pubblico</string>
|
||||||
<string name="encryption_information_device_id">ID sessione</string>
|
<string name="device_manager_session_details_session_id">ID sessione</string>
|
||||||
<string name="encryption_information_device_key">Chiave sessione</string>
|
<string name="encryption_information_device_key">Chiave sessione</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Esporta le chiavi di crittografia E2E delle stanze</string>
|
<string name="encryption_export_e2e_room_keys">Esporta le chiavi di crittografia E2E delle stanze</string>
|
||||||
<string name="encryption_export_room_keys">Esporta le chiavi delle stanze</string>
|
<string name="encryption_export_room_keys">Esporta le chiavi delle stanze</string>
|
||||||
|
@ -542,7 +542,7 @@
|
|||||||
<string name="encryption_export_room_keys">יצא מפתחות חדר</string>
|
<string name="encryption_export_room_keys">יצא מפתחות חדר</string>
|
||||||
<string name="encryption_export_e2e_room_keys">ייצא מפתחות חדר E2E</string>
|
<string name="encryption_export_e2e_room_keys">ייצא מפתחות חדר E2E</string>
|
||||||
<string name="encryption_information_device_key">מזהה מפתח</string>
|
<string name="encryption_information_device_key">מזהה מפתח</string>
|
||||||
<string name="encryption_information_device_id">מזהה מושב</string>
|
<string name="device_manager_session_details_session_id">מזהה מושב</string>
|
||||||
<string name="encryption_information_device_name">שם ציבורי</string>
|
<string name="encryption_information_device_name">שם ציבורי</string>
|
||||||
<string name="encryption_information_decryption_error">שגיאת פענוח</string>
|
<string name="encryption_information_decryption_error">שגיאת פענוח</string>
|
||||||
<string name="settings_theme">ערכת נושא</string>
|
<string name="settings_theme">ערכת נושא</string>
|
||||||
|
@ -197,7 +197,7 @@
|
|||||||
<string name="room_settings_labs_warning_message">これらは予期しない不具合が生じるかもしれない実験的機能です。慎重に使用してください。</string>
|
<string name="room_settings_labs_warning_message">これらは予期しない不具合が生じるかもしれない実験的機能です。慎重に使用してください。</string>
|
||||||
<string name="room_settings_set_main_address">メインアドレスとして設定</string>
|
<string name="room_settings_set_main_address">メインアドレスとして設定</string>
|
||||||
<string name="room_settings_unset_main_address">メインアドレスとしての設定を解除</string>
|
<string name="room_settings_unset_main_address">メインアドレスとしての設定を解除</string>
|
||||||
<string name="encryption_information_device_id">セッションID</string>
|
<string name="device_manager_session_details_session_id">セッションID</string>
|
||||||
<string name="font_size">文字の大きさ</string>
|
<string name="font_size">文字の大きさ</string>
|
||||||
<string name="tiny">とても小さい</string>
|
<string name="tiny">とても小さい</string>
|
||||||
<string name="small">小さい</string>
|
<string name="small">小さい</string>
|
||||||
|
@ -291,7 +291,7 @@
|
|||||||
<string name="room_settings_category_advanced_title">Talqayt</string>
|
<string name="room_settings_category_advanced_title">Talqayt</string>
|
||||||
<string name="room_settings_labs_pref_title">Tinarimin</string>
|
<string name="room_settings_labs_pref_title">Tinarimin</string>
|
||||||
<string name="settings_theme">Asentel</string>
|
<string name="settings_theme">Asentel</string>
|
||||||
<string name="encryption_information_device_id">Asulay n tqimit</string>
|
<string name="device_manager_session_details_session_id">Asulay n tqimit</string>
|
||||||
<string name="encryption_information_device_key">Tasarut n tɣimit</string>
|
<string name="encryption_information_device_key">Tasarut n tɣimit</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Sifeḍ tisura n texxamt E2E</string>
|
<string name="encryption_export_e2e_room_keys">Sifeḍ tisura n texxamt E2E</string>
|
||||||
<string name="encryption_export_room_keys">Sifeḍ tisura n texxamt</string>
|
<string name="encryption_export_room_keys">Sifeḍ tisura n texxamt</string>
|
||||||
|
@ -431,7 +431,7 @@
|
|||||||
<string name="settings_theme">테마</string>
|
<string name="settings_theme">테마</string>
|
||||||
<string name="encryption_information_decryption_error">암호 복호화 오류</string>
|
<string name="encryption_information_decryption_error">암호 복호화 오류</string>
|
||||||
<string name="encryption_information_device_name">공개 이름</string>
|
<string name="encryption_information_device_name">공개 이름</string>
|
||||||
<string name="encryption_information_device_id">ID</string>
|
<string name="device_manager_session_details_session_id">ID</string>
|
||||||
<string name="encryption_information_device_key">기기 키</string>
|
<string name="encryption_information_device_key">기기 키</string>
|
||||||
<string name="encryption_export_e2e_room_keys">종단간 암호화 방 키 내보내기</string>
|
<string name="encryption_export_e2e_room_keys">종단간 암호화 방 키 내보내기</string>
|
||||||
<string name="encryption_export_room_keys">방 키 내보내기</string>
|
<string name="encryption_export_room_keys">방 키 내보내기</string>
|
||||||
|
@ -909,7 +909,7 @@
|
|||||||
<string name="encryption_export_room_keys">ສົ່ງອອກກະແຈຫ້ອງ</string>
|
<string name="encryption_export_room_keys">ສົ່ງອອກກະແຈຫ້ອງ</string>
|
||||||
<string name="encryption_export_e2e_room_keys">ສົ່ງອອກກະແຈຫ້ອງ E2E</string>
|
<string name="encryption_export_e2e_room_keys">ສົ່ງອອກກະແຈຫ້ອງ E2E</string>
|
||||||
<string name="encryption_information_device_key">ລະຫັດລະບົບ</string>
|
<string name="encryption_information_device_key">ລະຫັດລະບົບ</string>
|
||||||
<string name="encryption_information_device_id">ID ລະບົບ</string>
|
<string name="device_manager_session_details_session_id">ID ລະບົບ</string>
|
||||||
<string name="encryption_information_device_name">ຊື່ສາທາລະນະ</string>
|
<string name="encryption_information_device_name">ຊື່ສາທາລະນະ</string>
|
||||||
<string name="encryption_information_decryption_error">ການຖອດລະຫັດຜິດພາດ</string>
|
<string name="encryption_information_decryption_error">ການຖອດລະຫັດຜິດພາດ</string>
|
||||||
<string name="settings_theme">ຫົວຂໍ້</string>
|
<string name="settings_theme">ຫົວຂໍ້</string>
|
||||||
|
@ -469,7 +469,7 @@
|
|||||||
<string name="settings_theme">Tēma</string>
|
<string name="settings_theme">Tēma</string>
|
||||||
<string name="encryption_information_decryption_error">Atšifrēšanas kļūda</string>
|
<string name="encryption_information_decryption_error">Atšifrēšanas kļūda</string>
|
||||||
<string name="encryption_information_device_name">Ierīces nosaukums</string>
|
<string name="encryption_information_device_name">Ierīces nosaukums</string>
|
||||||
<string name="encryption_information_device_id">Sesijas ID</string>
|
<string name="device_manager_session_details_session_id">Sesijas ID</string>
|
||||||
<string name="encryption_information_device_key">Sesijas atslēga</string>
|
<string name="encryption_information_device_key">Sesijas atslēga</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Eksportēt istabas šifrēšanas atslēgas</string>
|
<string name="encryption_export_e2e_room_keys">Eksportēt istabas šifrēšanas atslēgas</string>
|
||||||
<string name="encryption_export_room_keys">Eksportēt istabas atslēgas</string>
|
<string name="encryption_export_room_keys">Eksportēt istabas atslēgas</string>
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
<string name="room_settings_banned_users_title">Bannlyste brukere</string>
|
<string name="room_settings_banned_users_title">Bannlyste brukere</string>
|
||||||
<string name="room_settings_category_advanced_title">Avansert</string>
|
<string name="room_settings_category_advanced_title">Avansert</string>
|
||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
<string name="encryption_information_device_id">Økt-ID</string>
|
<string name="device_manager_session_details_session_id">Økt-ID</string>
|
||||||
<string name="encryption_information_device_key">Øktnøkkel</string>
|
<string name="encryption_information_device_key">Øktnøkkel</string>
|
||||||
<string name="encryption_export_export">Eksporter</string>
|
<string name="encryption_export_export">Eksporter</string>
|
||||||
<string name="encryption_import_import">Importer</string>
|
<string name="encryption_import_import">Importer</string>
|
||||||
|
@ -275,7 +275,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Niet instellen als hoofdadres</string>
|
<string name="room_settings_unset_main_address">Niet instellen als hoofdadres</string>
|
||||||
<string name="encryption_information_decryption_error">Ontsleutelingsfout</string>
|
<string name="encryption_information_decryption_error">Ontsleutelingsfout</string>
|
||||||
<string name="encryption_information_device_name">Publieke naam</string>
|
<string name="encryption_information_device_name">Publieke naam</string>
|
||||||
<string name="encryption_information_device_id">Sessie ID</string>
|
<string name="device_manager_session_details_session_id">Sessie ID</string>
|
||||||
<string name="encryption_information_device_key">Sessiesleutel</string>
|
<string name="encryption_information_device_key">Sessiesleutel</string>
|
||||||
<string name="encryption_export_e2e_room_keys">E2E-gesprekssleutels exporteren</string>
|
<string name="encryption_export_e2e_room_keys">E2E-gesprekssleutels exporteren</string>
|
||||||
<string name="encryption_export_room_keys">Gesprekssleutels exporteren</string>
|
<string name="encryption_export_room_keys">Gesprekssleutels exporteren</string>
|
||||||
|
@ -310,7 +310,7 @@
|
|||||||
<string name="settings_theme">Preg</string>
|
<string name="settings_theme">Preg</string>
|
||||||
<string name="encryption_information_decryption_error">Noko gjekk gale med dekrypteringa</string>
|
<string name="encryption_information_decryption_error">Noko gjekk gale med dekrypteringa</string>
|
||||||
<string name="encryption_information_device_name">Offentleg namn</string>
|
<string name="encryption_information_device_name">Offentleg namn</string>
|
||||||
<string name="encryption_information_device_id">Økt-ID</string>
|
<string name="device_manager_session_details_session_id">Økt-ID</string>
|
||||||
<string name="encryption_information_device_key">Sesjonsnøkkel</string>
|
<string name="encryption_information_device_key">Sesjonsnøkkel</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Eksporter E2E-romnøkklar</string>
|
<string name="encryption_export_e2e_room_keys">Eksporter E2E-romnøkklar</string>
|
||||||
<string name="encryption_export_room_keys">Eksporter romnøkklar</string>
|
<string name="encryption_export_room_keys">Eksporter romnøkklar</string>
|
||||||
|
@ -231,7 +231,7 @@
|
|||||||
<string name="room_settings_set_main_address">Ustaw jako główny adres</string>
|
<string name="room_settings_set_main_address">Ustaw jako główny adres</string>
|
||||||
<string name="settings_theme">Motyw</string>
|
<string name="settings_theme">Motyw</string>
|
||||||
<string name="encryption_information_device_name">Nazwa publiczna</string>
|
<string name="encryption_information_device_name">Nazwa publiczna</string>
|
||||||
<string name="encryption_information_device_id">ID sesji</string>
|
<string name="device_manager_session_details_session_id">ID sesji</string>
|
||||||
<string name="encryption_export_export">Eksportuj</string>
|
<string name="encryption_export_export">Eksportuj</string>
|
||||||
<string name="passphrase_enter_passphrase">Wprowadź hasło</string>
|
<string name="passphrase_enter_passphrase">Wprowadź hasło</string>
|
||||||
<string name="passphrase_confirm_passphrase">Potwierdź hasło</string>
|
<string name="passphrase_confirm_passphrase">Potwierdź hasło</string>
|
||||||
@ -2734,4 +2734,4 @@
|
|||||||
<string name="timeline_error_room_not_found">Niestety, ten pokój nie został znaleziony.
|
<string name="timeline_error_room_not_found">Niestety, ten pokój nie został znaleziony.
|
||||||
\nSpróbuj ponownie później.%s</string>
|
\nSpróbuj ponownie później.%s</string>
|
||||||
<string name="invites_title">Zaproszenia</string>
|
<string name="invites_title">Zaproszenia</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -418,7 +418,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Des-definir como endereço principal</string>
|
<string name="room_settings_unset_main_address">Des-definir como endereço principal</string>
|
||||||
<string name="encryption_information_decryption_error">Erro de decriptação</string>
|
<string name="encryption_information_decryption_error">Erro de decriptação</string>
|
||||||
<string name="encryption_information_device_name">Nome público</string>
|
<string name="encryption_information_device_name">Nome público</string>
|
||||||
<string name="encryption_information_device_id">ID de sessão</string>
|
<string name="device_manager_session_details_session_id">ID de sessão</string>
|
||||||
<string name="encryption_information_device_key">Chave de sessão</string>
|
<string name="encryption_information_device_key">Chave de sessão</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exportar chaves de sala E2E</string>
|
<string name="encryption_export_e2e_room_keys">Exportar chaves de sala E2E</string>
|
||||||
<string name="encryption_export_room_keys">Exportar chaves de sala</string>
|
<string name="encryption_export_room_keys">Exportar chaves de sala</string>
|
||||||
|
@ -246,7 +246,7 @@ Note que esta acção irá reiniciar a aplicação e poderá levar algum tempo.<
|
|||||||
|
|
||||||
<string name="encryption_information_decryption_error">Erro de decifragem</string>
|
<string name="encryption_information_decryption_error">Erro de decifragem</string>
|
||||||
<string name="encryption_information_device_name">Nome do dispositivo</string>
|
<string name="encryption_information_device_name">Nome do dispositivo</string>
|
||||||
<string name="encryption_information_device_id">ID do dispositivo</string>
|
<string name="device_manager_session_details_session_id">ID do dispositivo</string>
|
||||||
<string name="encryption_information_device_key">Chave do dispositivo</string>
|
<string name="encryption_information_device_key">Chave do dispositivo</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exportar chaves E2E da sala</string>
|
<string name="encryption_export_e2e_room_keys">Exportar chaves E2E da sala</string>
|
||||||
<string name="encryption_export_room_keys">Exportar chaves de sala</string>
|
<string name="encryption_export_room_keys">Exportar chaves de sala</string>
|
||||||
|
@ -432,7 +432,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Сбросить основной адрес</string>
|
<string name="room_settings_unset_main_address">Сбросить основной адрес</string>
|
||||||
<string name="encryption_information_decryption_error">Ошибка дешифровки</string>
|
<string name="encryption_information_decryption_error">Ошибка дешифровки</string>
|
||||||
<string name="encryption_information_device_name">Публичное имя</string>
|
<string name="encryption_information_device_name">Публичное имя</string>
|
||||||
<string name="encryption_information_device_id">ID сессии</string>
|
<string name="device_manager_session_details_session_id">ID сессии</string>
|
||||||
<string name="encryption_information_device_key">Ключ сессии</string>
|
<string name="encryption_information_device_key">Ключ сессии</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Экспорт E2E ключей комнаты</string>
|
<string name="encryption_export_e2e_room_keys">Экспорт E2E ключей комнаты</string>
|
||||||
<string name="encryption_export_room_keys">Экспорт ключей комнаты</string>
|
<string name="encryption_export_room_keys">Экспорт ключей комнаты</string>
|
||||||
@ -2678,4 +2678,4 @@
|
|||||||
<string name="explore_rooms">Обзор комнат</string>
|
<string name="explore_rooms">Обзор комнат</string>
|
||||||
<string name="start_chat">Начать беседу</string>
|
<string name="start_chat">Начать беседу</string>
|
||||||
<string name="create_room">Создать комнату</string>
|
<string name="create_room">Создать комнату</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -388,7 +388,7 @@
|
|||||||
<string name="settings_theme">Vzhľad</string>
|
<string name="settings_theme">Vzhľad</string>
|
||||||
<string name="encryption_information_decryption_error">Chyba dešifrovania</string>
|
<string name="encryption_information_decryption_error">Chyba dešifrovania</string>
|
||||||
<string name="encryption_information_device_name">Verejné meno</string>
|
<string name="encryption_information_device_name">Verejné meno</string>
|
||||||
<string name="encryption_information_device_id">ID relácie</string>
|
<string name="device_manager_session_details_session_id">ID relácie</string>
|
||||||
<string name="encryption_information_device_key">Kľúč relácie</string>
|
<string name="encryption_information_device_key">Kľúč relácie</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exportovať šifrovacie kľúče miestnosti</string>
|
<string name="encryption_export_e2e_room_keys">Exportovať šifrovacie kľúče miestnosti</string>
|
||||||
<string name="encryption_export_room_keys">Exportovať kľúče miestnosti</string>
|
<string name="encryption_export_room_keys">Exportovať kľúče miestnosti</string>
|
||||||
|
@ -431,7 +431,7 @@
|
|||||||
<string name="settings_theme">Temë</string>
|
<string name="settings_theme">Temë</string>
|
||||||
<string name="encryption_information_decryption_error">Gabim shfshehtëzimi</string>
|
<string name="encryption_information_decryption_error">Gabim shfshehtëzimi</string>
|
||||||
<string name="encryption_information_device_name">Emër publik</string>
|
<string name="encryption_information_device_name">Emër publik</string>
|
||||||
<string name="encryption_information_device_id">ID Sesioni</string>
|
<string name="device_manager_session_details_session_id">ID Sesioni</string>
|
||||||
<string name="encryption_information_device_key">Kyç sesioni</string>
|
<string name="encryption_information_device_key">Kyç sesioni</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Eksporto kyçe dhome E2E</string>
|
<string name="encryption_export_e2e_room_keys">Eksporto kyçe dhome E2E</string>
|
||||||
<string name="encryption_export_room_keys">Eksporto kyçe dhome</string>
|
<string name="encryption_export_room_keys">Eksporto kyçe dhome</string>
|
||||||
|
@ -918,7 +918,7 @@
|
|||||||
<string name="settings_secure_backup_enter_to_setup">Sätt upp på den här enheten</string>
|
<string name="settings_secure_backup_enter_to_setup">Sätt upp på den här enheten</string>
|
||||||
<string name="reset_secure_backup_title">Generera en ny säkerhetskopia eller sätt en ny lösenfras för din existerande säkerhetskopia.</string>
|
<string name="reset_secure_backup_title">Generera en ny säkerhetskopia eller sätt en ny lösenfras för din existerande säkerhetskopia.</string>
|
||||||
<string name="room_settings_labs_warning_message">Detta är experimentella funktioner som kan gå sönder på oväntade sätt. Använd varsamt.</string>
|
<string name="room_settings_labs_warning_message">Detta är experimentella funktioner som kan gå sönder på oväntade sätt. Använd varsamt.</string>
|
||||||
<string name="encryption_information_device_id">Sessions-ID</string>
|
<string name="device_manager_session_details_session_id">Sessions-ID</string>
|
||||||
<string name="encryption_information_device_key">Sessionsnyckel</string>
|
<string name="encryption_information_device_key">Sessionsnyckel</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Exportera krypteringsnycklar</string>
|
<string name="encryption_export_e2e_room_keys">Exportera krypteringsnycklar</string>
|
||||||
<string name="encryption_export_room_keys">Exportera rumsnycklar</string>
|
<string name="encryption_export_room_keys">Exportera rumsnycklar</string>
|
||||||
|
@ -260,7 +260,7 @@
|
|||||||
<string name="room_settings_set_main_address">ప్రధాన చిరునామాగా సెట్ చేయండి</string>
|
<string name="room_settings_set_main_address">ప్రధాన చిరునామాగా సెట్ చేయండి</string>
|
||||||
|
|
||||||
<string name="encryption_information_device_name">పరికరం పేరు</string>
|
<string name="encryption_information_device_name">పరికరం పేరు</string>
|
||||||
<string name="encryption_information_device_id">పరికరం ID</string>
|
<string name="device_manager_session_details_session_id">పరికరం ID</string>
|
||||||
<string name="encryption_information_device_key">పరికరం కీ</string>
|
<string name="encryption_information_device_key">పరికరం కీ</string>
|
||||||
|
|
||||||
<string name="encryption_export_e2e_room_keys">E2E గది కీలను ఎగుమతి చేయండి</string>
|
<string name="encryption_export_e2e_room_keys">E2E గది కీలను ఎగుమతి చేయండి</string>
|
||||||
|
@ -376,7 +376,7 @@
|
|||||||
<string name="settings_theme">Tema</string>
|
<string name="settings_theme">Tema</string>
|
||||||
<string name="encryption_information_decryption_error">Çözme hatası</string>
|
<string name="encryption_information_decryption_error">Çözme hatası</string>
|
||||||
<string name="encryption_information_device_name">Görünür Ad</string>
|
<string name="encryption_information_device_name">Görünür Ad</string>
|
||||||
<string name="encryption_information_device_id">Oturum kimliği</string>
|
<string name="device_manager_session_details_session_id">Oturum kimliği</string>
|
||||||
<string name="encryption_information_device_key">Oturum anahtarı</string>
|
<string name="encryption_information_device_key">Oturum anahtarı</string>
|
||||||
<string name="encryption_export_e2e_room_keys">E2E Oda anahtarlarını dışa aktar</string>
|
<string name="encryption_export_e2e_room_keys">E2E Oda anahtarlarını dışa aktar</string>
|
||||||
<string name="encryption_export_room_keys">Oda anahtarlarını dışa aktar</string>
|
<string name="encryption_export_room_keys">Oda anahtarlarını dışa aktar</string>
|
||||||
|
@ -354,7 +354,7 @@
|
|||||||
<string name="room_settings_unset_main_address">Зробити не основною адресою</string>
|
<string name="room_settings_unset_main_address">Зробити не основною адресою</string>
|
||||||
<string name="encryption_information_decryption_error">Помилка розшифрування</string>
|
<string name="encryption_information_decryption_error">Помилка розшифрування</string>
|
||||||
<string name="encryption_information_device_name">Загальнодоступна назва</string>
|
<string name="encryption_information_device_name">Загальнодоступна назва</string>
|
||||||
<string name="encryption_information_device_id">ID сеансу</string>
|
<string name="device_manager_session_details_session_id">ID сеансу</string>
|
||||||
<string name="encryption_information_device_key">Ключ сеансу</string>
|
<string name="encryption_information_device_key">Ключ сеансу</string>
|
||||||
<string name="encryption_export_e2e_room_keys">Експортувати E2E ключі кімнати</string>
|
<string name="encryption_export_e2e_room_keys">Експортувати E2E ключі кімнати</string>
|
||||||
<string name="encryption_export_room_keys">Експортувати ключі кімнати</string>
|
<string name="encryption_export_room_keys">Експортувати ключі кімнати</string>
|
||||||
|
@ -594,7 +594,7 @@
|
|||||||
<string name="deactivate_account_title">Hủy tài khoản</string>
|
<string name="deactivate_account_title">Hủy tài khoản</string>
|
||||||
<string name="dialog_user_consent_submit">Xem lại ngay</string>
|
<string name="dialog_user_consent_submit">Xem lại ngay</string>
|
||||||
<string name="encryption_information_device_key">Chìa khóa phiên</string>
|
<string name="encryption_information_device_key">Chìa khóa phiên</string>
|
||||||
<string name="encryption_information_device_id">Mã phiên</string>
|
<string name="device_manager_session_details_session_id">Mã phiên</string>
|
||||||
<string name="encryption_information_device_name">Tên công khai</string>
|
<string name="encryption_information_device_name">Tên công khai</string>
|
||||||
<string name="encryption_information_decryption_error">Lỗi giải mã</string>
|
<string name="encryption_information_decryption_error">Lỗi giải mã</string>
|
||||||
<string name="room_settings_labs_warning_message">Những chức năng này mang tính thí nghiệm có thể còn nhiều lỗi. Lưu ý khi dùng.</string>
|
<string name="room_settings_labs_warning_message">Những chức năng này mang tính thí nghiệm có thể còn nhiều lỗi. Lưu ý khi dùng.</string>
|
||||||
|
@ -242,7 +242,7 @@
|
|||||||
<string name="settings_password_updated">你的密码已更新</string>
|
<string name="settings_password_updated">你的密码已更新</string>
|
||||||
<string name="encryption_information_decryption_error">解密错误</string>
|
<string name="encryption_information_decryption_error">解密错误</string>
|
||||||
<string name="encryption_information_device_name">公开名称</string>
|
<string name="encryption_information_device_name">公开名称</string>
|
||||||
<string name="encryption_information_device_id">会话 ID</string>
|
<string name="device_manager_session_details_session_id">会话 ID</string>
|
||||||
<string name="encryption_information_device_key">会话密钥</string>
|
<string name="encryption_information_device_key">会话密钥</string>
|
||||||
<string name="encryption_import_import">导入</string>
|
<string name="encryption_import_import">导入</string>
|
||||||
<string name="encryption_information_verified">已验证</string>
|
<string name="encryption_information_verified">已验证</string>
|
||||||
@ -2583,4 +2583,4 @@
|
|||||||
<string name="device_manager_verification_status_verified">已验证的会话</string>
|
<string name="device_manager_verification_status_verified">已验证的会话</string>
|
||||||
<string name="a11y_device_manager_device_type_unknown">未知的设备类型</string>
|
<string name="a11y_device_manager_device_type_unknown">未知的设备类型</string>
|
||||||
<string name="invites_title">邀请</string>
|
<string name="invites_title">邀请</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -469,7 +469,7 @@
|
|||||||
<string name="settings_theme">主題</string>
|
<string name="settings_theme">主題</string>
|
||||||
<string name="encryption_information_decryption_error">解密錯誤</string>
|
<string name="encryption_information_decryption_error">解密錯誤</string>
|
||||||
<string name="encryption_information_device_name">公開名稱</string>
|
<string name="encryption_information_device_name">公開名稱</string>
|
||||||
<string name="encryption_information_device_id">工作階段 ID</string>
|
<string name="device_manager_session_details_session_id">工作階段 ID</string>
|
||||||
<string name="encryption_information_device_key">工作階段金鑰</string>
|
<string name="encryption_information_device_key">工作階段金鑰</string>
|
||||||
<string name="encryption_export_e2e_room_keys">匯出聊天室的端到端加密金鑰</string>
|
<string name="encryption_export_e2e_room_keys">匯出聊天室的端到端加密金鑰</string>
|
||||||
<string name="encryption_export_room_keys">匯出聊天室的加密金鑰</string>
|
<string name="encryption_export_room_keys">匯出聊天室的加密金鑰</string>
|
||||||
|
@ -1212,7 +1212,6 @@
|
|||||||
<string name="encryption_information_decryption_error">Decryption error</string>
|
<string name="encryption_information_decryption_error">Decryption error</string>
|
||||||
|
|
||||||
<string name="encryption_information_device_name">Public name</string>
|
<string name="encryption_information_device_name">Public name</string>
|
||||||
<string name="encryption_information_device_id">Session ID</string>
|
|
||||||
<string name="encryption_information_device_key">Session key</string>
|
<string name="encryption_information_device_key">Session key</string>
|
||||||
|
|
||||||
<string name="encryption_export_e2e_room_keys">Export E2E room keys</string>
|
<string name="encryption_export_e2e_room_keys">Export E2E room keys</string>
|
||||||
@ -3263,8 +3262,15 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="device_manager_current_session_title">Current Session</string>
|
<string name="device_manager_current_session_title">Current Session</string>
|
||||||
<string name="device_manager_session_title">Session</string>
|
<string name="device_manager_session_title">Session</string>
|
||||||
|
<string name="device_manager_device_title">Device</string>
|
||||||
<!-- Examples: Last activity Yesterday at 6PM, Last activity Aug 31 at 5:47PM -->
|
<!-- Examples: Last activity Yesterday at 6PM, Last activity Aug 31 at 5:47PM -->
|
||||||
<string name="device_manager_session_last_activity">Last activity %1$s</string>
|
<string name="device_manager_session_last_activity">Last activity %1$s</string>
|
||||||
|
<string name="device_manager_session_details_title">Session details</string>
|
||||||
|
<string name="device_manager_session_details_description">Application, device, and activity information.</string>
|
||||||
|
<string name="device_manager_session_details_session_name">Session name</string>
|
||||||
|
<string name="device_manager_session_details_session_id">Session ID</string>
|
||||||
|
<string name="device_manager_session_details_session_last_activity">Last activity</string>
|
||||||
|
<string name="device_manager_session_details_device_ip_address">IP address</string>
|
||||||
|
|
||||||
<!-- Note to translators: %s will be replaces with selected space name -->
|
<!-- Note to translators: %s will be replaces with selected space name -->
|
||||||
<string name="home_empty_space_no_rooms_title">%s\nis looking a little empty.</string>
|
<string name="home_empty_space_no_rooms_title">%s\nis looking a little empty.</string>
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<declare-styleable name="SessionOverviewEntryView">
|
||||||
|
<attr name="sessionOverviewEntryTitle" format="string" />
|
||||||
|
<attr name="sessionOverviewEntryDescription" format="string" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
</resources>
|
@ -2,8 +2,8 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<declare-styleable name="SessionsListHeaderView">
|
<declare-styleable name="SessionsListHeaderView">
|
||||||
<attr name="devicesListHeaderTitle" format="string" />
|
<attr name="sessionsListHeaderTitle" format="string" />
|
||||||
<attr name="devicesListHeaderDescription" format="string" />
|
<attr name="sessionsListHeaderDescription" format="string" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -1,6 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
|
<style name="TextAppearance.Vector.Subtitle.DevicesManagement">
|
||||||
|
<item name="android:textColor">?vctr_content_primary</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="TextAppearance.Vector.Subtitle.Medium.DevicesManagement">
|
<style name="TextAppearance.Vector.Subtitle.Medium.DevicesManagement">
|
||||||
<item name="android:textColor">?vctr_content_primary</item>
|
<item name="android:textColor">?vctr_content_primary</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -340,6 +340,7 @@
|
|||||||
<activity android:name=".features.home.room.list.home.invites.InvitesActivity"/>
|
<activity android:name=".features.home.room.list.home.invites.InvitesActivity"/>
|
||||||
<activity android:name=".features.home.room.list.home.release.ReleaseNotesActivity"/>
|
<activity android:name=".features.home.room.list.home.release.ReleaseNotesActivity"/>
|
||||||
<activity android:name=".features.settings.devices.v2.overview.SessionOverviewActivity"/>
|
<activity android:name=".features.settings.devices.v2.overview.SessionOverviewActivity"/>
|
||||||
|
<activity android:name=".features.settings.devices.v2.details.SessionDetailsActivity"/>
|
||||||
|
|
||||||
<!-- Services -->
|
<!-- Services -->
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ import im.vector.app.features.settings.account.deactivation.DeactivateAccountVie
|
|||||||
import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewModel
|
import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewModel
|
||||||
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheetViewModel
|
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheetViewModel
|
||||||
import im.vector.app.features.settings.devices.DevicesViewModel
|
import im.vector.app.features.settings.devices.DevicesViewModel
|
||||||
|
import im.vector.app.features.settings.devices.v2.details.SessionDetailsViewModel
|
||||||
import im.vector.app.features.settings.devices.v2.overview.SessionOverviewViewModel
|
import im.vector.app.features.settings.devices.v2.overview.SessionOverviewViewModel
|
||||||
import im.vector.app.features.settings.devtools.AccountDataViewModel
|
import im.vector.app.features.settings.devtools.AccountDataViewModel
|
||||||
import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel
|
import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel
|
||||||
@ -641,4 +642,9 @@ interface MavericksViewModelModule {
|
|||||||
@IntoMap
|
@IntoMap
|
||||||
@MavericksViewModelKey(SessionOverviewViewModel::class)
|
@MavericksViewModelKey(SessionOverviewViewModel::class)
|
||||||
fun sessionOverviewViewModelFactory(factory: SessionOverviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
fun sessionOverviewViewModelFactory(factory: SessionOverviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@MavericksViewModelKey(SessionDetailsViewModel::class)
|
||||||
|
fun sessionDetailsViewModelFactory(factory: SessionDetailsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||||
}
|
}
|
||||||
|
@ -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.utils
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.core.content.getSystemService
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CopyToClipboardUseCase @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun execute(text: CharSequence) {
|
||||||
|
context.getSystemService<ClipboardManager>()
|
||||||
|
?.setPrimaryClip(ClipData.newPlainText("", text))
|
||||||
|
}
|
||||||
|
}
|
@ -19,8 +19,6 @@ package im.vector.app.core.utils
|
|||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@ -100,8 +98,7 @@ fun requestDisablingBatteryOptimization(activity: Activity, activityResultLaunch
|
|||||||
* @param toastMessage content of the toast message as a String resource
|
* @param toastMessage content of the toast message as a String resource
|
||||||
*/
|
*/
|
||||||
fun copyToClipboard(context: Context, text: CharSequence, showToast: Boolean = true, @StringRes toastMessage: Int = R.string.copied_to_clipboard) {
|
fun copyToClipboard(context: Context, text: CharSequence, showToast: Boolean = true, @StringRes toastMessage: Int = R.string.copied_to_clipboard) {
|
||||||
val clipboard = context.getSystemService<ClipboardManager>()!!
|
CopyToClipboardUseCase(context).execute(text)
|
||||||
clipboard.setPrimaryClip(ClipData.newPlainText("", text))
|
|
||||||
if (showToast) {
|
if (showToast) {
|
||||||
context.toast(toastMessage)
|
context.toast(toastMessage)
|
||||||
}
|
}
|
||||||
|
@ -201,13 +201,12 @@ class NewHomeDetailFragment :
|
|||||||
private fun setupFabs() {
|
private fun setupFabs() {
|
||||||
showFABs()
|
showFABs()
|
||||||
|
|
||||||
views.newLayoutCreateChatButton.setOnClickListener {
|
views.newLayoutCreateChatButton.debouncedClicks {
|
||||||
newChatBottomSheet.show(requireActivity().supportFragmentManager, NewChatBottomSheet.TAG)
|
newChatBottomSheet.takeIf { !it.isAdded }?.show(requireActivity().supportFragmentManager, NewChatBottomSheet.TAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
views.newLayoutOpenSpacesButton.setOnClickListener {
|
views.newLayoutOpenSpacesButton.debouncedClicks {
|
||||||
// Click action for open spaces modal goes here
|
spaceListBottomSheet.takeIf { !it.isAdded }?.show(requireActivity().supportFragmentManager, SpaceListBottomSheet.TAG)
|
||||||
spaceListBottomSheet.show(requireActivity().supportFragmentManager, SpaceListBottomSheet.TAG)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import im.vector.app.features.navigation.Navigator
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class NewChatBottomSheet @Inject constructor() : VectorBaseBottomSheetDialogFragment<FragmentNewChatBottomSheetBinding>() {
|
class NewChatBottomSheet : VectorBaseBottomSheetDialogFragment<FragmentNewChatBottomSheetBinding>() {
|
||||||
|
|
||||||
@Inject lateinit var navigator: Navigator
|
@Inject lateinit var navigator: Navigator
|
||||||
|
|
||||||
|
@ -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.features.settings.devices.v2.details
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CheckIfSectionDeviceIsVisibleUseCase @Inject constructor() {
|
||||||
|
|
||||||
|
fun execute(deviceInfo: DeviceInfo): Boolean {
|
||||||
|
return deviceInfo.lastSeenIp?.isNotEmpty().orFalse()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CheckIfSectionSessionIsVisibleUseCase @Inject constructor() {
|
||||||
|
|
||||||
|
fun execute(deviceInfo: DeviceInfo): Boolean {
|
||||||
|
return deviceInfo.displayName?.isNotEmpty().orFalse() ||
|
||||||
|
deviceInfo.deviceId?.isNotEmpty().orFalse() ||
|
||||||
|
(deviceInfo.lastSeenTs ?: 0) > 0
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
|
||||||
|
sealed class SessionDetailsAction : VectorViewModelAction {
|
||||||
|
data class CopyToClipboard(val content: String) : SessionDetailsAction()
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import com.airbnb.mvrx.Mavericks
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import im.vector.app.core.extensions.addFragment
|
||||||
|
import im.vector.app.core.platform.SimpleFragmentActivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the details info about a Session.
|
||||||
|
*/
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class SessionDetailsActivity : SimpleFragmentActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
if (isFirstCreation()) {
|
||||||
|
addFragment(
|
||||||
|
container = views.container,
|
||||||
|
fragmentClass = SessionDetailsFragment::class.java,
|
||||||
|
params = intent.getParcelableExtra(Mavericks.KEY_ARG)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newIntent(context: Context, deviceId: String): Intent {
|
||||||
|
return Intent(context, SessionDetailsActivity::class.java).apply {
|
||||||
|
putExtra(Mavericks.KEY_ARG, SessionDetailsArgs(deviceId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.features.settings.devices.v2.details
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class SessionDetailsArgs(
|
||||||
|
val deviceId: String
|
||||||
|
) : Parcelable
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
|
||||||
|
@EpoxyModelClass
|
||||||
|
abstract class SessionDetailsContentItem : VectorEpoxyModel<SessionDetailsContentItem.Holder>(R.layout.item_session_details_content) {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var title: String? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var description: String? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var hasDivider: Boolean = true
|
||||||
|
|
||||||
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||||
|
var onLongClickListener: View.OnLongClickListener? = null
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.sessionDetailsContentTitle.text = title
|
||||||
|
holder.sessionDetailsContentDescription.text = description
|
||||||
|
holder.view.isClickable = onLongClickListener != null
|
||||||
|
holder.view.setOnLongClickListener(onLongClickListener)
|
||||||
|
holder.sessionDetailsContentDivider.isVisible = hasDivider
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val sessionDetailsContentTitle by bind<TextView>(R.id.sessionDetailsContentTitle)
|
||||||
|
val sessionDetailsContentDescription by bind<TextView>(R.id.sessionDetailsContentDescription)
|
||||||
|
val sessionDetailsContentDivider by bind<View>(R.id.sessionDetailsContentDivider)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.date.DateFormatKind
|
||||||
|
import im.vector.app.core.date.VectorDateFormatter
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.core.utils.DimensionConverter
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SessionDetailsController @Inject constructor(
|
||||||
|
private val checkIfSectionSessionIsVisibleUseCase: CheckIfSectionSessionIsVisibleUseCase,
|
||||||
|
private val checkIfSectionDeviceIsVisibleUseCase: CheckIfSectionDeviceIsVisibleUseCase,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val dateFormatter: VectorDateFormatter,
|
||||||
|
private val dimensionConverter: DimensionConverter,
|
||||||
|
) : TypedEpoxyController<DeviceInfo>() {
|
||||||
|
|
||||||
|
var callback: Callback? = null
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun onItemLongClicked(content: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildModels(data: DeviceInfo?) {
|
||||||
|
data?.let { info ->
|
||||||
|
val hasSectionSession = hasSectionSession(data)
|
||||||
|
if (hasSectionSession) {
|
||||||
|
buildSectionSession(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSectionDevice(data)) {
|
||||||
|
buildSectionDevice(info, addExtraTopMargin = hasSectionSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildHeaderItem(@StringRes titleResId: Int, addExtraTopMargin: Boolean = false) {
|
||||||
|
val host = this
|
||||||
|
sessionDetailsHeaderItem {
|
||||||
|
id(titleResId)
|
||||||
|
title(host.stringProvider.getString(titleResId))
|
||||||
|
addExtraTopMargin(addExtraTopMargin)
|
||||||
|
dimensionConverter(host.dimensionConverter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildContentItem(@StringRes titleResId: Int, value: String, hasDivider: Boolean) {
|
||||||
|
val host = this
|
||||||
|
sessionDetailsContentItem {
|
||||||
|
id(titleResId)
|
||||||
|
title(host.stringProvider.getString(titleResId))
|
||||||
|
description(value)
|
||||||
|
hasDivider(hasDivider)
|
||||||
|
onLongClickListener(View.OnLongClickListener {
|
||||||
|
host.callback?.onItemLongClicked(value)
|
||||||
|
true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasSectionSession(data: DeviceInfo): Boolean {
|
||||||
|
return checkIfSectionSessionIsVisibleUseCase.execute(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildSectionSession(data: DeviceInfo) {
|
||||||
|
val sessionName = data.displayName
|
||||||
|
val sessionId = data.deviceId
|
||||||
|
val sessionLastSeenTs = data.lastSeenTs
|
||||||
|
|
||||||
|
buildHeaderItem(R.string.device_manager_session_title)
|
||||||
|
|
||||||
|
sessionName?.let {
|
||||||
|
val hasDivider = sessionId != null || sessionLastSeenTs != null
|
||||||
|
buildContentItem(R.string.device_manager_session_details_session_name, it, hasDivider)
|
||||||
|
}
|
||||||
|
sessionId?.let {
|
||||||
|
val hasDivider = sessionLastSeenTs != null
|
||||||
|
buildContentItem(R.string.device_manager_session_details_session_id, it, hasDivider)
|
||||||
|
}
|
||||||
|
sessionLastSeenTs?.let {
|
||||||
|
val formattedDate = dateFormatter.format(it, DateFormatKind.MESSAGE_DETAIL)
|
||||||
|
val hasDivider = false
|
||||||
|
buildContentItem(R.string.device_manager_session_details_session_last_activity, formattedDate, hasDivider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasSectionDevice(data: DeviceInfo): Boolean {
|
||||||
|
return checkIfSectionDeviceIsVisibleUseCase.execute(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildSectionDevice(data: DeviceInfo, addExtraTopMargin: Boolean) {
|
||||||
|
val lastSeenIp = data.lastSeenIp
|
||||||
|
|
||||||
|
buildHeaderItem(R.string.device_manager_device_title, addExtraTopMargin)
|
||||||
|
|
||||||
|
lastSeenIp?.let {
|
||||||
|
val hasDivider = false
|
||||||
|
buildContentItem(R.string.device_manager_session_details_device_ip_address, it, hasDivider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
|
import com.airbnb.mvrx.withState
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.cleanup
|
||||||
|
import im.vector.app.core.extensions.configureWith
|
||||||
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
|
import im.vector.app.core.platform.showOptimizedSnackbar
|
||||||
|
import im.vector.app.databinding.FragmentSessionDetailsBinding
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the details info about a Session.
|
||||||
|
*/
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class SessionDetailsFragment :
|
||||||
|
VectorBaseFragment<FragmentSessionDetailsBinding>() {
|
||||||
|
|
||||||
|
@Inject lateinit var sessionDetailsController: SessionDetailsController
|
||||||
|
|
||||||
|
private val viewModel: SessionDetailsViewModel by fragmentViewModel()
|
||||||
|
|
||||||
|
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSessionDetailsBinding {
|
||||||
|
return FragmentSessionDetailsBinding.inflate(inflater, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
initToolbar()
|
||||||
|
initSessionDetails()
|
||||||
|
observeViewEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initToolbar() {
|
||||||
|
(activity as? AppCompatActivity)
|
||||||
|
?.supportActionBar
|
||||||
|
?.setTitle(R.string.device_manager_session_details_title)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initSessionDetails() {
|
||||||
|
sessionDetailsController.callback = object : SessionDetailsController.Callback {
|
||||||
|
override fun onItemLongClicked(content: String) {
|
||||||
|
viewModel.handle(SessionDetailsAction.CopyToClipboard(content))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
views.sessionDetails.configureWith(sessionDetailsController)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeViewEvents() {
|
||||||
|
viewModel.observeViewEvents { viewEvent ->
|
||||||
|
when (viewEvent) {
|
||||||
|
SessionDetailsViewEvent.ContentCopiedToClipboard -> view?.showOptimizedSnackbar(getString(R.string.copied_to_clipboard))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
cleanUpSessionDetails()
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cleanUpSessionDetails() {
|
||||||
|
sessionDetailsController.callback = null
|
||||||
|
views.sessionDetails.cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
|
if (state.deviceInfo is Success) {
|
||||||
|
renderSessionDetails(state.deviceInfo.invoke())
|
||||||
|
} else {
|
||||||
|
hideSessionDetails()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderSessionDetails(deviceInfo: DeviceInfo) {
|
||||||
|
views.sessionDetails.isVisible = true
|
||||||
|
sessionDetailsController.setData(deviceInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideSessionDetails() {
|
||||||
|
views.sessionDetails.isGone = true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.core.view.updateMargins
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.app.core.utils.DimensionConverter
|
||||||
|
|
||||||
|
private const val EXTRA_TOP_MARGIN_DP = 48
|
||||||
|
|
||||||
|
@EpoxyModelClass
|
||||||
|
abstract class SessionDetailsHeaderItem : VectorEpoxyModel<SessionDetailsHeaderItem.Holder>(R.layout.item_session_details_header) {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var title: String? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var addExtraTopMargin: Boolean = false
|
||||||
|
|
||||||
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||||
|
var dimensionConverter: DimensionConverter? = null
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.sessionDetailsHeaderTitle.text = title
|
||||||
|
val topMargin = if (addExtraTopMargin) {
|
||||||
|
dimensionConverter?.dpToPx(EXTRA_TOP_MARGIN_DP) ?: 0
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
holder.sessionDetailsHeaderTitle.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
updateMargins(top = topMargin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val sessionDetailsHeaderTitle by bind<TextView>(R.id.sessionDetailsHeaderTitle)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import im.vector.app.core.platform.VectorViewEvents
|
||||||
|
|
||||||
|
sealed class SessionDetailsViewEvent : VectorViewEvents {
|
||||||
|
object ContentCopiedToClipboard : SessionDetailsViewEvent()
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
|
import im.vector.app.core.utils.CopyToClipboardUseCase
|
||||||
|
import im.vector.app.features.settings.devices.v2.overview.GetDeviceFullInfoUseCase
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
|
class SessionDetailsViewModel @AssistedInject constructor(
|
||||||
|
@Assisted val initialState: SessionDetailsViewState,
|
||||||
|
private val getDeviceFullInfoUseCase: GetDeviceFullInfoUseCase,
|
||||||
|
private val copyToClipboardUseCase: CopyToClipboardUseCase,
|
||||||
|
) : VectorViewModel<SessionDetailsViewState, SessionDetailsAction, SessionDetailsViewEvent>(initialState) {
|
||||||
|
|
||||||
|
companion object : MavericksViewModelFactory<SessionDetailsViewModel, SessionDetailsViewState> by hiltMavericksViewModelFactory()
|
||||||
|
|
||||||
|
@AssistedFactory
|
||||||
|
interface Factory : MavericksAssistedViewModelFactory<SessionDetailsViewModel, SessionDetailsViewState> {
|
||||||
|
override fun create(initialState: SessionDetailsViewState): SessionDetailsViewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
observeSessionInfo(initialState.deviceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeSessionInfo(deviceId: String) {
|
||||||
|
getDeviceFullInfoUseCase.execute(deviceId)
|
||||||
|
.onEach { setState { copy(deviceInfo = Success(it.deviceInfo)) } }
|
||||||
|
.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handle(action: SessionDetailsAction) {
|
||||||
|
return when (action) {
|
||||||
|
is SessionDetailsAction.CopyToClipboard -> handleCopyToClipboard(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleCopyToClipboard(copyToClipboard: SessionDetailsAction.CopyToClipboard) {
|
||||||
|
copyToClipboardUseCase.execute(copyToClipboard.content)
|
||||||
|
_viewEvents.post(SessionDetailsViewEvent.ContentCopiedToClipboard)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.Async
|
||||||
|
import com.airbnb.mvrx.MavericksState
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
|
||||||
|
data class SessionDetailsViewState(
|
||||||
|
val deviceId: String,
|
||||||
|
val deviceInfo: Async<DeviceInfo> = Uninitialized,
|
||||||
|
) : MavericksState {
|
||||||
|
constructor(args: SessionDetailsArgs) : this(
|
||||||
|
deviceId = args.deviceId
|
||||||
|
)
|
||||||
|
}
|
@ -24,6 +24,7 @@ import androidx.core.view.isVisible
|
|||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.date.DateFormatKind
|
import im.vector.app.core.date.DateFormatKind
|
||||||
import im.vector.app.core.date.VectorDateFormatter
|
import im.vector.app.core.date.VectorDateFormatter
|
||||||
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
import im.vector.app.core.extensions.setTextWithColoredPart
|
import im.vector.app.core.extensions.setTextWithColoredPart
|
||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.core.resources.DrawableProvider
|
import im.vector.app.core.resources.DrawableProvider
|
||||||
@ -91,13 +92,14 @@ class SessionInfoView @JvmOverloads constructor(
|
|||||||
private fun appendLearnMoreToVerificationStatus() {
|
private fun appendLearnMoreToVerificationStatus() {
|
||||||
val status = views.sessionInfoVerificationStatusDetailTextView.text
|
val status = views.sessionInfoVerificationStatusDetailTextView.text
|
||||||
val learnMore = context.getString(R.string.action_learn_more)
|
val learnMore = context.getString(R.string.action_learn_more)
|
||||||
val stringBuilder = StringBuilder()
|
val statusText = buildString {
|
||||||
stringBuilder.append(status)
|
append(status)
|
||||||
stringBuilder.append(" ")
|
append(" ")
|
||||||
stringBuilder.append(learnMore)
|
append(learnMore)
|
||||||
|
}
|
||||||
|
|
||||||
views.sessionInfoVerificationStatusDetailTextView.setTextWithColoredPart(
|
views.sessionInfoVerificationStatusDetailTextView.setTextWithColoredPart(
|
||||||
fullText = stringBuilder.toString(),
|
fullText = statusText,
|
||||||
coloredPart = learnMore,
|
coloredPart = learnMore,
|
||||||
underline = false
|
underline = false
|
||||||
) {
|
) {
|
||||||
@ -172,15 +174,7 @@ class SessionInfoView @JvmOverloads constructor(
|
|||||||
views.sessionInfoLastActivityTextView.isGone = true
|
views.sessionInfoLastActivityTextView.isGone = true
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceInfo.lastSeenIp
|
views.sessionInfoLastIPAddressTextView.setTextOrHide(deviceInfo.lastSeenIp?.takeIf { isLastSeenDetailsVisible })
|
||||||
?.takeIf { isLastSeenDetailsVisible }
|
|
||||||
?.let { ipAddress ->
|
|
||||||
views.sessionInfoLastIPAddressTextView.isVisible = true
|
|
||||||
views.sessionInfoLastIPAddressTextView.text = ipAddress
|
|
||||||
}
|
|
||||||
?: run {
|
|
||||||
views.sessionInfoLastIPAddressTextView.isGone = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderDetailsButton(isDetailsButtonVisible: Boolean) {
|
private fun renderDetailsButton(isDetailsButtonVisible: Boolean) {
|
||||||
|
@ -53,26 +53,27 @@ class SessionsListHeaderView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setTitle(typedArray: TypedArray) {
|
private fun setTitle(typedArray: TypedArray) {
|
||||||
val title = typedArray.getString(R.styleable.SessionsListHeaderView_devicesListHeaderTitle)
|
val title = typedArray.getString(R.styleable.SessionsListHeaderView_sessionsListHeaderTitle)
|
||||||
binding.sessionsListHeaderTitle.text = title
|
binding.sessionsListHeaderTitle.text = title
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setDescription(typedArray: TypedArray) {
|
private fun setDescription(typedArray: TypedArray) {
|
||||||
val description = typedArray.getString(R.styleable.SessionsListHeaderView_devicesListHeaderDescription)
|
val description = typedArray.getString(R.styleable.SessionsListHeaderView_sessionsListHeaderDescription)
|
||||||
if (description.isNullOrEmpty()) {
|
if (description.isNullOrEmpty()) {
|
||||||
binding.sessionsListHeaderDescription.isVisible = false
|
binding.sessionsListHeaderDescription.isVisible = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val learnMore = context.getString(R.string.action_learn_more)
|
val learnMore = context.getString(R.string.action_learn_more)
|
||||||
val stringBuilder = StringBuilder()
|
val fullDescription = buildString {
|
||||||
stringBuilder.append(description)
|
append(description)
|
||||||
stringBuilder.append(" ")
|
append(" ")
|
||||||
stringBuilder.append(learnMore)
|
append(learnMore)
|
||||||
|
}
|
||||||
|
|
||||||
binding.sessionsListHeaderDescription.isVisible = true
|
binding.sessionsListHeaderDescription.isVisible = true
|
||||||
binding.sessionsListHeaderDescription.setTextWithColoredPart(
|
binding.sessionsListHeaderDescription.setTextWithColoredPart(
|
||||||
fullText = stringBuilder.toString(),
|
fullText = fullDescription,
|
||||||
coloredPart = learnMore,
|
coloredPart = learnMore,
|
||||||
underline = false
|
underline = false
|
||||||
) {
|
) {
|
||||||
|
@ -25,8 +25,8 @@ import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveU
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GetDeviceFullInfoUseCase @Inject constructor(
|
class GetDeviceFullInfoUseCase @Inject constructor(
|
||||||
@ -36,7 +36,7 @@ class GetDeviceFullInfoUseCase @Inject constructor(
|
|||||||
private val checkIfSessionIsInactiveUseCase: CheckIfSessionIsInactiveUseCase,
|
private val checkIfSessionIsInactiveUseCase: CheckIfSessionIsInactiveUseCase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun execute(deviceId: String): Flow<Optional<DeviceFullInfo>> {
|
fun execute(deviceId: String): Flow<DeviceFullInfo> {
|
||||||
return activeSessionHolder.getSafeActiveSession()?.let { session ->
|
return activeSessionHolder.getSafeActiveSession()?.let { session ->
|
||||||
combine(
|
combine(
|
||||||
getCurrentSessionCrossSigningInfoUseCase.execute(),
|
getCurrentSessionCrossSigningInfoUseCase.execute(),
|
||||||
@ -58,7 +58,7 @@ class GetDeviceFullInfoUseCase @Inject constructor(
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
fullInfo.toOptional()
|
fullInfo.toOptional()
|
||||||
}
|
}.unwrap()
|
||||||
} ?: emptyFlow()
|
} ?: emptyFlow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.overview
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.TypedArray
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.core.content.res.use
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.setAttributeBackground
|
||||||
|
import im.vector.app.databinding.ViewSessionOverviewEntryBinding
|
||||||
|
|
||||||
|
class SessionOverviewEntryView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : ConstraintLayout(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private val binding = ViewSessionOverviewEntryBinding.inflate(
|
||||||
|
LayoutInflater.from(context),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
initBackground()
|
||||||
|
context.obtainStyledAttributes(
|
||||||
|
attrs,
|
||||||
|
R.styleable.SessionOverviewEntryView,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
).use {
|
||||||
|
setTitle(it)
|
||||||
|
setDescription(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initBackground() {
|
||||||
|
binding.root.setAttributeBackground(android.R.attr.selectableItemBackground)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setTitle(typedArray: TypedArray) {
|
||||||
|
val title = typedArray.getString(R.styleable.SessionOverviewEntryView_sessionOverviewEntryTitle)
|
||||||
|
binding.sessionsOverviewEntryTitle.text = title
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setDescription(typedArray: TypedArray) {
|
||||||
|
val description = typedArray.getString(R.styleable.SessionOverviewEntryView_sessionOverviewEntryDescription)
|
||||||
|
binding.sessionsOverviewEntryDescription.text = description
|
||||||
|
}
|
||||||
|
}
|
@ -45,6 +45,8 @@ import javax.inject.Inject
|
|||||||
class SessionOverviewFragment :
|
class SessionOverviewFragment :
|
||||||
VectorBaseFragment<FragmentSessionOverviewBinding>() {
|
VectorBaseFragment<FragmentSessionOverviewBinding>() {
|
||||||
|
|
||||||
|
@Inject lateinit var viewNavigator: SessionOverviewViewNavigator
|
||||||
|
|
||||||
@Inject lateinit var dateFormatter: VectorDateFormatter
|
@Inject lateinit var dateFormatter: VectorDateFormatter
|
||||||
|
|
||||||
@Inject lateinit var drawableProvider: DrawableProvider
|
@Inject lateinit var drawableProvider: DrawableProvider
|
||||||
@ -79,6 +81,7 @@ class SessionOverviewFragment :
|
|||||||
|
|
||||||
override fun invalidate() = withState(viewModel) { state ->
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
updateToolbar(state.isCurrentSession)
|
updateToolbar(state.isCurrentSession)
|
||||||
|
updateEntryDetails(state.deviceId)
|
||||||
if (state.deviceInfo is Success) {
|
if (state.deviceInfo is Success) {
|
||||||
renderSessionInfo(state.isCurrentSession, state.deviceInfo.invoke())
|
renderSessionInfo(state.isCurrentSession, state.deviceInfo.invoke())
|
||||||
} else {
|
} else {
|
||||||
@ -93,6 +96,12 @@ class SessionOverviewFragment :
|
|||||||
?.setTitle(titleResId)
|
?.setTitle(titleResId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateEntryDetails(deviceId: String) {
|
||||||
|
views.sessionOverviewEntryDetails.setOnClickListener {
|
||||||
|
viewNavigator.navigateToSessionDetails(requireContext(), deviceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun renderSessionInfo(isCurrentSession: Boolean, deviceFullInfo: DeviceFullInfo) {
|
private fun renderSessionInfo(isCurrentSession: Boolean, deviceFullInfo: DeviceFullInfo) {
|
||||||
views.sessionOverviewInfo.isVisible = true
|
views.sessionOverviewInfo.isVisible = true
|
||||||
val viewState = SessionInfoViewState(
|
val viewState = SessionInfoViewState(
|
||||||
|
@ -26,7 +26,6 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
|
|||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
@ -54,7 +53,6 @@ class SessionOverviewViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
private fun observeSessionInfo(deviceId: String) {
|
private fun observeSessionInfo(deviceId: String) {
|
||||||
getDeviceFullInfoUseCase.execute(deviceId)
|
getDeviceFullInfoUseCase.execute(deviceId)
|
||||||
.mapNotNull { it.getOrNull() }
|
|
||||||
.onEach { setState { copy(deviceInfo = Success(it)) } }
|
.onEach { setState { copy(deviceInfo = Success(it)) } }
|
||||||
.launchIn(viewModelScope)
|
.launchIn(viewModelScope)
|
||||||
}
|
}
|
||||||
|
@ -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.features.settings.devices.v2.overview
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import im.vector.app.features.settings.devices.v2.details.SessionDetailsActivity
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SessionOverviewViewNavigator @Inject constructor() {
|
||||||
|
|
||||||
|
fun navigateToSessionDetails(context: Context, deviceId: String) {
|
||||||
|
context.startActivity(SessionDetailsActivity.newIntent(context, deviceId))
|
||||||
|
}
|
||||||
|
}
|
@ -39,7 +39,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
android:text="@string/encryption_information_device_id"
|
android:text="@string/device_manager_session_details_session_id"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -73,4 +73,4 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
21
vector/src/main/res/layout/fragment_session_details.xml
Normal file
21
vector/src/main/res/layout/fragment_session_details.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/sessionDetails"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.0"
|
||||||
|
tools:listitem="@layout/item_session_details_content" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,20 +1,36 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<im.vector.app.features.settings.devices.v2.list.SessionInfoView
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/sessionOverviewInfo"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="0dp"
|
android:layout_height="wrap_content">
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="16dp"
|
|
||||||
android:layout_marginVertical="24dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<im.vector.app.features.settings.devices.v2.list.SessionInfoView
|
||||||
|
android:id="@+id/sessionOverviewInfo"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginVertical="24dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<im.vector.app.features.settings.devices.v2.overview.SessionOverviewEntryView
|
||||||
|
android:id="@+id/sessionOverviewEntryDetails"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sessionOverviewInfo"
|
||||||
|
app:sessionOverviewEntryDescription="@string/device_manager_session_details_description"
|
||||||
|
app:sessionOverviewEntryTitle="@string/device_manager_session_details_title" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
android:id="@+id/deviceListHeaderSectionSecurityRecommendations"
|
android:id="@+id/deviceListHeaderSectionSecurityRecommendations"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:devicesListHeaderDescription="@string/device_manager_header_section_security_recommendations_description"
|
app:sessionsListHeaderDescription="@string/device_manager_header_section_security_recommendations_description"
|
||||||
app:devicesListHeaderTitle="@string/device_manager_header_section_security_recommendations_title"
|
app:sessionsListHeaderTitle="@string/device_manager_header_section_security_recommendations_title"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
@ -60,8 +60,8 @@
|
|||||||
android:id="@+id/deviceListHeaderCurrentSession"
|
android:id="@+id/deviceListHeaderCurrentSession"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:devicesListHeaderDescription=""
|
app:sessionsListHeaderDescription=""
|
||||||
app:devicesListHeaderTitle="@string/device_manager_current_session_title"
|
app:sessionsListHeaderTitle="@string/device_manager_current_session_title"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/deviceListSecurityRecommendationsDivider" />
|
app:layout_constraintTop_toBottomOf="@id/deviceListSecurityRecommendationsDivider" />
|
||||||
@ -90,8 +90,8 @@
|
|||||||
android:id="@+id/deviceListHeaderOtherSessions"
|
android:id="@+id/deviceListHeaderOtherSessions"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:devicesListHeaderDescription="@string/settings_sessions_other_description"
|
app:sessionsListHeaderDescription="@string/settings_sessions_other_description"
|
||||||
app:devicesListHeaderTitle="@string/settings_sessions_other_title"
|
app:sessionsListHeaderTitle="@string/settings_sessions_other_title"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/deviceListDividerCurrentSession" />
|
app:layout_constraintTop_toBottomOf="@id/deviceListDividerCurrentSession" />
|
||||||
|
50
vector/src/main/res/layout/item_session_details_content.xml
Normal file
50
vector/src/main/res/layout/item_session_details_content.xml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="14dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sessionDetailsContentTitle"
|
||||||
|
style="@style/TextAppearance.Vector.Body.DevicesManagement"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/sessionDetailsContentDescription"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Session name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sessionDetailsContentDescription"
|
||||||
|
style="@style/TextAppearance.Vector.Body"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||||
|
android:gravity="end"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/sessionDetailsContentTitle"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Element Web: Firefox on macOS" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/sessionDetailsContentDivider"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="14dp"
|
||||||
|
android:background="@drawable/divider_horizontal"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/sessionDetailsContentDescription"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/sessionDetailsContentTitle"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sessionDetailsContentBarrier" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Barrier
|
||||||
|
android:id="@+id/sessionDetailsContentBarrier"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:barrierDirection="bottom"
|
||||||
|
app:constraint_referenced_ids="sessionDetailsContentTitle, sessionDetailsContentDescription" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
21
vector/src/main/res/layout/item_session_details_header.xml
Normal file
21
vector/src/main/res/layout/item_session_details_header.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sessionDetailsHeaderTitle"
|
||||||
|
style="@style/TextAppearance.Vector.Body.Medium"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="@dimen/layout_horizontal_margin"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:lines="1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Session" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
42
vector/src/main/res/layout/view_session_overview_entry.xml
Normal file
42
vector/src/main/res/layout/view_session_overview_entry.xml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sessionsOverviewEntryTitle"
|
||||||
|
style="@style/TextAppearance.Vector.Subtitle.DevicesManagement"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="@dimen/layout_horizontal_margin"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Session details" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sessionsOverviewEntryDescription"
|
||||||
|
style="@style/TextAppearance.Vector.Body.DevicesManagement"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/sessionsOverviewEntryTitle"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/sessionsOverviewEntryTitle"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sessionsOverviewEntryTitle"
|
||||||
|
tools:text="Application, device, and activity information." />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/sessionsOverviewEntryDivider"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:background="@drawable/divider_horizontal"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/sessionsOverviewEntryTitle"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/sessionsOverviewEntryTitle"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sessionsOverviewEntryDescription" />
|
||||||
|
|
||||||
|
</merge>
|
@ -35,7 +35,7 @@
|
|||||||
<im.vector.app.core.preference.VectorPreference
|
<im.vector.app.core.preference.VectorPreference
|
||||||
android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY"
|
android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/encryption_information_device_id"
|
android:title="@string/device_manager_session_details_session_id"
|
||||||
tools:summary="VZRHETBEER" />
|
tools:summary="VZRHETBEER" />
|
||||||
|
|
||||||
<im.vector.app.core.preference.VectorPreference
|
<im.vector.app.core.preference.VectorPreference
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import im.vector.app.test.fakes.FakeContext
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import io.mockk.unmockkAll
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
private const val A_TEXT = "text"
|
||||||
|
|
||||||
|
class CopyToClipboardUseCaseTest {
|
||||||
|
|
||||||
|
private val fakeContext = FakeContext()
|
||||||
|
|
||||||
|
private val copyToClipboardUseCase = CopyToClipboardUseCase(
|
||||||
|
context = fakeContext.instance
|
||||||
|
)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
mockkStatic(ClipData::class)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
unmockkAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a text when executing the use case then the text is copied into the clipboard`() {
|
||||||
|
// Given
|
||||||
|
val clipboardManager = fakeContext.givenClipboardManager()
|
||||||
|
clipboardManager.givenSetPrimaryClip()
|
||||||
|
val clipData = mockk<ClipData>()
|
||||||
|
every { ClipData.newPlainText(any(), any()) } returns clipData
|
||||||
|
|
||||||
|
// When
|
||||||
|
copyToClipboardUseCase.execute(A_TEXT)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
clipboardManager.verifySetPrimaryClip(clipData)
|
||||||
|
verify { ClipData.newPlainText("", A_TEXT) }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
|
||||||
|
private const val AN_IP_ADDRESS = "ip-address"
|
||||||
|
|
||||||
|
class CheckIfSectionDeviceIsVisibleUseCaseTest {
|
||||||
|
|
||||||
|
private val checkIfSectionDeviceIsVisibleUseCase = CheckIfSectionDeviceIsVisibleUseCase()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given device info with Ip address when checking is device section is visible then it returns true`() = runTest {
|
||||||
|
// Given
|
||||||
|
val deviceInfo = givenADeviceInfo(AN_IP_ADDRESS)
|
||||||
|
|
||||||
|
// When
|
||||||
|
val result = checkIfSectionDeviceIsVisibleUseCase.execute(deviceInfo)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result shouldBeEqualTo true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given device info with empty or null Ip address when checking is device section is visible then it returns false`() = runTest {
|
||||||
|
// Given
|
||||||
|
val deviceInfo1 = givenADeviceInfo("")
|
||||||
|
val deviceInfo2 = givenADeviceInfo(null)
|
||||||
|
|
||||||
|
// When
|
||||||
|
val result1 = checkIfSectionDeviceIsVisibleUseCase.execute(deviceInfo1)
|
||||||
|
val result2 = checkIfSectionDeviceIsVisibleUseCase.execute(deviceInfo2)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result1 shouldBeEqualTo false
|
||||||
|
result2 shouldBeEqualTo false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenADeviceInfo(ipAddress: String?): DeviceInfo {
|
||||||
|
val info = mockk<DeviceInfo>()
|
||||||
|
every { info.lastSeenIp } returns ipAddress
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
|
||||||
|
private const val A_SESSION_NAME = "session-name"
|
||||||
|
private const val A_SESSION_ID = "session-id"
|
||||||
|
private const val A_LAST_SEEN_TS = 123L
|
||||||
|
|
||||||
|
class CheckIfSectionSessionIsVisibleUseCaseTest {
|
||||||
|
|
||||||
|
private val checkIfSectionSessionIsVisibleUseCase = CheckIfSectionSessionIsVisibleUseCase()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given device info with name, id or lastSeenTs when checking is session section is visible then it returns true`() = runTest {
|
||||||
|
// Given
|
||||||
|
val deviceInfoList = listOf(
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = A_SESSION_NAME,
|
||||||
|
sessionId = null,
|
||||||
|
lastSeenTs = null,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = null,
|
||||||
|
sessionId = A_SESSION_ID,
|
||||||
|
lastSeenTs = null,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = null,
|
||||||
|
sessionId = null,
|
||||||
|
lastSeenTs = A_LAST_SEEN_TS,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = A_SESSION_NAME,
|
||||||
|
sessionId = A_SESSION_ID,
|
||||||
|
lastSeenTs = null,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = A_SESSION_NAME,
|
||||||
|
sessionId = null,
|
||||||
|
lastSeenTs = A_LAST_SEEN_TS,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = null,
|
||||||
|
sessionId = A_SESSION_ID,
|
||||||
|
lastSeenTs = A_LAST_SEEN_TS,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = A_SESSION_NAME,
|
||||||
|
sessionId = A_SESSION_ID,
|
||||||
|
lastSeenTs = A_LAST_SEEN_TS,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
deviceInfoList.forEach { deviceInfo ->
|
||||||
|
// When
|
||||||
|
val result = checkIfSectionSessionIsVisibleUseCase.execute(deviceInfo)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result shouldBeEqualTo true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given device info with missing session info when checking is session section is visible then it returns true`() = runTest {
|
||||||
|
// Given
|
||||||
|
val deviceInfoList = listOf(
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = null,
|
||||||
|
sessionId = null,
|
||||||
|
lastSeenTs = null,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = "",
|
||||||
|
sessionId = "",
|
||||||
|
lastSeenTs = null,
|
||||||
|
),
|
||||||
|
givenADeviceInfo(
|
||||||
|
sessionName = "",
|
||||||
|
sessionId = "",
|
||||||
|
lastSeenTs = -1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
deviceInfoList.forEach { deviceInfo ->
|
||||||
|
// When
|
||||||
|
val result = checkIfSectionSessionIsVisibleUseCase.execute(deviceInfo)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result shouldBeEqualTo false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenADeviceInfo(
|
||||||
|
sessionName: String?,
|
||||||
|
sessionId: String?,
|
||||||
|
lastSeenTs: Long?,
|
||||||
|
): DeviceInfo {
|
||||||
|
val info = mockk<DeviceInfo>()
|
||||||
|
every { info.displayName } returns sessionName
|
||||||
|
every { info.deviceId } returns sessionId
|
||||||
|
every { info.lastSeenTs } returns lastSeenTs
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.details
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.test.MvRxTestRule
|
||||||
|
import im.vector.app.core.utils.CopyToClipboardUseCase
|
||||||
|
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
|
||||||
|
import im.vector.app.features.settings.devices.v2.overview.GetDeviceFullInfoUseCase
|
||||||
|
import im.vector.app.test.test
|
||||||
|
import im.vector.app.test.testDispatcher
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.just
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.runs
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
|
||||||
|
private const val A_SESSION_ID = "session-id"
|
||||||
|
private const val A_TEXT = "text"
|
||||||
|
|
||||||
|
class SessionDetailsViewModelTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val mvRxTestRule = MvRxTestRule(testDispatcher = testDispatcher)
|
||||||
|
|
||||||
|
private val args = SessionDetailsArgs(
|
||||||
|
deviceId = A_SESSION_ID
|
||||||
|
)
|
||||||
|
private val getDeviceFullInfoUseCase = mockk<GetDeviceFullInfoUseCase>()
|
||||||
|
private val copyToClipboardUseCase = mockk<CopyToClipboardUseCase>()
|
||||||
|
|
||||||
|
private fun createViewModel() = SessionDetailsViewModel(
|
||||||
|
initialState = SessionDetailsViewState(args),
|
||||||
|
getDeviceFullInfoUseCase = getDeviceFullInfoUseCase,
|
||||||
|
copyToClipboardUseCase = copyToClipboardUseCase,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given the viewModel has been initialized then viewState is updated with session info`() {
|
||||||
|
// Given
|
||||||
|
val deviceFullInfo = mockk<DeviceFullInfo>()
|
||||||
|
val deviceInfo = mockk<DeviceInfo>()
|
||||||
|
every { deviceFullInfo.deviceInfo } returns deviceInfo
|
||||||
|
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID) } returns flowOf(deviceFullInfo)
|
||||||
|
val expectedState = SessionDetailsViewState(
|
||||||
|
deviceId = A_SESSION_ID,
|
||||||
|
deviceInfo = Success(deviceInfo)
|
||||||
|
)
|
||||||
|
|
||||||
|
// When
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
|
// Then
|
||||||
|
viewModel.test()
|
||||||
|
.assertLatestState { state -> state == expectedState }
|
||||||
|
.finish()
|
||||||
|
verify { getDeviceFullInfoUseCase.execute(A_SESSION_ID) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given copyToClipboard action when viewModel handle it then related use case is executed and viewEvent is updated`() {
|
||||||
|
// Given
|
||||||
|
val deviceFullInfo = mockk<DeviceFullInfo>()
|
||||||
|
val deviceInfo = mockk<DeviceInfo>()
|
||||||
|
every { deviceFullInfo.deviceInfo } returns deviceInfo
|
||||||
|
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID) } returns flowOf(deviceFullInfo)
|
||||||
|
val action = SessionDetailsAction.CopyToClipboard(A_TEXT)
|
||||||
|
every { copyToClipboardUseCase.execute(any()) } just runs
|
||||||
|
|
||||||
|
// When
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
val viewModelTest = viewModel.test()
|
||||||
|
viewModel.handle(action)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
viewModelTest
|
||||||
|
.assertEvent { it is SessionDetailsViewEvent.ContentCopiedToClipboard }
|
||||||
|
.finish()
|
||||||
|
verify { copyToClipboardUseCase.execute(A_TEXT) }
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,7 @@ import kotlinx.coroutines.flow.firstOrNull
|
|||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.amshove.kluent.shouldBeEqualTo
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.amshove.kluent.shouldBeNull
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -72,6 +73,7 @@ class GetDeviceFullInfoUseCaseTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given current session and info for device when getting device info then the result is correct`() = runTest {
|
fun `given current session and info for device when getting device info then the result is correct`() = runTest {
|
||||||
|
// Given
|
||||||
val currentSessionCrossSigningInfo = givenCurrentSessionCrossSigningInfo()
|
val currentSessionCrossSigningInfo = givenCurrentSessionCrossSigningInfo()
|
||||||
val deviceInfo = DeviceInfo(
|
val deviceInfo = DeviceInfo(
|
||||||
lastSeenTs = A_TIMESTAMP
|
lastSeenTs = A_TIMESTAMP
|
||||||
@ -85,15 +87,15 @@ class GetDeviceFullInfoUseCaseTest {
|
|||||||
val isInactive = false
|
val isInactive = false
|
||||||
every { checkIfSessionIsInactiveUseCase.execute(any()) } returns isInactive
|
every { checkIfSessionIsInactiveUseCase.execute(any()) } returns isInactive
|
||||||
|
|
||||||
|
// When
|
||||||
val deviceFullInfo = getDeviceFullInfoUseCase.execute(A_DEVICE_ID).firstOrNull()
|
val deviceFullInfo = getDeviceFullInfoUseCase.execute(A_DEVICE_ID).firstOrNull()
|
||||||
|
|
||||||
deviceFullInfo shouldBeEqualTo Optional(
|
// Then
|
||||||
DeviceFullInfo(
|
deviceFullInfo shouldBeEqualTo DeviceFullInfo(
|
||||||
deviceInfo = deviceInfo,
|
deviceInfo = deviceInfo,
|
||||||
cryptoDeviceInfo = cryptoDeviceInfo,
|
cryptoDeviceInfo = cryptoDeviceInfo,
|
||||||
roomEncryptionTrustLevel = trustLevel,
|
roomEncryptionTrustLevel = trustLevel,
|
||||||
isInactive = isInactive,
|
isInactive = isInactive,
|
||||||
)
|
|
||||||
)
|
)
|
||||||
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
||||||
verify { getCurrentSessionCrossSigningInfoUseCase.execute() }
|
verify { getCurrentSessionCrossSigningInfoUseCase.execute() }
|
||||||
@ -104,16 +106,19 @@ class GetDeviceFullInfoUseCaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given current session and no info for device when getting device info then the result is null`() = runTest {
|
fun `given current session and no info for device when getting device info then the result is empty`() = runTest {
|
||||||
|
// Given
|
||||||
givenCurrentSessionCrossSigningInfo()
|
givenCurrentSessionCrossSigningInfo()
|
||||||
fakeActiveSessionHolder.fakeSession.fakeCryptoService.myDevicesInfoWithIdLiveData = MutableLiveData(Optional(null))
|
fakeActiveSessionHolder.fakeSession.fakeCryptoService.myDevicesInfoWithIdLiveData = MutableLiveData(Optional(null))
|
||||||
fakeActiveSessionHolder.fakeSession.fakeCryptoService.myDevicesInfoWithIdLiveData.givenAsFlow()
|
fakeActiveSessionHolder.fakeSession.fakeCryptoService.myDevicesInfoWithIdLiveData.givenAsFlow()
|
||||||
fakeActiveSessionHolder.fakeSession.fakeCryptoService.cryptoDeviceInfoWithIdLiveData = MutableLiveData(Optional(null))
|
fakeActiveSessionHolder.fakeSession.fakeCryptoService.cryptoDeviceInfoWithIdLiveData = MutableLiveData(Optional(null))
|
||||||
fakeActiveSessionHolder.fakeSession.fakeCryptoService.cryptoDeviceInfoWithIdLiveData.givenAsFlow()
|
fakeActiveSessionHolder.fakeSession.fakeCryptoService.cryptoDeviceInfoWithIdLiveData.givenAsFlow()
|
||||||
|
|
||||||
|
// When
|
||||||
val deviceFullInfo = getDeviceFullInfoUseCase.execute(A_DEVICE_ID).firstOrNull()
|
val deviceFullInfo = getDeviceFullInfoUseCase.execute(A_DEVICE_ID).firstOrNull()
|
||||||
|
|
||||||
deviceFullInfo shouldBeEqualTo Optional(null)
|
// Then
|
||||||
|
deviceFullInfo.shouldBeNull()
|
||||||
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
||||||
verify { fakeActiveSessionHolder.fakeSession.fakeCryptoService.getMyDevicesInfoLive(A_DEVICE_ID).asFlow() }
|
verify { fakeActiveSessionHolder.fakeSession.fakeCryptoService.getMyDevicesInfoLive(A_DEVICE_ID).asFlow() }
|
||||||
verify { fakeActiveSessionHolder.fakeSession.fakeCryptoService.getLiveCryptoDeviceInfoWithId(A_DEVICE_ID).asFlow() }
|
verify { fakeActiveSessionHolder.fakeSession.fakeCryptoService.getLiveCryptoDeviceInfoWithId(A_DEVICE_ID).asFlow() }
|
||||||
@ -121,11 +126,14 @@ class GetDeviceFullInfoUseCaseTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given no current session when getting device info then the result is empty`() = runTest {
|
fun `given no current session when getting device info then the result is empty`() = runTest {
|
||||||
|
// Given
|
||||||
fakeActiveSessionHolder.givenGetSafeActiveSessionReturns(null)
|
fakeActiveSessionHolder.givenGetSafeActiveSessionReturns(null)
|
||||||
|
|
||||||
|
// When
|
||||||
val deviceFullInfo = getDeviceFullInfoUseCase.execute(A_DEVICE_ID).firstOrNull()
|
val deviceFullInfo = getDeviceFullInfoUseCase.execute(A_DEVICE_ID).firstOrNull()
|
||||||
|
|
||||||
deviceFullInfo shouldBeEqualTo null
|
// Then
|
||||||
|
deviceFullInfo.shouldBeNull()
|
||||||
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,22 +21,21 @@ import com.airbnb.mvrx.test.MvRxTestRule
|
|||||||
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
|
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
|
||||||
import im.vector.app.test.fakes.FakeSession
|
import im.vector.app.test.fakes.FakeSession
|
||||||
import im.vector.app.test.test
|
import im.vector.app.test.test
|
||||||
|
import im.vector.app.test.testDispatcher
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.matrix.android.sdk.api.auth.data.SessionParams
|
import org.matrix.android.sdk.api.auth.data.SessionParams
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
|
||||||
|
|
||||||
private const val A_SESSION_ID = "session-id"
|
private const val A_SESSION_ID = "session-id"
|
||||||
|
|
||||||
class SessionOverviewViewModelTest {
|
class SessionOverviewViewModelTest {
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val mvRxTestRule = MvRxTestRule(testDispatcher = UnconfinedTestDispatcher())
|
val mvRxTestRule = MvRxTestRule(testDispatcher = testDispatcher)
|
||||||
|
|
||||||
private val args = SessionOverviewArgs(
|
private val args = SessionOverviewArgs(
|
||||||
deviceId = A_SESSION_ID
|
deviceId = A_SESSION_ID
|
||||||
@ -52,17 +51,20 @@ class SessionOverviewViewModelTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given the viewModel has been initialized then viewState is updated with session info`() {
|
fun `given the viewModel has been initialized then viewState is updated with session info`() {
|
||||||
|
// Given
|
||||||
val sessionParams = givenIdForSession(A_SESSION_ID)
|
val sessionParams = givenIdForSession(A_SESSION_ID)
|
||||||
val deviceFullInfo = mockk<DeviceFullInfo>()
|
val deviceFullInfo = mockk<DeviceFullInfo>()
|
||||||
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID) } returns flowOf(Optional(deviceFullInfo))
|
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID) } returns flowOf(deviceFullInfo)
|
||||||
val expectedState = SessionOverviewViewState(
|
val expectedState = SessionOverviewViewState(
|
||||||
deviceId = A_SESSION_ID,
|
deviceId = A_SESSION_ID,
|
||||||
isCurrentSession = true,
|
isCurrentSession = true,
|
||||||
deviceInfo = Success(deviceFullInfo)
|
deviceInfo = Success(deviceFullInfo)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// When
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
|
// Then
|
||||||
viewModel.test()
|
viewModel.test()
|
||||||
.assertLatestState { state -> state == expectedState }
|
.assertLatestState { state -> state == expectedState }
|
||||||
.finish()
|
.finish()
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings.devices.v2.overview
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import im.vector.app.features.settings.devices.v2.details.SessionDetailsActivity
|
||||||
|
import im.vector.app.test.fakes.FakeContext
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkObject
|
||||||
|
import io.mockk.unmockkAll
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
private const val A_SESSION_ID = "session_id"
|
||||||
|
|
||||||
|
class SessionOverviewViewNavigatorTest {
|
||||||
|
|
||||||
|
private val context = FakeContext()
|
||||||
|
private val sessionOverviewViewNavigator = SessionOverviewViewNavigator()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
mockkObject(SessionDetailsActivity)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
unmockkAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a session id when navigating to details then it starts the correct activity`() {
|
||||||
|
// Given
|
||||||
|
val intent = givenIntentForSessionDetails(A_SESSION_ID)
|
||||||
|
context.givenStartActivity(intent)
|
||||||
|
|
||||||
|
// When
|
||||||
|
sessionOverviewViewNavigator.navigateToSessionDetails(context.instance, A_SESSION_ID)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
verify {
|
||||||
|
context.instance.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenIntentForSessionDetails(sessionId: String): Intent {
|
||||||
|
val intent = mockk<Intent>()
|
||||||
|
every { SessionDetailsActivity.newIntent(context.instance, sessionId) } returns intent
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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 android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.just
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.runs
|
||||||
|
import io.mockk.verify
|
||||||
|
|
||||||
|
class FakeClipboardManager {
|
||||||
|
val instance = mockk<ClipboardManager>()
|
||||||
|
|
||||||
|
fun givenSetPrimaryClip() {
|
||||||
|
every { instance.setPrimaryClip(any()) } just runs
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifySetPrimaryClip(clipData: ClipData) {
|
||||||
|
verify { instance.setPrimaryClip(clipData) }
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package im.vector.app.test.fakes
|
package im.vector.app.test.fakes
|
||||||
|
|
||||||
|
import android.content.ClipboardManager
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -74,4 +75,10 @@ class FakeContext(
|
|||||||
fun givenStartActivity(intent: Intent) {
|
fun givenStartActivity(intent: Intent) {
|
||||||
every { instance.startActivity(intent) } just runs
|
every { instance.startActivity(intent) } just runs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun givenClipboardManager(): FakeClipboardManager {
|
||||||
|
val fakeClipboardManager = FakeClipboardManager()
|
||||||
|
givenService(Context.CLIPBOARD_SERVICE, ClipboardManager::class.java, fakeClipboardManager.instance)
|
||||||
|
return fakeClipboardManager
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user