Merge branch 'develop' into feature/bma/android12
This commit is contained in:
commit
b9c28ba4ce
|
@ -31,7 +31,7 @@ jobs:
|
|||
ui-tests:
|
||||
name: UI Tests (Synapse)
|
||||
needs: should-i-run
|
||||
runs-on: macos-latest
|
||||
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
|
@ -13,7 +13,10 @@ env:
|
|||
jobs:
|
||||
tests:
|
||||
name: Runs all tests
|
||||
runs-on: macos-latest # for the emulator
|
||||
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||
strategy:
|
||||
matrix:
|
||||
api-level: [28]
|
||||
# Allow all jobs on main and develop. Just one per PR.
|
||||
concurrency:
|
||||
group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }}
|
||||
|
@ -36,40 +39,70 @@ jobs:
|
|||
httpPort: 8080
|
||||
disableRateLimiting: true
|
||||
public_baseurl: "http://10.0.2.2:8080/"
|
||||
|
||||
- name: AVD cache
|
||||
uses: actions/cache@v3
|
||||
id: avd-cache
|
||||
with:
|
||||
path: |
|
||||
~/.android/avd/*
|
||||
~/.android/adb*
|
||||
key: avd-${{ matrix.api-level }}
|
||||
|
||||
- name: create AVD and generate snapshot for caching
|
||||
if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: true # Is set to false in the doc https://github.com/ReactiveCircus/android-emulator-runner
|
||||
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
disable-animations: true
|
||||
script: echo "Generated AVD snapshot for caching."
|
||||
|
||||
- name: Run all the codecoverage tests at once
|
||||
id: tests
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
continue-on-error: true
|
||||
# continue-on-error: true
|
||||
with:
|
||||
api-level: 28
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
disable-animations: true
|
||||
emulator-build: 7425822
|
||||
# emulator-build: 7425822
|
||||
script: |
|
||||
./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||
# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves stes.tests.outcome = 'failure'
|
||||
- name: Run all the codecoverage tests at once (retry if emulator failed)
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded.
|
||||
# NB: continue-on-error marks steps.tests.conclusion = 'success' but leaves steps.tests.outcome = 'failure'
|
||||
### - name: Run all the codecoverage tests at once (retry if emulator failed)
|
||||
### uses: reactivecircus/android-emulator-runner@v2
|
||||
### if: always() && steps.tests.outcome == 'failure' # don't run if previous step succeeded.
|
||||
### with:
|
||||
### api-level: 28
|
||||
### arch: x86
|
||||
### profile: Nexus 5X
|
||||
### force-avd-creation: false
|
||||
### emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
### disable-animations: true
|
||||
### emulator-build: 7425822
|
||||
### script: |
|
||||
### ./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
|
||||
### ./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
### ./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
### ./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||
|
||||
- name: Upload Integration Test Report Log
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
api-level: 28
|
||||
arch: x86
|
||||
profile: Nexus 5X
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
disable-animations: true
|
||||
emulator-build: 7425822
|
||||
script: |
|
||||
./gradlew gatherGplayDebugStringTemplates $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew unitTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew instrumentationTestsWithCoverage $CI_GRADLE_ARG_PROPERTIES
|
||||
./gradlew generateCoverageReport $CI_GRADLE_ARG_PROPERTIES
|
||||
name: integration-test-error-results
|
||||
path: |
|
||||
*/build/outputs/androidTest-results/connected/
|
||||
*/build/reports/androidTests/connected/
|
||||
|
||||
# we may have failed a previous step and retried, that's OK
|
||||
- name: Publish results to Sonar
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Create DM room only on first message - Add a spinner when sending the first message
|
|
@ -0,0 +1 @@
|
|||
[Device Manager] Filter Other Sessions
|
|
@ -0,0 +1 @@
|
|||
Fixed problem when room list's scroll did jump after rooms placeholders were replaced with rooms summary items
|
|
@ -0,0 +1 @@
|
|||
Move some GitHub actions to buildjet runners, and remove the second attempt to run integration tests.
|
|
@ -0,0 +1 @@
|
|||
Create DM room only on first message - Handle the local rooms within the new AppLayout
|
|
@ -0,0 +1 @@
|
|||
New App Layout is now enabled by default! Go to the Settings > Labs to toggle this
|
|
@ -0,0 +1 @@
|
|||
Deferred DMs - Enable and move the feature to labs settings
|
|
@ -0,0 +1 @@
|
|||
Fixes Room List not getting updated when fragment is not in focus
|
|
@ -320,7 +320,7 @@
|
|||
<string name="settings_theme">السمة</string>
|
||||
<string name="encryption_information_decryption_error">خطأ في فكّ التعمية</string>
|
||||
<string name="encryption_information_device_name">اسم الجهاز</string>
|
||||
<string name="device_manager_session_details_session_id">معرّف الجهاز</string>
|
||||
<string name="encryption_information_device_id">معرّف الجهاز</string>
|
||||
<string name="encryption_information_device_key">مفتاح الجهاز</string>
|
||||
<string name="encryption_export_room_keys">صدّر مفاتيح الغرفة</string>
|
||||
<string name="encryption_export_room_keys_summary">صدّر المفاتيح إلى ملف محلي</string>
|
||||
|
|
|
@ -396,7 +396,7 @@
|
|||
<string name="settings_theme">Тема</string>
|
||||
<string name="encryption_information_decryption_error">Грешка при разшифроване</string>
|
||||
<string name="encryption_information_device_name">Публично име</string>
|
||||
<string name="device_manager_session_details_session_id">Сесийно ID</string>
|
||||
<string name="encryption_information_device_id">Сесийно ID</string>
|
||||
<string name="encryption_information_device_key">Ключ на устройство</string>
|
||||
<string name="encryption_export_e2e_room_keys">Експортирай E2E ключове за стая</string>
|
||||
<string name="encryption_export_room_keys">Експортиране на ключове за стая</string>
|
||||
|
|
|
@ -789,7 +789,7 @@
|
|||
<string name="encryption_export_room_keys">রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
||||
<string name="encryption_export_e2e_room_keys">শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
||||
<string name="encryption_information_device_key">সেশানের কুঞ্জি</string>
|
||||
<string name="device_manager_session_details_session_id">আইডি</string>
|
||||
<string name="encryption_information_device_id">আইডি</string>
|
||||
<string name="encryption_information_device_name">সর্বজনীন নাম</string>
|
||||
<string name="encryption_information_decryption_error">ডিক্রিপশন সমস্যা</string>
|
||||
<string name="settings_theme">থিম</string>
|
||||
|
|
|
@ -693,7 +693,7 @@
|
|||
<string name="encryption_information_decryption_error">ডিক্রিপশন সমস্যা</string>
|
||||
|
||||
<string name="encryption_information_device_name">সর্বজনীন নাম</string>
|
||||
<string name="device_manager_session_details_session_id">আইডি</string>
|
||||
<string name="encryption_information_device_id">আইডি</string>
|
||||
<string name="encryption_information_device_key">সেশানের কুঞ্জি</string>
|
||||
|
||||
<string name="encryption_export_e2e_room_keys">শেষ থেকে শেষ রুমের কুঞ্জিগুলি এক্সপোর্ট করুন</string>
|
||||
|
|
|
@ -448,7 +448,7 @@
|
|||
<string name="settings_theme">Tema</string>
|
||||
<string name="encryption_information_decryption_error">Error al desxifrar</string>
|
||||
<string name="encryption_information_device_name">Nom públic</string>
|
||||
<string name="device_manager_session_details_session_id">ID de sessió</string>
|
||||
<string name="encryption_information_device_id">ID 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_room_keys">Exporta les claus de la sala</string>
|
||||
|
|
|
@ -635,7 +635,7 @@
|
|||
<string name="settings_theme">Motiv vzhledu</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="device_manager_session_details_session_id">ID relace</string>
|
||||
<string name="encryption_information_device_id">ID 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_room_keys">Export klíčů místností</string>
|
||||
|
|
|
@ -418,7 +418,7 @@
|
|||
<string name="room_settings_unset_main_address">Als Hauptadresse aufheben</string>
|
||||
<string name="encryption_information_decryption_error">Entschlüsselungsfehler</string>
|
||||
<string name="encryption_information_device_name">Öffentlicher Name</string>
|
||||
<string name="device_manager_session_details_session_id">Sitzungs-ID</string>
|
||||
<string name="encryption_information_device_id">Sitzungs-ID</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_room_keys">Raumschlüssel exportieren</string>
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
<string name="settings_theme">Θέμα</string>
|
||||
<string name="encryption_information_decryption_error">Σφάλμα αποκρυπτογράφησης</string>
|
||||
<string name="encryption_information_device_name">Όνομα συσκευής</string>
|
||||
<string name="device_manager_session_details_session_id">Αναγνωριστικό συσκευής</string>
|
||||
<string name="encryption_information_device_id">Αναγνωριστικό συσκευής</string>
|
||||
<string name="encryption_export_export">Εξαγωγή</string>
|
||||
<string name="encryption_import_import">Εισαγωγή</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_e2e_room_keys">Elporti tutvoje ĉifrajn ŝlosilojn de ĉambroj</string>
|
||||
<string name="encryption_information_device_key">Ŝlosilo de salutaĵo</string>
|
||||
<string name="device_manager_session_details_session_id">Identigilo de salutaĵo</string>
|
||||
<string name="encryption_information_device_id">Identigilo de salutaĵo</string>
|
||||
<string name="encryption_information_device_name">Publika nomo</string>
|
||||
<string name="encryption_information_decryption_error">Eraris malĉifrado</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="encryption_information_decryption_error">Error en descifrar</string>
|
||||
<string name="encryption_information_device_name">Nombre del dispositivo</string>
|
||||
<string name="device_manager_session_details_session_id">Identificación del dispositivo</string>
|
||||
<string name="encryption_information_device_id">Identificación 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_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="encryption_information_decryption_error">Error de descifrado</string>
|
||||
<string name="encryption_information_device_name">Nombre público</string>
|
||||
<string name="device_manager_session_details_session_id">ID de sesión</string>
|
||||
<string name="encryption_information_device_id">ID 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_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="encryption_information_decryption_error">Dekrüptimise viga</string>
|
||||
<string name="encryption_information_device_name">Avalik nimi</string>
|
||||
<string name="device_manager_session_details_session_id">Sessiooni tunnus</string>
|
||||
<string name="encryption_information_device_id">Sessiooni tunnus</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_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_device_name">Izen publikoa</string>
|
||||
<string name="device_manager_session_details_session_id">IDa</string>
|
||||
<string name="encryption_information_device_id">IDa</string>
|
||||
<string name="encryption_information_device_key">Saioaren gakoa</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_set_main_address">تنظیم به عنوان نشانی اصلی</string>
|
||||
<string name="encryption_information_device_name">نام عمومی</string>
|
||||
<string name="device_manager_session_details_session_id">شناسهٔ نشست</string>
|
||||
<string name="encryption_information_device_id">شناسهٔ نشست</string>
|
||||
<string name="encryption_information_device_key">کلید نشست</string>
|
||||
<string name="encryption_export_e2e_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="encryption_information_decryption_error">Salauksenpurkuvirhe</string>
|
||||
<string name="encryption_information_device_name">Julkinen nimi</string>
|
||||
<string name="device_manager_session_details_session_id">Istunnon tunnus</string>
|
||||
<string name="encryption_information_device_id">Istunnon tunnus</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_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_e2e_room_keys">Exporter les clés E2E des salons</string>
|
||||
<string name="encryption_information_device_key">Clé de la session</string>
|
||||
<string name="device_manager_session_details_session_id">Identifiant de session</string>
|
||||
<string name="encryption_information_device_id">Identifiant de session</string>
|
||||
<string name="encryption_information_device_name">Nom public</string>
|
||||
<string name="encryption_information_decryption_error">Erreur de déchiffrement</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="encryption_information_decryption_error">Erreur de déchiffrement</string>
|
||||
<string name="encryption_information_device_name">Nom public</string>
|
||||
<string name="device_manager_session_details_session_id">Identifiant de session</string>
|
||||
<string name="encryption_information_device_id">Identifiant de 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_room_keys">Exporter les clés des salons</string>
|
||||
|
|
|
@ -380,7 +380,7 @@
|
|||
<string name="settings_theme">Tema</string>
|
||||
<string name="encryption_information_decryption_error">Fallo ao descifrar</string>
|
||||
<string name="encryption_information_device_name">Nome do dispositivo</string>
|
||||
<string name="device_manager_session_details_session_id">ID de sesión</string>
|
||||
<string name="encryption_information_device_id">ID de sesión</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_room_keys">Exportar chaves da sala</string>
|
||||
|
|
|
@ -572,7 +572,7 @@
|
|||
<string name="settings_theme">Tema</string>
|
||||
<string name="encryption_information_decryption_error">Greška u dešifriranju</string>
|
||||
<string name="encryption_information_device_name">Javni naziv</string>
|
||||
<string name="device_manager_session_details_session_id">Identitet</string>
|
||||
<string name="encryption_information_device_id">Identitet</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_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="encryption_information_decryption_error">Visszafejtés hiba</string>
|
||||
<string name="encryption_information_device_name">Nyilvános név</string>
|
||||
<string name="device_manager_session_details_session_id">Munkamenet-azonosító</string>
|
||||
<string name="encryption_information_device_id">Munkamenet-azonosító</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_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="encryption_information_decryption_error">Kesalahan dekripsi</string>
|
||||
<string name="encryption_information_device_name">Nama perangkat</string>
|
||||
<string name="device_manager_session_details_session_id">ID Sesi</string>
|
||||
<string name="encryption_information_device_id">ID Sesi</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_room_keys">Ekspor ruangan kunci</string>
|
||||
|
|
|
@ -193,7 +193,7 @@
|
|||
<string name="settings_theme">Þema</string>
|
||||
<string name="encryption_information_decryption_error">Afkóðunarvilla</string>
|
||||
<string name="encryption_information_device_name">Heiti tækis</string>
|
||||
<string name="device_manager_session_details_session_id">Auðkenni setu</string>
|
||||
<string name="encryption_information_device_id">Auðkenni setu</string>
|
||||
<string name="encryption_information_device_key">Dulritunarlykill setu</string>
|
||||
<string name="encryption_export_export">Flytja út</string>
|
||||
<string name="passphrase_enter_passphrase">Settu inn lykilsetningu</string>
|
||||
|
|
|
@ -430,7 +430,7 @@
|
|||
<string name="settings_theme">Tema</string>
|
||||
<string name="encryption_information_decryption_error">Errore di decriptazione</string>
|
||||
<string name="encryption_information_device_name">Nome pubblico</string>
|
||||
<string name="device_manager_session_details_session_id">ID sessione</string>
|
||||
<string name="encryption_information_device_id">ID 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_room_keys">Esporta le chiavi delle stanze</string>
|
||||
|
|
|
@ -542,7 +542,7 @@
|
|||
<string name="encryption_export_room_keys">יצא מפתחות חדר</string>
|
||||
<string name="encryption_export_e2e_room_keys">ייצא מפתחות חדר E2E</string>
|
||||
<string name="encryption_information_device_key">מזהה מפתח</string>
|
||||
<string name="device_manager_session_details_session_id">מזהה מושב</string>
|
||||
<string name="encryption_information_device_id">מזהה מושב</string>
|
||||
<string name="encryption_information_device_name">שם ציבורי</string>
|
||||
<string name="encryption_information_decryption_error">שגיאת פענוח</string>
|
||||
<string name="settings_theme">ערכת נושא</string>
|
||||
|
|
|
@ -197,7 +197,7 @@
|
|||
<string name="room_settings_labs_warning_message">これらは予期しない不具合が生じるかもしれない実験的機能です。慎重に使用してください。</string>
|
||||
<string name="room_settings_set_main_address">メインアドレスとして設定</string>
|
||||
<string name="room_settings_unset_main_address">メインアドレスとしての設定を解除</string>
|
||||
<string name="device_manager_session_details_session_id">セッションID</string>
|
||||
<string name="encryption_information_device_id">セッションID</string>
|
||||
<string name="font_size">文字の大きさ</string>
|
||||
<string name="tiny">とても小さい</string>
|
||||
<string name="small">小さい</string>
|
||||
|
|
|
@ -291,7 +291,7 @@
|
|||
<string name="room_settings_category_advanced_title">Talqayt</string>
|
||||
<string name="room_settings_labs_pref_title">Tinarimin</string>
|
||||
<string name="settings_theme">Asentel</string>
|
||||
<string name="device_manager_session_details_session_id">Asulay n tqimit</string>
|
||||
<string name="encryption_information_device_id">Asulay n tqimit</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_room_keys">Sifeḍ tisura n texxamt</string>
|
||||
|
|
|
@ -431,7 +431,7 @@
|
|||
<string name="settings_theme">테마</string>
|
||||
<string name="encryption_information_decryption_error">암호 복호화 오류</string>
|
||||
<string name="encryption_information_device_name">공개 이름</string>
|
||||
<string name="device_manager_session_details_session_id">ID</string>
|
||||
<string name="encryption_information_device_id">ID</string>
|
||||
<string name="encryption_information_device_key">기기 키</string>
|
||||
<string name="encryption_export_e2e_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_e2e_room_keys">ສົ່ງອອກກະແຈຫ້ອງ E2E</string>
|
||||
<string name="encryption_information_device_key">ລະຫັດລະບົບ</string>
|
||||
<string name="device_manager_session_details_session_id">ID ລະບົບ</string>
|
||||
<string name="encryption_information_device_id">ID ລະບົບ</string>
|
||||
<string name="encryption_information_device_name">ຊື່ສາທາລະນະ</string>
|
||||
<string name="encryption_information_decryption_error">ການຖອດລະຫັດຜິດພາດ</string>
|
||||
<string name="settings_theme">ຫົວຂໍ້</string>
|
||||
|
|
|
@ -469,7 +469,7 @@
|
|||
<string name="settings_theme">Tēma</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="device_manager_session_details_session_id">Sesijas ID</string>
|
||||
<string name="encryption_information_device_id">Sesijas ID</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_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_category_advanced_title">Avansert</string>
|
||||
<string name="settings_theme">Tema</string>
|
||||
<string name="device_manager_session_details_session_id">Økt-ID</string>
|
||||
<string name="encryption_information_device_id">Økt-ID</string>
|
||||
<string name="encryption_information_device_key">Øktnøkkel</string>
|
||||
<string name="encryption_export_export">Eksporter</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="encryption_information_decryption_error">Ontsleutelingsfout</string>
|
||||
<string name="encryption_information_device_name">Publieke naam</string>
|
||||
<string name="device_manager_session_details_session_id">Sessie ID</string>
|
||||
<string name="encryption_information_device_id">Sessie ID</string>
|
||||
<string name="encryption_information_device_key">Sessiesleutel</string>
|
||||
<string name="encryption_export_e2e_room_keys">E2E-gesprekssleutels exporteren</string>
|
||||
<string name="encryption_export_room_keys">Gesprekssleutels exporteren</string>
|
||||
|
|
|
@ -310,7 +310,7 @@
|
|||
<string name="settings_theme">Preg</string>
|
||||
<string name="encryption_information_decryption_error">Noko gjekk gale med dekrypteringa</string>
|
||||
<string name="encryption_information_device_name">Offentleg namn</string>
|
||||
<string name="device_manager_session_details_session_id">Økt-ID</string>
|
||||
<string name="encryption_information_device_id">Økt-ID</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_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="settings_theme">Motyw</string>
|
||||
<string name="encryption_information_device_name">Nazwa publiczna</string>
|
||||
<string name="device_manager_session_details_session_id">ID sesji</string>
|
||||
<string name="encryption_information_device_id">ID sesji</string>
|
||||
<string name="encryption_export_export">Eksportuj</string>
|
||||
<string name="passphrase_enter_passphrase">Wprowadź hasło</string>
|
||||
<string name="passphrase_confirm_passphrase">Potwierdź hasło</string>
|
||||
|
|
|
@ -418,7 +418,7 @@
|
|||
<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_device_name">Nome público</string>
|
||||
<string name="device_manager_session_details_session_id">ID de sessão</string>
|
||||
<string name="encryption_information_device_id">ID 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_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_device_name">Nome do dispositivo</string>
|
||||
<string name="device_manager_session_details_session_id">ID do dispositivo</string>
|
||||
<string name="encryption_information_device_id">ID 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_room_keys">Exportar chaves de sala</string>
|
||||
|
|
|
@ -432,7 +432,7 @@
|
|||
<string name="room_settings_unset_main_address">Сбросить основной адрес</string>
|
||||
<string name="encryption_information_decryption_error">Ошибка дешифровки</string>
|
||||
<string name="encryption_information_device_name">Публичное имя</string>
|
||||
<string name="device_manager_session_details_session_id">ID сессии</string>
|
||||
<string name="encryption_information_device_id">ID сессии</string>
|
||||
<string name="encryption_information_device_key">Ключ сессии</string>
|
||||
<string name="encryption_export_e2e_room_keys">Экспорт E2E ключей комнаты</string>
|
||||
<string name="encryption_export_room_keys">Экспорт ключей комнаты</string>
|
||||
|
|
|
@ -388,7 +388,7 @@
|
|||
<string name="settings_theme">Vzhľad</string>
|
||||
<string name="encryption_information_decryption_error">Chyba dešifrovania</string>
|
||||
<string name="encryption_information_device_name">Verejné meno</string>
|
||||
<string name="device_manager_session_details_session_id">ID relácie</string>
|
||||
<string name="encryption_information_device_id">ID 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_room_keys">Exportovať kľúče miestnosti</string>
|
||||
|
|
|
@ -431,7 +431,7 @@
|
|||
<string name="settings_theme">Temë</string>
|
||||
<string name="encryption_information_decryption_error">Gabim shfshehtëzimi</string>
|
||||
<string name="encryption_information_device_name">Emër publik</string>
|
||||
<string name="device_manager_session_details_session_id">ID Sesioni</string>
|
||||
<string name="encryption_information_device_id">ID 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_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="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="device_manager_session_details_session_id">Sessions-ID</string>
|
||||
<string name="encryption_information_device_id">Sessions-ID</string>
|
||||
<string name="encryption_information_device_key">Sessionsnyckel</string>
|
||||
<string name="encryption_export_e2e_room_keys">Exportera krypteringsnycklar</string>
|
||||
<string name="encryption_export_room_keys">Exportera rumsnycklar</string>
|
||||
|
|
|
@ -260,7 +260,7 @@
|
|||
<string name="room_settings_set_main_address">ప్రధాన చిరునామాగా సెట్ చేయండి</string>
|
||||
|
||||
<string name="encryption_information_device_name">పరికరం పేరు</string>
|
||||
<string name="device_manager_session_details_session_id">పరికరం ID</string>
|
||||
<string name="encryption_information_device_id">పరికరం ID</string>
|
||||
<string name="encryption_information_device_key">పరికరం కీ</string>
|
||||
|
||||
<string name="encryption_export_e2e_room_keys">E2E గది కీలను ఎగుమతి చేయండి</string>
|
||||
|
|
|
@ -376,7 +376,7 @@
|
|||
<string name="settings_theme">Tema</string>
|
||||
<string name="encryption_information_decryption_error">Çözme hatası</string>
|
||||
<string name="encryption_information_device_name">Görünür Ad</string>
|
||||
<string name="device_manager_session_details_session_id">Oturum kimliği</string>
|
||||
<string name="encryption_information_device_id">Oturum kimliği</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_room_keys">Oda anahtarlarını dışa aktar</string>
|
||||
|
|
|
@ -354,7 +354,7 @@
|
|||
<string name="room_settings_unset_main_address">Зробити не основною адресою</string>
|
||||
<string name="encryption_information_decryption_error">Помилка розшифрування</string>
|
||||
<string name="encryption_information_device_name">Загальнодоступна назва</string>
|
||||
<string name="device_manager_session_details_session_id">ID сеансу</string>
|
||||
<string name="encryption_information_device_id">ID сеансу</string>
|
||||
<string name="encryption_information_device_key">Ключ сеансу</string>
|
||||
<string name="encryption_export_e2e_room_keys">Експортувати E2E ключі кімнати</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="dialog_user_consent_submit">Xem lại ngay</string>
|
||||
<string name="encryption_information_device_key">Chìa khóa phiên</string>
|
||||
<string name="device_manager_session_details_session_id">Mã phiên</string>
|
||||
<string name="encryption_information_device_id">Mã phiên</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="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="encryption_information_decryption_error">解密错误</string>
|
||||
<string name="encryption_information_device_name">公开名称</string>
|
||||
<string name="device_manager_session_details_session_id">会话 ID</string>
|
||||
<string name="encryption_information_device_id">会话 ID</string>
|
||||
<string name="encryption_information_device_key">会话密钥</string>
|
||||
<string name="encryption_import_import">导入</string>
|
||||
<string name="encryption_information_verified">已验证</string>
|
||||
|
|
|
@ -469,7 +469,7 @@
|
|||
<string name="settings_theme">主題</string>
|
||||
<string name="encryption_information_decryption_error">解密錯誤</string>
|
||||
<string name="encryption_information_device_name">公開名稱</string>
|
||||
<string name="device_manager_session_details_session_id">工作階段 ID</string>
|
||||
<string name="encryption_information_device_id">工作階段 ID</string>
|
||||
<string name="encryption_information_device_key">工作階段金鑰</string>
|
||||
<string name="encryption_export_e2e_room_keys">匯出聊天室的端到端加密金鑰</string>
|
||||
<string name="encryption_export_room_keys">匯出聊天室的加密金鑰</string>
|
||||
|
|
|
@ -442,6 +442,9 @@
|
|||
<string name="labs_enable_new_app_layout_title">Enable new layout</string>
|
||||
<string name="labs_enable_new_app_layout_summary">A simplified Element with optional tabs</string>
|
||||
|
||||
<string name="labs_enable_deferred_dm_title">Enable deferred DMs</string>
|
||||
<string name="labs_enable_deferred_dm_summary">Create DM only on first message</string>
|
||||
|
||||
<!-- Home fragment -->
|
||||
<string name="invitations_header">Invites</string>
|
||||
<string name="low_priority_header">Low priority</string>
|
||||
|
@ -2361,7 +2364,9 @@
|
|||
<string name="settings_active_sessions_manage">Manage Sessions</string>
|
||||
<string name="settings_active_sessions_signout_device">Sign out of this session</string>
|
||||
<string name="settings_sessions_list">Sessions</string>
|
||||
<!-- TODO rename to device_manager_sessions_other_title -->
|
||||
<string name="settings_sessions_other_title">Other sessions</string>
|
||||
<!-- TODO rename to device_manager_sessions_other_description -->
|
||||
<string name="settings_sessions_other_description">For best security, verify your sessions and sign out from any session that you don’t recognize or use anymore.</string>
|
||||
|
||||
<string name="settings_server_name">Server name</string>
|
||||
|
@ -3265,10 +3270,36 @@
|
|||
<string name="device_manager_device_title">Device</string>
|
||||
<!-- 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_filter_bottom_sheet_title">Filter</string>
|
||||
<string name="device_manager_filter_option_all_sessions">All sessions</string>
|
||||
<string name="device_manager_filter_option_verified">Verified</string>
|
||||
<string name="device_manager_filter_option_verified_description">Ready for secure messaging</string>
|
||||
<string name="device_manager_filter_option_unverified">Unverified</string>
|
||||
<string name="device_manager_filter_option_unverified_description">Not ready for secure messaging</string>
|
||||
<string name="device_manager_filter_option_inactive">Inactive</string>
|
||||
<plurals name="device_manager_filter_option_inactive_description">
|
||||
<item quantity="one">Inactive for %1$d day or longer</item>
|
||||
<item quantity="other">Inactive for %1$d days or longer</item>
|
||||
</plurals>
|
||||
<string name="a11y_device_manager_filter">Filter</string>
|
||||
<string name="device_manager_other_sessions_recommendation_title_verified">Verified</string>
|
||||
<string name="device_manager_other_sessions_recommendation_description_verified">For best security, sign out from any session that you don’t recognize or use anymore.</string>
|
||||
<string name="device_manager_other_sessions_recommendation_title_unverified">Unverified</string>
|
||||
<string name="device_manager_other_sessions_recommendation_description_unverified">Verify your sessions for enhanced secure messaging or sign out from those you don’t recognize or use anymore.</string>
|
||||
<string name="device_manager_other_sessions_recommendation_title_inactive">Inactive</string>
|
||||
<plurals name="device_manager_other_sessions_recommendation_description_inactive">
|
||||
<item quantity="one">Consider signing out from old sessions (%1$d day or more) you don’t use anymore.</item>
|
||||
<item quantity="other">Consider signing out from old sessions (%1$d days or more) you don’t use anymore.</item>
|
||||
</plurals>
|
||||
<string name="device_manager_other_sessions_no_verified_sessions_found">No verified sessions found.</string>
|
||||
<string name="device_manager_other_sessions_no_unverified_sessions_found">No unverified sessions found.</string>
|
||||
<string name="device_manager_other_sessions_no_inactive_sessions_found">No inactive sessions found.</string>
|
||||
<string name="device_manager_other_sessions_clear_filter">Clear Filter</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>
|
||||
<!-- TODO rename to device_manager_session_details_session_id -->
|
||||
<string name="encryption_information_device_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>
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@
|
|||
|
||||
<!-- Shield colors -->
|
||||
<color name="shield_color_trust">#0DBD8B</color>
|
||||
<color name="shield_color_trust_background">#0F0DBD8B</color>
|
||||
<color name="shield_color_black">#17191C</color>
|
||||
<color name="shield_color_warning">#FF4B55</color>
|
||||
<color name="shield_color_warning_background">#0FFF4B55</color>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="OtherSessionsSecurityRecommendationView">
|
||||
<attr name="otherSessionsRecommendationTitle" format="string" />
|
||||
<attr name="otherSessionsRecommendationDescription" format="string" />
|
||||
<attr name="otherSessionsRecommendationImageResource" format="reference" />
|
||||
<attr name="otherSessionsRecommendationImageBackgroundTint" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
|
@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.getStateEvent
|
|||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
@ -46,6 +47,13 @@ class FlowRoom(private val room: Room) {
|
|||
}
|
||||
}
|
||||
|
||||
fun liveLocalRoomSummary(): Flow<Optional<LocalRoomSummary>> {
|
||||
return room.getLocalRoomSummaryLive().asFlow()
|
||||
.startWith(room.coroutineDispatchers.io) {
|
||||
room.localRoomSummary().toOptional()
|
||||
}
|
||||
}
|
||||
|
||||
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Flow<List<RoomMemberSummary>> {
|
||||
return room.membershipService().getRoomMembersLive(queryParams).asFlow()
|
||||
.startWith(room.coroutineDispatchers.io) {
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
|||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
|
||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
||||
import org.matrix.android.sdk.api.session.room.notification.RoomPushRuleService
|
||||
|
@ -60,11 +61,22 @@ interface Room {
|
|||
*/
|
||||
fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>>
|
||||
|
||||
/**
|
||||
* A live [LocalRoomSummary] associated with the room.
|
||||
* You can observe this summary to get dynamic data from this room.
|
||||
*/
|
||||
fun getLocalRoomSummaryLive(): LiveData<Optional<LocalRoomSummary>>
|
||||
|
||||
/**
|
||||
* A current snapshot of [RoomSummary] associated with the room.
|
||||
*/
|
||||
fun roomSummary(): RoomSummary?
|
||||
|
||||
/**
|
||||
* A current snapshot of [LocalRoomSummary] associated with the room.
|
||||
*/
|
||||
fun localRoomSummary(): LocalRoomSummary?
|
||||
|
||||
/**
|
||||
* Use this room as a Space, if the type is correct.
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
|
|||
import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
|
||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
@ -117,6 +118,12 @@ interface RoomService {
|
|||
*/
|
||||
fun getRoomSummaryLive(roomId: String): LiveData<Optional<RoomSummary>>
|
||||
|
||||
/**
|
||||
* A live [LocalRoomSummary] associated with the room with id [roomId].
|
||||
* You can observe this summary to get dynamic data from this room, even if the room is not joined yet
|
||||
*/
|
||||
fun getLocalRoomSummaryLive(roomId: String): LiveData<Optional<LocalRoomSummary>>
|
||||
|
||||
/**
|
||||
* Get a snapshot list of room summaries.
|
||||
* @return the immutable list of [RoomSummary]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.model
|
||||
|
||||
enum class LocalRoomCreationState {
|
||||
NOT_CREATED,
|
||||
CREATING,
|
||||
FAILURE,
|
||||
CREATED
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.model
|
||||
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
|
||||
/**
|
||||
* This class holds some data of a local room.
|
||||
* It can be retrieved by [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]
|
||||
*/
|
||||
data class LocalRoomSummary(
|
||||
/**
|
||||
* The roomId of the room.
|
||||
*/
|
||||
val roomId: String,
|
||||
/**
|
||||
* The room summary of the room.
|
||||
*/
|
||||
val roomSummary: RoomSummary?,
|
||||
/**
|
||||
* The creation params attached to the room.
|
||||
*/
|
||||
val createRoomParams: CreateRoomParams?,
|
||||
/**
|
||||
* The roomId of the created room (ie. created on the server), if any.
|
||||
*/
|
||||
val replacementRoomId: String?,
|
||||
/**
|
||||
* The creation state of the room.
|
||||
*/
|
||||
val creationState: LocalRoomCreationState,
|
||||
)
|
|
@ -53,6 +53,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo033
|
|||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo034
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo035
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo036
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo037
|
||||
import org.matrix.android.sdk.internal.util.Normalizer
|
||||
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
|
||||
import javax.inject.Inject
|
||||
|
@ -61,7 +62,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
|||
private val normalizer: Normalizer
|
||||
) : MatrixRealmMigration(
|
||||
dbName = "Session",
|
||||
schemaVersion = 36L,
|
||||
schemaVersion = 37L,
|
||||
) {
|
||||
/**
|
||||
* Forces all RealmSessionStoreMigration instances to be equal.
|
||||
|
@ -107,5 +108,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
|||
if (oldVersion < 34) MigrateSessionTo034(realm).perform()
|
||||
if (oldVersion < 35) MigrateSessionTo035(realm).perform()
|
||||
if (oldVersion < 36) MigrateSessionTo036(realm).perform()
|
||||
if (oldVersion < 37) MigrateSessionTo037(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.database.mapper
|
||||
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class LocalRoomSummaryMapper @Inject constructor(
|
||||
private val roomSummaryMapper: RoomSummaryMapper,
|
||||
) {
|
||||
|
||||
fun map(localRoomSummaryEntity: LocalRoomSummaryEntity): LocalRoomSummary {
|
||||
return LocalRoomSummary(
|
||||
roomId = localRoomSummaryEntity.roomId,
|
||||
roomSummary = localRoomSummaryEntity.roomSummaryEntity?.let { roomSummaryMapper.map(it) },
|
||||
createRoomParams = localRoomSummaryEntity.createRoomParams,
|
||||
replacementRoomId = localRoomSummaryEntity.replacementRoomId,
|
||||
creationState = localRoomSummaryEntity.creationState
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.database.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
internal class MigrateSessionTo037(realm: DynamicRealm) : RealmMigrator(realm, 37) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("LocalRoomSummaryEntity")
|
||||
?.addField(LocalRoomSummaryEntityFields.REPLACEMENT_ROOM_ID, String::class.java)
|
||||
?.addField(LocalRoomSummaryEntityFields.STATE_STR, String::class.java)
|
||||
?.transform { obj ->
|
||||
obj.set(LocalRoomSummaryEntityFields.STATE_STR, LocalRoomCreationState.NOT_CREATED.name)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,15 +18,24 @@ package org.matrix.android.sdk.internal.database.model
|
|||
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.PrimaryKey
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.toJSONString
|
||||
|
||||
internal open class LocalRoomSummaryEntity(
|
||||
@PrimaryKey var roomId: String = "",
|
||||
var roomSummaryEntity: RoomSummaryEntity? = null,
|
||||
private var createRoomParamsStr: String? = null
|
||||
var replacementRoomId: String? = null,
|
||||
) : RealmObject() {
|
||||
|
||||
private var stateStr: String = LocalRoomCreationState.NOT_CREATED.name
|
||||
var creationState: LocalRoomCreationState
|
||||
get() = LocalRoomCreationState.valueOf(stateStr)
|
||||
set(value) {
|
||||
stateStr = value.name
|
||||
}
|
||||
|
||||
private var createRoomParamsStr: String? = null
|
||||
var createRoomParams: CreateRoomParams?
|
||||
get() {
|
||||
return CreateRoomParams.fromJson(createRoomParamsStr)
|
||||
|
|
|
@ -22,10 +22,6 @@ import io.realm.kotlin.where
|
|||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
||||
|
||||
internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String? = null): RealmQuery<LocalRoomSummaryEntity> {
|
||||
val query = realm.where<LocalRoomSummaryEntity>()
|
||||
if (roomId != null) {
|
||||
query.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId)
|
||||
}
|
||||
return query
|
||||
internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<LocalRoomSummaryEntity> {
|
||||
return realm.where<LocalRoomSummaryEntity>().equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId)
|
||||
}
|
||||
|
|
|
@ -33,6 +33,11 @@ internal fun ReadReceiptEntity.Companion.whereUserId(realm: Realm, userId: Strin
|
|||
.equalTo(ReadReceiptEntityFields.USER_ID, userId)
|
||||
}
|
||||
|
||||
internal fun ReadReceiptEntity.Companion.whereRoomId(realm: Realm, roomId: String): RealmQuery<ReadReceiptEntity> {
|
||||
return realm.where<ReadReceiptEntity>()
|
||||
.equalTo(ReadReceiptEntityFields.ROOM_ID, roomId)
|
||||
}
|
||||
|
||||
internal fun ReadReceiptEntity.Companion.createUnmanaged(roomId: String, eventId: String, userId: String, originServerTs: Double): ReadReceiptEntity {
|
||||
return ReadReceiptEntity().apply {
|
||||
this.primaryKey = "${roomId}_$userId"
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
|||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
|
||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
||||
|
@ -82,6 +83,14 @@ internal class DefaultRoom(
|
|||
return roomSummaryDataSource.getRoomSummary(roomId)
|
||||
}
|
||||
|
||||
override fun getLocalRoomSummaryLive(): LiveData<Optional<LocalRoomSummary>> {
|
||||
return roomSummaryDataSource.getLocalRoomSummaryLive(roomId)
|
||||
}
|
||||
|
||||
override fun localRoomSummary(): LocalRoomSummary? {
|
||||
return roomSummaryDataSource.getLocalRoomSummary(roomId)
|
||||
}
|
||||
|
||||
override fun asSpace(): Space? {
|
||||
if (roomSummary()?.roomType != RoomType.SPACE) return null
|
||||
return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder)
|
||||
|
|
|
@ -29,10 +29,12 @@ import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
|||
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
|
||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.session.room.peeking.PeekResult
|
||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
|
||||
|
@ -106,6 +108,10 @@ internal class DefaultRoomService @Inject constructor(
|
|||
return roomSummaryDataSource.getRoomSummaryLive(roomId)
|
||||
}
|
||||
|
||||
override fun getLocalRoomSummaryLive(roomId: String): LiveData<Optional<LocalRoomSummary>> {
|
||||
return roomSummaryDataSource.getLocalRoomSummaryLive(roomId)
|
||||
}
|
||||
|
||||
override fun getRoomSummaries(
|
||||
queryParams: RoomSummaryQueryParams,
|
||||
sortOrder: RoomSortOrder
|
||||
|
@ -173,7 +179,10 @@ internal class DefaultRoomService @Inject constructor(
|
|||
}
|
||||
|
||||
override suspend fun onRoomDisplayed(roomId: String) {
|
||||
updateBreadcrumbsTask.execute(UpdateBreadcrumbsTask.Params(roomId))
|
||||
// Do not add local rooms to the recent rooms list as they should not be known by the server
|
||||
if (!RoomLocalEcho.isLocalEchoId(roomId)) {
|
||||
updateBreadcrumbsTask.execute(UpdateBreadcrumbsTask.Params(roomId))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun joinRoom(roomIdOrAlias: String, reason: String?, viaServers: List<String>) {
|
||||
|
|
|
@ -17,38 +17,23 @@
|
|||
package org.matrix.android.sdk.internal.session.room.create
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import io.realm.kotlin.where
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.database.query.whereRoomId
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -56,94 +41,100 @@ import javax.inject.Inject
|
|||
* Create a room on the server from a local room.
|
||||
* The configuration of the local room will be use to configure the new room.
|
||||
* The potential local room members will also be invited to this new room.
|
||||
*
|
||||
* A local tombstone event will be created to indicate that the local room has been replacing by the new one.
|
||||
*/
|
||||
internal interface CreateRoomFromLocalRoomTask : Task<CreateRoomFromLocalRoomTask.Params, String> {
|
||||
data class Params(val localRoomId: String)
|
||||
}
|
||||
|
||||
internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val createRoomTask: CreateRoomTask,
|
||||
private val stateEventDataSource: StateEventDataSource,
|
||||
private val clock: Clock,
|
||||
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||
) : CreateRoomFromLocalRoomTask {
|
||||
|
||||
private val realmConfiguration
|
||||
get() = monarchy.realmConfiguration
|
||||
|
||||
override suspend fun execute(params: CreateRoomFromLocalRoomTask.Params): String {
|
||||
val replacementRoomId = stateEventDataSource.getStateEvent(params.localRoomId, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)
|
||||
?.content.toModel<RoomTombstoneContent>()
|
||||
?.replacementRoomId
|
||||
val localRoomSummary = roomSummaryDataSource.getLocalRoomSummary(params.localRoomId)
|
||||
?: error("## CreateRoomFromLocalRoomTask - Cannot retrieve LocalRoomSummary with roomId ${params.localRoomId}")
|
||||
|
||||
if (replacementRoomId != null) {
|
||||
return replacementRoomId
|
||||
// If a room has already been created for the given local room, return the existing roomId
|
||||
if (localRoomSummary.replacementRoomId != null) {
|
||||
return localRoomSummary.replacementRoomId
|
||||
}
|
||||
|
||||
var createRoomParams: CreateRoomParams? = null
|
||||
var isEncrypted = false
|
||||
monarchy.doWithRealm { realm ->
|
||||
realm.where<LocalRoomSummaryEntity>()
|
||||
.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, params.localRoomId)
|
||||
.findFirst()
|
||||
?.let {
|
||||
createRoomParams = it.createRoomParams
|
||||
isEncrypted = it.roomSummaryEntity?.isEncrypted.orFalse()
|
||||
}
|
||||
if (localRoomSummary.createRoomParams != null && localRoomSummary.roomSummary != null) {
|
||||
return createRoom(params.localRoomId, localRoomSummary.roomSummary, localRoomSummary.createRoomParams)
|
||||
} else {
|
||||
error("## CreateRoomFromLocalRoomTask - Invalid LocalRoomSummary: $localRoomSummary")
|
||||
}
|
||||
val roomId = createRoomTask.execute(createRoomParams!!)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a room on the server for the given local room.
|
||||
*
|
||||
* @param localRoomId the local room identifier.
|
||||
* @param localRoomSummary the RoomSummary of the local room.
|
||||
* @param createRoomParams the CreateRoomParams object which was used to configure the local room.
|
||||
*
|
||||
* @return the identifier of the created room.
|
||||
*/
|
||||
private suspend fun createRoom(localRoomId: String, localRoomSummary: RoomSummary, createRoomParams: CreateRoomParams): String {
|
||||
updateCreationState(localRoomId, LocalRoomCreationState.CREATING)
|
||||
val replacementRoomId = runCatching {
|
||||
createRoomTask.execute(createRoomParams)
|
||||
}.fold(
|
||||
{ it },
|
||||
{
|
||||
updateCreationState(localRoomId, LocalRoomCreationState.FAILURE)
|
||||
throw it
|
||||
}
|
||||
)
|
||||
updateReplacementRoomId(localRoomId, replacementRoomId)
|
||||
waitForRoomEvents(replacementRoomId, localRoomSummary)
|
||||
updateCreationState(localRoomId, LocalRoomCreationState.CREATED)
|
||||
return replacementRoomId
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for all the room events before triggering the created state.
|
||||
*
|
||||
* @param replacementRoomId the identifier of the created room
|
||||
* @param localRoomSummary the RoomSummary of the local room.
|
||||
*/
|
||||
private suspend fun waitForRoomEvents(replacementRoomId: String, localRoomSummary: RoomSummary) {
|
||||
try {
|
||||
// Wait for all the room events before triggering the replacement room
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
realm.where(RoomSummaryEntity::class.java)
|
||||
.equalTo(RoomSummaryEntityFields.ROOM_ID, roomId)
|
||||
.equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, createRoomParams?.invitedUserIds?.size ?: 0)
|
||||
.equalTo(RoomSummaryEntityFields.ROOM_ID, replacementRoomId)
|
||||
.equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, localRoomSummary.invitedMembersCount)
|
||||
}
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
EventEntity.whereRoomId(realm, roomId)
|
||||
EventEntity.whereRoomId(realm, replacementRoomId)
|
||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_HISTORY_VISIBILITY)
|
||||
}
|
||||
if (isEncrypted) {
|
||||
if (localRoomSummary.isEncrypted) {
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
EventEntity.whereRoomId(realm, roomId)
|
||||
EventEntity.whereRoomId(realm, replacementRoomId)
|
||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION)
|
||||
}
|
||||
}
|
||||
} catch (exception: TimeoutCancellationException) {
|
||||
throw CreateRoomFailure.CreatedWithTimeout(roomId)
|
||||
updateCreationState(localRoomSummary.roomId, LocalRoomCreationState.FAILURE)
|
||||
throw CreateRoomFailure.CreatedWithTimeout(replacementRoomId)
|
||||
}
|
||||
|
||||
createTombstoneEvent(params, roomId)
|
||||
return roomId
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Tombstone event to indicate that the local room has been replaced by a new one.
|
||||
*/
|
||||
private suspend fun createTombstoneEvent(params: CreateRoomFromLocalRoomTask.Params, roomId: String) {
|
||||
val now = clock.epochMillis()
|
||||
val event = Event(
|
||||
type = EventType.STATE_ROOM_TOMBSTONE,
|
||||
senderId = userId,
|
||||
originServerTs = now,
|
||||
stateKey = "",
|
||||
eventId = UUID.randomUUID().toString(),
|
||||
content = RoomTombstoneContent(
|
||||
replacementRoomId = roomId
|
||||
).toContent()
|
||||
)
|
||||
monarchy.awaitTransaction { realm ->
|
||||
val eventEntity = event.toEntity(params.localRoomId, SendState.SYNCED, now).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC)
|
||||
if (event.stateKey != null && event.type != null && event.eventId != null) {
|
||||
CurrentStateEventEntity.getOrCreate(realm, params.localRoomId, event.stateKey, event.type).apply {
|
||||
eventId = event.eventId
|
||||
root = eventEntity
|
||||
}
|
||||
}
|
||||
private fun updateCreationState(roomId: String, creationState: LocalRoomCreationState) {
|
||||
monarchy.runTransactionSync { realm ->
|
||||
LocalRoomSummaryEntity.where(realm, roomId).findFirst()?.creationState = creationState
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateReplacementRoomId(localRoomId: String, replacementRoomId: String) {
|
||||
monarchy.runTransactionSync { realm ->
|
||||
LocalRoomSummaryEntity.where(realm, localRoomId).findFirst()?.replacementRoomId = replacementRoomId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,12 +22,15 @@ import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
|||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.ReadReceiptEntity
|
||||
import org.matrix.android.sdk.internal.database.model.ReadReceiptsSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.deleteOnCascade
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.database.query.whereInRoom
|
||||
import org.matrix.android.sdk.internal.database.query.whereRoomId
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.session.room.delete.DeleteLocalRoomTask.Params
|
||||
|
@ -50,6 +53,12 @@ internal class DefaultDeleteLocalRoomTask @Inject constructor(
|
|||
if (RoomLocalEcho.isLocalEchoId(roomId)) {
|
||||
monarchy.awaitTransaction { realm ->
|
||||
Timber.i("## DeleteLocalRoomTask - delete local room id $roomId")
|
||||
ReadReceiptsSummaryEntity.whereInRoom(realm, roomId = roomId).findAll()
|
||||
?.also { Timber.i("## DeleteLocalRoomTask - ReadReceiptsSummaryEntity - delete ${it.size} entries") }
|
||||
?.deleteAllFromRealm()
|
||||
ReadReceiptEntity.whereRoomId(realm, roomId = roomId).findAll()
|
||||
?.also { Timber.i("## DeleteLocalRoomTask - ReadReceiptEntity - delete ${it.size} entries") }
|
||||
?.deleteAllFromRealm()
|
||||
RoomMemberSummaryEntity.where(realm, roomId = roomId).findAll()
|
||||
?.also { Timber.i("## DeleteLocalRoomTask - RoomMemberSummaryEntity - delete ${it.size} entries") }
|
||||
?.deleteAllFromRealm()
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.room.ResultBoundaries
|
|||
import org.matrix.android.sdk.api.session.room.RoomSortOrder
|
||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||
|
@ -43,7 +44,9 @@ import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotification
|
|||
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.api.util.toOptional
|
||||
import org.matrix.android.sdk.internal.database.mapper.LocalRoomSummaryMapper
|
||||
import org.matrix.android.sdk.internal.database.mapper.RoomSummaryMapper
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.query.findByAlias
|
||||
|
@ -57,6 +60,7 @@ import javax.inject.Inject
|
|||
internal class RoomSummaryDataSource @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val roomSummaryMapper: RoomSummaryMapper,
|
||||
private val localRoomSummaryMapper: LocalRoomSummaryMapper,
|
||||
private val queryStringValueProcessor: QueryStringValueProcessor,
|
||||
) {
|
||||
|
||||
|
@ -95,6 +99,25 @@ internal class RoomSummaryDataSource @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
fun getLocalRoomSummary(roomId: String): LocalRoomSummary? {
|
||||
return monarchy
|
||||
.fetchCopyMap({
|
||||
LocalRoomSummaryEntity.where(it, roomId).findFirst()
|
||||
}, { entity, _ ->
|
||||
localRoomSummaryMapper.map(entity)
|
||||
})
|
||||
}
|
||||
|
||||
fun getLocalRoomSummaryLive(roomId: String): LiveData<Optional<LocalRoomSummary>> {
|
||||
val liveData = monarchy.findAllMappedWithChanges(
|
||||
{ realm -> LocalRoomSummaryEntity.where(realm, roomId) },
|
||||
{ localRoomSummaryMapper.map(it) }
|
||||
)
|
||||
return Transformations.map(liveData) { results ->
|
||||
results.firstOrNull().toOptional()
|
||||
}
|
||||
}
|
||||
|
||||
fun getRoomSummariesLive(
|
||||
queryParams: RoomSummaryQueryParams,
|
||||
sortOrder: RoomSortOrder = RoomSortOrder.NONE
|
||||
|
|
|
@ -22,21 +22,22 @@ import io.mockk.coVerify
|
|||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.spyk
|
||||
import io.mockk.unmockkAll
|
||||
import io.mockk.verify
|
||||
import io.mockk.verifyOrder
|
||||
import io.realm.kotlin.where
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.amshove.kluent.shouldBeEqualTo
|
||||
import org.amshove.kluent.shouldBeNull
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
||||
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||
|
@ -44,29 +45,24 @@ import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
|||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||
import org.matrix.android.sdk.internal.util.time.DefaultClock
|
||||
import org.matrix.android.sdk.test.fakes.FakeMonarchy
|
||||
import org.matrix.android.sdk.test.fakes.FakeStateEventDataSource
|
||||
import org.matrix.android.sdk.test.fakes.FakeRoomSummaryDataSource
|
||||
|
||||
private const val A_LOCAL_ROOM_ID = "local.a-local-room-id"
|
||||
private const val AN_EXISTING_ROOM_ID = "an-existing-room-id"
|
||||
private const val A_ROOM_ID = "a-room-id"
|
||||
private const val MY_USER_ID = "my-user-id"
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
||||
|
||||
private val fakeMonarchy = FakeMonarchy()
|
||||
private val clock = DefaultClock()
|
||||
private val createRoomTask = mockk<CreateRoomTask>()
|
||||
private val fakeStateEventDataSource = FakeStateEventDataSource()
|
||||
private val fakeRoomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||
|
||||
private val defaultCreateRoomFromLocalRoomTask = DefaultCreateRoomFromLocalRoomTask(
|
||||
userId = MY_USER_ID,
|
||||
monarchy = fakeMonarchy.instance,
|
||||
createRoomTask = createRoomTask,
|
||||
stateEventDataSource = fakeStateEventDataSource.instance,
|
||||
clock = clock
|
||||
roomSummaryDataSource = fakeRoomSummaryDataSource.instance,
|
||||
)
|
||||
|
||||
@Before
|
||||
|
@ -91,13 +87,12 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
|||
@Test
|
||||
fun `given a local room id when execute then the existing room id is kept`() = runTest {
|
||||
// Given
|
||||
givenATombstoneEvent(
|
||||
Event(
|
||||
roomId = A_LOCAL_ROOM_ID,
|
||||
type = EventType.STATE_ROOM_TOMBSTONE,
|
||||
stateKey = "",
|
||||
content = RoomTombstoneContent(replacementRoomId = AN_EXISTING_ROOM_ID).toContent()
|
||||
)
|
||||
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aCreationState = LocalRoomCreationState.CREATED, aReplacementRoomId = AN_EXISTING_ROOM_ID)
|
||||
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(
|
||||
aCreateRoomParams = aCreateRoomParams,
|
||||
aCreationState = LocalRoomCreationState.CREATED,
|
||||
aReplacementRoomId = AN_EXISTING_ROOM_ID
|
||||
)
|
||||
|
||||
// When
|
||||
|
@ -105,20 +100,18 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
|||
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
||||
|
||||
// Then
|
||||
verifyTombstoneEvent(AN_EXISTING_ROOM_ID)
|
||||
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||
result shouldBeEqualTo AN_EXISTING_ROOM_ID
|
||||
aLocalRoomSummaryEntity.replacementRoomId shouldBeEqualTo AN_EXISTING_ROOM_ID
|
||||
aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.CREATED
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a local room id when execute then it is correctly executed`() = runTest {
|
||||
// Given
|
||||
val aCreateRoomParams = mockk<CreateRoomParams>()
|
||||
val aLocalRoomSummaryEntity = mockk<LocalRoomSummaryEntity> {
|
||||
every { roomSummaryEntity } returns mockk(relaxed = true)
|
||||
every { createRoomParams } returns aCreateRoomParams
|
||||
}
|
||||
givenATombstoneEvent(null)
|
||||
givenALocalRoomSummaryEntity(aLocalRoomSummaryEntity)
|
||||
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||
|
||||
coEvery { createRoomTask.execute(any()) } returns A_ROOM_ID
|
||||
|
||||
|
@ -127,32 +120,84 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
|||
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
||||
|
||||
// Then
|
||||
verifyTombstoneEvent(null)
|
||||
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||
// CreateRoomTask has been called with the initial CreateRoomParams
|
||||
coVerify { createRoomTask.execute(aCreateRoomParams) }
|
||||
// The resulting roomId matches the roomId returned by the createRoomTask
|
||||
result shouldBeEqualTo A_ROOM_ID
|
||||
// A tombstone state event has been created
|
||||
coVerify { CurrentStateEventEntity.getOrCreate(realm = any(), roomId = A_LOCAL_ROOM_ID, stateKey = any(), type = EventType.STATE_ROOM_TOMBSTONE) }
|
||||
// The room creation state has correctly been updated
|
||||
verifyOrder {
|
||||
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATING
|
||||
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATED
|
||||
}
|
||||
// The local room summary has been updated with the created room id
|
||||
verify { aLocalRoomSummaryEntity.replacementRoomId = A_ROOM_ID }
|
||||
aLocalRoomSummaryEntity.replacementRoomId shouldBeEqualTo A_ROOM_ID
|
||||
aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.CREATED
|
||||
}
|
||||
|
||||
private fun givenATombstoneEvent(event: Event?) {
|
||||
fakeStateEventDataSource.givenGetStateEventReturns(event)
|
||||
@Test
|
||||
fun `given a local room id when execute with an exception then the creation state is correctly updated`() = runTest {
|
||||
// Given
|
||||
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||
|
||||
coEvery { createRoomTask.execute(any()) }.throws(mockk())
|
||||
|
||||
// When
|
||||
val params = CreateRoomFromLocalRoomTask.Params(A_LOCAL_ROOM_ID)
|
||||
tryOrNull { defaultCreateRoomFromLocalRoomTask.execute(params) }
|
||||
|
||||
// Then
|
||||
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||
// CreateRoomTask has been called with the initial CreateRoomParams
|
||||
coVerify { createRoomTask.execute(aCreateRoomParams) }
|
||||
// The room creation state has correctly been updated
|
||||
verifyOrder {
|
||||
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATING
|
||||
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.FAILURE
|
||||
}
|
||||
// The local room summary has been updated with the created room id
|
||||
aLocalRoomSummaryEntity.replacementRoomId.shouldBeNull()
|
||||
aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.FAILURE
|
||||
}
|
||||
|
||||
private fun givenALocalRoomSummaryEntity(localRoomSummaryEntity: LocalRoomSummaryEntity) {
|
||||
private fun givenALocalRoomSummary(
|
||||
aCreateRoomParams: CreateRoomParams,
|
||||
aCreationState: LocalRoomCreationState = LocalRoomCreationState.NOT_CREATED,
|
||||
aReplacementRoomId: String? = null
|
||||
): LocalRoomSummary {
|
||||
val aLocalRoomSummary = LocalRoomSummary(
|
||||
roomId = A_LOCAL_ROOM_ID,
|
||||
roomSummary = mockk(relaxed = true),
|
||||
createRoomParams = aCreateRoomParams,
|
||||
creationState = aCreationState,
|
||||
replacementRoomId = aReplacementRoomId,
|
||||
)
|
||||
fakeRoomSummaryDataSource.givenGetLocalRoomSummaryReturns(A_LOCAL_ROOM_ID, aLocalRoomSummary)
|
||||
return aLocalRoomSummary
|
||||
}
|
||||
|
||||
private fun givenALocalRoomSummaryEntity(
|
||||
aCreateRoomParams: CreateRoomParams,
|
||||
aCreationState: LocalRoomCreationState = LocalRoomCreationState.NOT_CREATED,
|
||||
aReplacementRoomId: String? = null
|
||||
): LocalRoomSummaryEntity {
|
||||
val aLocalRoomSummaryEntity = spyk(LocalRoomSummaryEntity(
|
||||
roomId = A_LOCAL_ROOM_ID,
|
||||
roomSummaryEntity = mockk(relaxed = true),
|
||||
replacementRoomId = aReplacementRoomId,
|
||||
).apply {
|
||||
createRoomParams = aCreateRoomParams
|
||||
creationState = aCreationState
|
||||
})
|
||||
every {
|
||||
fakeMonarchy.fakeRealm.instance
|
||||
.where<LocalRoomSummaryEntity>()
|
||||
.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, A_LOCAL_ROOM_ID)
|
||||
.findFirst()
|
||||
} returns localRoomSummaryEntity
|
||||
}
|
||||
|
||||
private fun verifyTombstoneEvent(expectedRoomId: String?) {
|
||||
fakeStateEventDataSource.verifyGetStateEvent(A_LOCAL_ROOM_ID, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)
|
||||
fakeStateEventDataSource.instance.getStateEvent(A_LOCAL_ROOM_ID, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)
|
||||
?.content.toModel<RoomTombstoneContent>()
|
||||
?.replacementRoomId shouldBeEqualTo expectedRoomId
|
||||
} returns aLocalRoomSummaryEntity
|
||||
return aLocalRoomSummaryEntity
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,11 @@ internal class FakeMonarchy {
|
|||
} coAnswers {
|
||||
firstArg<Monarchy.RealmBlock>().doWithRealm(fakeRealm.instance)
|
||||
}
|
||||
coEvery {
|
||||
instance.runTransactionSync(any())
|
||||
} coAnswers {
|
||||
firstArg<Realm.Transaction>().execute(fakeRealm.instance)
|
||||
}
|
||||
every { instance.realmConfiguration } returns mockk()
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.test.fakes
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||
|
||||
internal class FakeRoomSummaryDataSource {
|
||||
|
||||
val instance: RoomSummaryDataSource = mockk()
|
||||
|
||||
fun givenGetLocalRoomSummaryReturns(roomId: String?, localRoomSummary: LocalRoomSummary?) {
|
||||
every { instance.getLocalRoomSummary(roomId = roomId ?: any()) } returns localRoomSummary
|
||||
}
|
||||
|
||||
fun verifyGetLocalRoomSummary(roomId: String) {
|
||||
verify { instance.getLocalRoomSummary(roomId) }
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -370,9 +370,9 @@ dependencies {
|
|||
debugImplementation 'com.facebook.soloader:soloader:0.10.4'
|
||||
debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0"
|
||||
|
||||
gplayImplementation "com.google.android.gms:play-services-location:16.0.0"
|
||||
gplayImplementation "com.google.android.gms:play-services-location:20.0.0"
|
||||
// UnifiedPush gplay flavor only
|
||||
gplayImplementation('com.github.UnifiedPush:android-embedded_fcm_distributor:2.1.2') {
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:23.0.8') {
|
||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||
|
|
|
@ -225,8 +225,8 @@ class VerifySessionInteractiveTest : VerificationTestBase() {
|
|||
|
||||
// Wait until local secrets are known (gossip)
|
||||
withIdlingResource(allSecretsKnownIdling(uiSession)) {
|
||||
onView(withId(R.id.groupToolbarAvatarImageView))
|
||||
.perform(click())
|
||||
onView(withId(R.id.roomListContainer))
|
||||
.check(matches(isDisplayed()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ import im.vector.app.withIdlingResource
|
|||
import timber.log.Timber
|
||||
|
||||
class ElementRobot(
|
||||
private val labsPreferences: LabFeaturesPreferences = LabFeaturesPreferences(false)
|
||||
private val labsPreferences: LabFeaturesPreferences = LabFeaturesPreferences(true)
|
||||
) {
|
||||
fun onboarding(block: OnboardingRobot.() -> Unit) {
|
||||
block(OnboardingRobot())
|
||||
|
@ -110,9 +110,6 @@ class ElementRobot(
|
|||
closeSoftKeyboard()
|
||||
block(NewDirectMessageRobot())
|
||||
pressBack()
|
||||
if (labsPreferences.isNewAppLayoutEnabled) {
|
||||
pressBack() // close create dialog
|
||||
}
|
||||
waitUntilViewVisible(withId(R.id.roomListContainer))
|
||||
}
|
||||
|
||||
|
@ -121,9 +118,6 @@ class ElementRobot(
|
|||
clickOn(R.id.bottom_action_rooms)
|
||||
}
|
||||
RoomListRobot(labsPreferences).newRoom { block() }
|
||||
if (labsPreferences.isNewAppLayoutEnabled) {
|
||||
pressBack() // close create dialog
|
||||
}
|
||||
waitUntilViewVisible(withId(R.id.roomListContainer))
|
||||
}
|
||||
|
||||
|
|
|
@ -80,11 +80,6 @@ class DebugFeaturesStateFactory @Inject constructor(
|
|||
key = DebugFeatureKeys.forceUsageOfOpusEncoder,
|
||||
factory = VectorFeatures::forceUsageOfOpusEncoder
|
||||
),
|
||||
createBooleanFeature(
|
||||
label = "Start DM on first message",
|
||||
key = DebugFeatureKeys.startDmOnFirstMsg,
|
||||
factory = VectorFeatures::shouldStartDmOnFirstMessage
|
||||
),
|
||||
createBooleanFeature(
|
||||
label = "Enable New App Layout",
|
||||
key = DebugFeatureKeys.newAppLayoutEnabled,
|
||||
|
|
|
@ -73,9 +73,6 @@ class DebugVectorFeatures(
|
|||
override fun forceUsageOfOpusEncoder(): Boolean = read(DebugFeatureKeys.forceUsageOfOpusEncoder)
|
||||
?: vectorFeatures.forceUsageOfOpusEncoder()
|
||||
|
||||
override fun shouldStartDmOnFirstMessage(): Boolean = read(DebugFeatureKeys.startDmOnFirstMsg)
|
||||
?: vectorFeatures.shouldStartDmOnFirstMessage()
|
||||
|
||||
override fun isNewAppLayoutFeatureEnabled(): Boolean = read(DebugFeatureKeys.newAppLayoutEnabled)
|
||||
?: vectorFeatures.isNewAppLayoutFeatureEnabled()
|
||||
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
<bool name="settings_ignored_users_visible">true</bool>
|
||||
|
||||
<!-- Level 1: Labs -->
|
||||
<bool name="settings_labs_deferred_dm_visible">true</bool>
|
||||
<bool name="settings_labs_deferred_dm_default">true</bool>
|
||||
<bool name="settings_labs_thread_messages_default">false</bool>
|
||||
<bool name="settings_labs_new_app_layout_default">false</bool>
|
||||
<bool name="settings_labs_new_app_layout_default">true</bool>
|
||||
<bool name="settings_timeline_show_live_sender_info_visible">true</bool>
|
||||
<bool name="settings_timeline_show_live_sender_info_default">false</bool>
|
||||
<!-- Level 1: Advanced settings -->
|
||||
|
|
|
@ -323,6 +323,7 @@
|
|||
<activity android:name=".features.home.room.list.home.invites.InvitesActivity" />
|
||||
<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.othersessions.OtherSessionsActivity" />
|
||||
<activity android:name=".features.settings.devices.v2.details.SessionDetailsActivity" />
|
||||
|
||||
<!-- Services -->
|
||||
|
|
|
@ -89,6 +89,7 @@ import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewMode
|
|||
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheetViewModel
|
||||
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.othersessions.OtherSessionsViewModel
|
||||
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.GossipingEventsPaperTrailViewModel
|
||||
|
@ -643,6 +644,11 @@ interface MavericksViewModelModule {
|
|||
@MavericksViewModelKey(SessionOverviewViewModel::class)
|
||||
fun sessionOverviewViewModelFactory(factory: SessionOverviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(OtherSessionsViewModel::class)
|
||||
fun otherSessionsViewModelFactory(factory: OtherSessionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(SessionDetailsViewModel::class)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
/**
|
||||
* This observer detects when item was added or moved to the first position of the adapter, while recyclerView is scrolled to the top. This is necessary
|
||||
* to force recycler to scroll to the top to make such item visible, because by default it will keep items on screen, while adding new item to the top,
|
||||
* outside of the viewport
|
||||
* @param layoutManager - [LinearLayoutManager] of the recycler view, which displays items
|
||||
* @property onItemUpdated - callback to be called, when observer detects event
|
||||
*/
|
||||
class FirstItemUpdatedObserver(
|
||||
layoutManager: LinearLayoutManager,
|
||||
private val onItemUpdated: () -> Unit
|
||||
) : RecyclerView.AdapterDataObserver() {
|
||||
|
||||
val layoutManager: LinearLayoutManager? by weak(layoutManager)
|
||||
|
||||
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
|
||||
if ((toPosition == 0 || fromPosition == 0) && layoutManager?.findFirstCompletelyVisibleItemPosition() == 0) {
|
||||
onItemUpdated.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||
if (positionStart == 0 && layoutManager?.findFirstCompletelyVisibleItemPosition() == 0) {
|
||||
onItemUpdated.invoke()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,6 @@ interface VectorFeatures {
|
|||
fun isScreenSharingEnabled(): Boolean
|
||||
fun isLocationSharingEnabled(): Boolean
|
||||
fun forceUsageOfOpusEncoder(): Boolean
|
||||
fun shouldStartDmOnFirstMessage(): Boolean
|
||||
|
||||
/**
|
||||
* This is only to enable if the labs flag should be visible and effective.
|
||||
|
@ -56,7 +55,6 @@ class DefaultVectorFeatures : VectorFeatures {
|
|||
override fun isScreenSharingEnabled(): Boolean = true
|
||||
override fun isLocationSharingEnabled() = Config.ENABLE_LOCATION_SHARING
|
||||
override fun forceUsageOfOpusEncoder(): Boolean = false
|
||||
override fun shouldStartDmOnFirstMessage(): Boolean = false
|
||||
override fun isNewAppLayoutFeatureEnabled(): Boolean = true
|
||||
override fun isNewDeviceManagementEnabled(): Boolean = false
|
||||
}
|
||||
|
|
|
@ -26,11 +26,11 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
|||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.mvrx.runCatchingToAsync
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.VectorFeatures
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import im.vector.app.features.raw.wellknown.getElementWellknown
|
||||
import im.vector.app.features.raw.wellknown.isE2EByDefault
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.userdirectory.PendingSelection
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -45,9 +45,9 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
|||
class CreateDirectRoomViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: CreateDirectRoomViewState,
|
||||
private val rawService: RawService,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
val session: Session,
|
||||
val analyticsTracker: AnalyticsTracker,
|
||||
val vectorFeatures: VectorFeatures
|
||||
) :
|
||||
VectorViewModel<CreateDirectRoomViewState, CreateDirectRoomAction, CreateDirectRoomViewEvents>(initialState) {
|
||||
|
||||
|
@ -124,7 +124,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
val result = runCatchingToAsync {
|
||||
if (vectorFeatures.shouldStartDmOnFirstMessage()) {
|
||||
if (vectorPreferences.isDeferredDmEnabled()) {
|
||||
session.roomService().createLocalRoom(roomParams)
|
||||
} else {
|
||||
analyticsTracker.capture(CreatedRoom(isDM = roomParams.isDirect.orFalse()))
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package im.vector.app.features.createdirect
|
||||
|
||||
import im.vector.app.features.VectorFeatures
|
||||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import im.vector.app.features.raw.wellknown.getElementWellknown
|
||||
import im.vector.app.features.raw.wellknown.isE2EByDefault
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.raw.RawService
|
||||
|
@ -32,7 +32,7 @@ class DirectRoomHelper @Inject constructor(
|
|||
private val rawService: RawService,
|
||||
private val session: Session,
|
||||
private val analyticsTracker: AnalyticsTracker,
|
||||
private val vectorFeatures: VectorFeatures,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
) {
|
||||
|
||||
suspend fun ensureDMExists(userId: String): String {
|
||||
|
@ -50,7 +50,7 @@ class DirectRoomHelper @Inject constructor(
|
|||
setDirectMessage()
|
||||
enableEncryptionIfInvitedUsersSupportIt = adminE2EByDefault
|
||||
}
|
||||
roomId = if (vectorFeatures.shouldStartDmOnFirstMessage()) {
|
||||
roomId = if (vectorPreferences.isDeferredDmEnabled()) {
|
||||
session.roomService().createLocalRoom(roomParams)
|
||||
} else {
|
||||
analyticsTracker.capture(CreatedRoom(isDM = roomParams.isDirect.orFalse()))
|
||||
|
|
|
@ -84,6 +84,7 @@ import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
|
|||
import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet
|
||||
import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.app.features.usercode.UserCodeActivity
|
||||
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -634,10 +635,18 @@ class HomeActivity :
|
|||
launchInviteFriends()
|
||||
true
|
||||
}
|
||||
R.id.menu_home_qr -> {
|
||||
launchQrCode()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchQrCode() {
|
||||
startActivity(UserCodeActivity.newIntent(this, sharedActionViewModel.session.myUserId))
|
||||
}
|
||||
|
||||
private fun launchInviteFriends() {
|
||||
activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createPermalink(sharedActionViewModel.session.myUserId)?.let { permalink ->
|
||||
analyticsTracker.screen(MobileScreen(screenName = MobileScreen.ScreenName.InviteFriends))
|
||||
|
|
|
@ -119,17 +119,19 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun observeReleaseNotes() = withState { state ->
|
||||
// we don't want to show release notes for new users or after relogin
|
||||
if (state.authenticationDescription == null && vectorPreferences.isNewAppLayoutEnabled()) {
|
||||
releaseNotesPreferencesStore.appLayoutOnboardingShown.onEach { isAppLayoutOnboardingShown ->
|
||||
if (!isAppLayoutOnboardingShown) {
|
||||
_viewEvents.post(HomeActivityViewEvents.ShowReleaseNotes)
|
||||
if (vectorPreferences.isNewAppLayoutEnabled()) {
|
||||
// we don't want to show release notes for new users or after relogin
|
||||
if (state.authenticationDescription == null) {
|
||||
releaseNotesPreferencesStore.appLayoutOnboardingShown.onEach { isAppLayoutOnboardingShown ->
|
||||
if (!isAppLayoutOnboardingShown) {
|
||||
_viewEvents.post(HomeActivityViewEvents.ShowReleaseNotes)
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
} else {
|
||||
// we assume that users which came from auth flow either have seen updates already (relogin) or don't need them (new user)
|
||||
viewModelScope.launch {
|
||||
releaseNotesPreferencesStore.setAppLayoutOnboardingShown(true)
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
} else {
|
||||
// we assume that users which came from auth flow either have seen updates already (relogin) or don't need them (new user)
|
||||
viewModelScope.launch {
|
||||
releaseNotesPreferencesStore.setAppLayoutOnboardingShown(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ sealed class RoomDetailViewEvents : VectorViewEvents {
|
|||
object OpenRoomProfile : RoomDetailViewEvents()
|
||||
data class ShowRoomAvatarFullScreen(val matrixItem: MatrixItem?, val view: View?) : RoomDetailViewEvents()
|
||||
|
||||
object ShowWaitingView : RoomDetailViewEvents()
|
||||
data class ShowWaitingView(val text: String? = null) : RoomDetailViewEvents()
|
||||
object HideWaitingView : RoomDetailViewEvents()
|
||||
|
||||
data class DownloadFileState(
|
||||
|
|
|
@ -493,7 +493,7 @@ class TimelineFragment :
|
|||
is RoomDetailViewEvents.ShowInfoOkDialog -> showDialogWithMessage(it.message)
|
||||
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
|
||||
RoomDetailViewEvents.LeaveJitsiConference -> leaveJitsiConference()
|
||||
RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView()
|
||||
is RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView(it.text)
|
||||
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
|
||||
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it)
|
||||
is RoomDetailViewEvents.OpenRoom -> handleOpenRoom(it)
|
||||
|
|
|
@ -39,6 +39,7 @@ import im.vector.app.core.utils.BehaviorDataSource
|
|||
import im.vector.app.features.analytics.AnalyticsTracker
|
||||
import im.vector.app.features.analytics.DecryptionFailureTracker
|
||||
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||
import im.vector.app.features.call.conference.ConferenceEvent
|
||||
import im.vector.app.features.call.conference.JitsiActiveConferenceHolder
|
||||
|
@ -78,12 +79,12 @@ import kotlinx.coroutines.flow.onEach
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixPatterns
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.raw.RawService
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||
import org.matrix.android.sdk.api.session.events.model.RelationType
|
||||
|
@ -100,9 +101,11 @@ import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
|||
import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
||||
|
@ -185,6 +188,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
init {
|
||||
// This method will take care of a null room to update the state.
|
||||
observeRoomSummary()
|
||||
observeLocalRoomSummary()
|
||||
if (room == null) {
|
||||
timeline = null
|
||||
} else {
|
||||
|
@ -617,7 +621,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun handleAddJitsiConference(action: RoomDetailAction.AddJitsiWidget) {
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView())
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val widget = jitsiService.createJitsiWidget(initialState.roomId, action.withVideo)
|
||||
|
@ -637,7 +641,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
if (isJitsiWidget) {
|
||||
setState { copy(jitsiState = jitsiState.copy(deleteWidgetInProgress = true)) }
|
||||
} else {
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView())
|
||||
}
|
||||
session.widgetService().destroyRoomWidget(initialState.roomId, widgetId)
|
||||
// local echo
|
||||
|
@ -1231,6 +1235,32 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun observeLocalRoomSummary() {
|
||||
if (room != null && RoomLocalEcho.isLocalEchoId(room.roomId)) {
|
||||
room.flow().liveLocalRoomSummary()
|
||||
.unwrap()
|
||||
.map { it.creationState }
|
||||
.distinctUntilChanged()
|
||||
.onEach { creationState ->
|
||||
when (creationState) {
|
||||
LocalRoomCreationState.NOT_CREATED -> Unit
|
||||
LocalRoomCreationState.CREATING ->
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView(stringProvider.getString(R.string.creating_direct_room)))
|
||||
LocalRoomCreationState.FAILURE -> {
|
||||
_viewEvents.post(RoomDetailViewEvents.HideWaitingView)
|
||||
}
|
||||
LocalRoomCreationState.CREATED -> {
|
||||
room.localRoomSummary()?.let {
|
||||
analyticsTracker.capture(CreatedRoom(isDM = it.roomSummary?.isDirect.orFalse()))
|
||||
_viewEvents.post(RoomDetailViewEvents.OpenRoom(it.replacementRoomId!!, true))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUnreadState() {
|
||||
if (room == null) return
|
||||
combine(
|
||||
|
@ -1322,26 +1352,11 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)?.also {
|
||||
onRoomTombstoneUpdated(it)
|
||||
setState { copy(tombstoneEvent = it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var roomTombstoneHandled = false
|
||||
private fun onRoomTombstoneUpdated(tombstoneEvent: Event) = withState { state ->
|
||||
if (roomTombstoneHandled) return@withState
|
||||
if (state.isLocalRoom()) {
|
||||
// Local room has been replaced, so navigate to the new room
|
||||
val roomId = tombstoneEvent.getClearContent()?.toModel<RoomTombstoneContent>()
|
||||
?.replacementRoomId
|
||||
?: return@withState
|
||||
_viewEvents.post(RoomDetailViewEvents.OpenRoom(roomId, closeCurrentRoom = true))
|
||||
roomTombstoneHandled = true
|
||||
} else {
|
||||
setState { copy(tombstoneEvent = tombstoneEvent) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the appropriate event (by paginating the thread timeline until the event is found
|
||||
* in the snapshot. The main reason for this function is to support the /relations api
|
||||
|
|
|
@ -31,4 +31,5 @@ sealed class RoomListAction : VectorViewModelAction {
|
|||
data class LeaveRoom(val roomId: String) : RoomListAction()
|
||||
data class JoinSuggestedRoom(val roomId: String, val viaServers: List<String>?) : RoomListAction()
|
||||
data class ShowRoomDetails(val roomId: String, val viaServers: List<String>?) : RoomListAction()
|
||||
object DeleteAllLocalRoom : RoomListAction()
|
||||
}
|
||||
|
|
|
@ -149,10 +149,13 @@ class RoomListFragment :
|
|||
(it.contentEpoxyController as? RoomSummaryPagedController)?.roomChangeMembershipStates = ms
|
||||
}
|
||||
}
|
||||
roomListViewModel.onEach(RoomListViewState::localRoomIds) {
|
||||
// Local rooms should not exist anymore when the room list is shown
|
||||
roomListViewModel.deleteLocalRooms(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
// Local rooms should not exist anymore when the room list is shown
|
||||
roomListViewModel.handle(RoomListAction.DeleteAllLocalRoom)
|
||||
}
|
||||
|
||||
private fun refreshCollapseStates() {
|
||||
|
|
|
@ -97,7 +97,6 @@ class RoomListViewModel @AssistedInject constructor(
|
|||
|
||||
init {
|
||||
observeMembershipChanges()
|
||||
observeLocalRooms()
|
||||
|
||||
spaceStateHandler.getSelectedSpaceFlow()
|
||||
.distinctUntilChanged()
|
||||
|
@ -125,16 +124,6 @@ class RoomListViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun observeLocalRooms() {
|
||||
session
|
||||
.flow()
|
||||
.liveRoomSummaries(roomSummaryQueryParams {
|
||||
roomId = QueryStringValue.Contains(RoomLocalEcho.PREFIX)
|
||||
})
|
||||
.map { page -> page.map { it.roomId } }
|
||||
.setOnEach { copy(localRoomIds = it) }
|
||||
}
|
||||
|
||||
companion object : MavericksViewModelFactory<RoomListViewModel, RoomListViewState> by hiltMavericksViewModelFactory()
|
||||
|
||||
private val roomListSectionBuilder = RoomListSectionBuilder(
|
||||
|
@ -166,6 +155,7 @@ class RoomListViewModel @AssistedInject constructor(
|
|||
is RoomListAction.ToggleSection -> handleToggleSection(action.section)
|
||||
is RoomListAction.JoinSuggestedRoom -> handleJoinSuggestedRoom(action)
|
||||
is RoomListAction.ShowRoomDetails -> handleShowRoomDetails(action)
|
||||
RoomListAction.DeleteAllLocalRoom -> handleDeleteLocalRooms()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,14 +163,6 @@ class RoomListViewModel @AssistedInject constructor(
|
|||
return session.getRoom(roomId)?.stateService()?.isPublic().orFalse()
|
||||
}
|
||||
|
||||
fun deleteLocalRooms(roomsIds: Iterable<String>) {
|
||||
viewModelScope.launch {
|
||||
roomsIds.forEach {
|
||||
session.roomService().deleteLocalRoom(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PRIVATE METHODS *****************************************************************************
|
||||
|
||||
private fun handleSelectRoom(action: RoomListAction.SelectRoom) = withState {
|
||||
|
@ -338,4 +320,16 @@ class RoomListViewModel @AssistedInject constructor(
|
|||
_viewEvents.post(value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDeleteLocalRooms() {
|
||||
val localRoomIds = session.roomService()
|
||||
.getRoomSummaries(roomSummaryQueryParams { roomId = QueryStringValue.Contains(RoomLocalEcho.PREFIX) })
|
||||
.map { it.roomId }
|
||||
|
||||
viewModelScope.launch {
|
||||
localRoomIds.forEach {
|
||||
session.roomService().deleteLocalRoom(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ data class RoomListViewState(
|
|||
val asyncSuggestedRooms: Async<List<SpaceChildInfo>> = Uninitialized,
|
||||
val currentUserName: String? = null,
|
||||
val asyncSelectedSpace: Async<RoomSummary?> = Uninitialized,
|
||||
val localRoomIds: List<String> = emptyList()
|
||||
) : MavericksState {
|
||||
|
||||
constructor(args: RoomListParams) : this(displayMode = args.displayMode)
|
||||
|
|
|
@ -103,6 +103,9 @@ abstract class RoomSummaryItem : VectorEpoxyModel<RoomSummaryItem.Holder>(R.layo
|
|||
@EpoxyAttribute
|
||||
var showSelected: Boolean = false
|
||||
|
||||
@EpoxyAttribute
|
||||
var useSingleLineForLastEvent: Boolean = false
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
|
||||
|
@ -122,6 +125,10 @@ abstract class RoomSummaryItem : VectorEpoxyModel<RoomSummaryItem.Holder>(R.layo
|
|||
holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending
|
||||
renderSelection(holder, showSelected)
|
||||
holder.roomAvatarPresenceImageView.render(showPresence, userPresence)
|
||||
|
||||
if (useSingleLineForLastEvent) {
|
||||
holder.subtitleView.setLines(1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderDisplayMode(holder: Holder) = when (displayMode) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue