Merge branch 'develop' into feature/ons/device_manager_current_session
* develop: (169 commits) new app layouts invites (#6911) bottom navigation tabs are removed for AppLayout (#6905) focus input when changing server address Fix copyright Improve createRoomThreePidEvents for clarity Remove roomCreatorUserId and use current userId by default Remove useless explicit field type Change visibility of LocalRoomThirdPartyInviteContent to internal Remove useless apply in CreateLocalRoomStateEventsTask Update doc Extract condition to reduce code complexity Verify tombstone event Remove safe call Add unit tests for CreateRoomFromLocalRoomTask Add unit tests for CreateLocalRoomStateEventsTask Set stateKey as empty by default Create local room state events in dedicated task Fix local events generation following the specification Update CreateRoomParams from the potential FeaturePreset before persisting Persists CreateRoomParams into LocalRoomSummaryEntity ... # Conflicts: # vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
This commit is contained in:
commit
7a3a5ae30d
.github
CHANGES.mdbuild.gradlechangelog.d
5525.wip6505.wip6565.wip6645.misc6693.feature6746.feature6750.wip6783.misc6786.misc6798.wip6799.misc6806.wip6808.misc6889.wip6894.misc6926.misc
dependencies.gradledocs
fastlane/metadata/android
cs-CZ/changelogs
en-US/changelogs
et/changelogs
fa/changelogs
fr-FR/changelogs
gl-ES
changelogs
40104160.txt40104180.txt40104190.txt40104200.txt40104220.txt40104230.txt40104240.txt40104250.txt40104260.txt40104270.txt
full_description.txtshort_description.txttitle.txtid
it-IT/changelogs
pt-BR/changelogs
sk/changelogs
uk/changelogs
zh-TW/changelogs
matrix-sdk-android
build.gradle
src/main/java/org/matrix/android/sdk
api
internal
crypto
database
RealmCompactOnLaunch.ktRealmLiveEntityObserver.ktRealmSessionStoreMigration.ktSessionRealmConfigurationFactory.kt
migration
model
query
tools
debug
di
session
DefaultSession.kt
room
RoomModule.kt
create
CreateLocalRoomStateEventsTask.ktCreateLocalRoomTask.ktCreateRoomBody.ktCreateRoomFromLocalRoomTask.ktCreateRoomTask.ktLocalRoomThirdPartyInviteContent.kt
delete
membership/threepid
send
state
timeline
sync
2
.github/ISSUE_TEMPLATE/release.yml
vendored
2
.github/ISSUE_TEMPLATE/release.yml
vendored
@ -21,6 +21,8 @@ body:
|
||||
- [ ] While Weblate is locked, and after the PR from Weblate has been merged, handle all the TODOs in the main `strings.xml` file
|
||||
- [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect.
|
||||
|
||||
- [ ] Ensure all [the required PRs](https://github.com/vector-im/element-android/pulls?q=is%3Aopen+is%3Apr+label%3AZ-NextRelease) have been merged
|
||||
|
||||
### Do the release
|
||||
|
||||
- [ ] Make sure `develop` and `main` are up to date (git pull)
|
||||
|
4
.github/workflows/danger.yml
vendored
4
.github/workflows/danger.yml
vendored
@ -11,8 +11,10 @@ jobs:
|
||||
- run: |
|
||||
npm install --save-dev @babel/plugin-transform-flow-strip-types
|
||||
- name: Danger
|
||||
uses: danger/danger-js@11.1.1
|
||||
uses: danger/danger-js@11.1.2
|
||||
with:
|
||||
args: "--dangerfile tools/danger/dangerfile.js"
|
||||
env:
|
||||
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
|
||||
# Fallback for forks
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
4
.github/workflows/quality.yml
vendored
4
.github/workflows/quality.yml
vendored
@ -66,11 +66,13 @@ jobs:
|
||||
yarn add danger-plugin-lint-report --dev
|
||||
- name: Danger lint
|
||||
if: always()
|
||||
uses: danger/danger-js@11.1.1
|
||||
uses: danger/danger-js@11.1.2
|
||||
with:
|
||||
args: "--dangerfile tools/danger/dangerfile-lint.js"
|
||||
env:
|
||||
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
|
||||
# Fallback for forks
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin
|
||||
dependency-analysis:
|
||||
|
3
.github/workflows/triage-labelled.yml
vendored
3
.github/workflows/triage-labelled.yml
vendored
@ -98,7 +98,8 @@ jobs:
|
||||
# Skip in forks
|
||||
if: >
|
||||
github.repository == 'vector-im/element-android' &&
|
||||
(contains(github.event.issue.labels.*.name, 'Team: Delight'))
|
||||
(contains(github.event.issue.labels.*.name, 'Team: Delight') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-AppLayout'))
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
|
48
CHANGES.md
48
CHANGES.md
@ -1,3 +1,51 @@
|
||||
Changes in Element v1.4.34 (2022-08-23)
|
||||
=======================================
|
||||
|
||||
Features ✨
|
||||
----------
|
||||
- [Notification] - Handle creation of notification for live location and poll start ([#6746](https://github.com/vector-im/element-android/issues/6746))
|
||||
|
||||
Bugfixes 🐛
|
||||
----------
|
||||
- Fixes onboarding requiring matrix.org to be accessible on the first step, the server can now be manually changed ([#6718](https://github.com/vector-im/element-android/issues/6718))
|
||||
- Fixing sign in/up for homeservers that rely on the SSO fallback url ([#6827](https://github.com/vector-im/element-android/issues/6827))
|
||||
- Fixes uncaught exceptions in the SyncWorker to cause the worker to become stuck in the failure state ([#6836](https://github.com/vector-im/element-android/issues/6836))
|
||||
- Fixes onboarding captcha crashing when no WebView is available by showing an error with information instead ([#6855](https://github.com/vector-im/element-android/issues/6855))
|
||||
- Removes ability to continue registration after the app has been destroyed, fixes the next steps crashing due to missing information from the previous steps ([#6860](https://github.com/vector-im/element-android/issues/6860))
|
||||
- Fixes crash when exiting the login or registration entry screens whilst they're loading ([#6861](https://github.com/vector-im/element-android/issues/6861))
|
||||
- Fixes server selection being unable to trust certificates ([#6864](https://github.com/vector-im/element-android/issues/6864))
|
||||
- Ensure SyncThread is started when the app is launched after a Push has been received. ([#6884](https://github.com/vector-im/element-android/issues/6884))
|
||||
- Fixes missing firebase notifications after logging in when UnifiedPush distributor is installed ([#6891](https://github.com/vector-im/element-android/issues/6891))
|
||||
|
||||
In development 🚧
|
||||
----------------
|
||||
- Create DM room only on first message - Trigger the flow when the "Direct Message" action is selected from the room member details screen ([#5525](https://github.com/vector-im/element-android/issues/5525))
|
||||
- added filter tabs for new App layout's Home screen ([#6505](https://github.com/vector-im/element-android/issues/6505))
|
||||
- [App Layout] added dialog to configure app layout ([#6506](https://github.com/vector-im/element-android/issues/6506))
|
||||
- Adds space list bottom sheet for new app layout ([#6749](https://github.com/vector-im/element-android/issues/6749))
|
||||
- [App Layout] Dialpad moved from bottom navigation tab to a separate activity accessed via home screen context menu ([#6787](https://github.com/vector-im/element-android/issues/6787))
|
||||
- Makes toolbar switch title based on space in New App Layout ([#6795](https://github.com/vector-im/element-android/issues/6795))
|
||||
- [Devices management] Add a feature flag and empty screen for future new layout ([#6798](https://github.com/vector-im/element-android/issues/6798))
|
||||
- Adds new chat bottom sheet as the click action of the main FAB in the new app layout ([#6801](https://github.com/vector-im/element-android/issues/6801))
|
||||
- [Devices management] Other sessions section in new layout ([#6806](https://github.com/vector-im/element-android/issues/6806))
|
||||
- [New Layout] Adds space settings accessible through clicking the toolbar ([#6859](https://github.com/vector-im/element-android/issues/6859))
|
||||
- Adds New App Layout FABs (hidden behind feature flag) ([#6693](https://github.com/vector-im/element-android/issues/6693))
|
||||
|
||||
SDK API changes ⚠️
|
||||
------------------
|
||||
- Rename `DebugService.logDbUsageInfo` (resp. `Session.logDbUsageInfo`) to `DebugService.getDbUsageInfo` (resp. `Session.getDbUsageInfo`) and return a String instead of logging. The caller may want to log the String. ([#6884](https://github.com/vector-im/element-android/issues/6884))
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Removes the Login2 proof of concept - replaced by the FTUE changes ([#5974](https://github.com/vector-im/element-android/issues/5974))
|
||||
- Enable auto-capitalization for Room creation Title field ([#6645](https://github.com/vector-im/element-android/issues/6645))
|
||||
- Decouples the variant logic from the vector module ([#6783](https://github.com/vector-im/element-android/issues/6783))
|
||||
- Add a developer setting to enable LeakCanary at runtime ([#6786](https://github.com/vector-im/element-android/issues/6786))
|
||||
- [Create Room] Reduce some boilerplate with room state event contents ([#6799](https://github.com/vector-im/element-android/issues/6799))
|
||||
- [Call] Memory leak after a call ([#6808](https://github.com/vector-im/element-android/issues/6808))
|
||||
- Fix some string template ([#6843](https://github.com/vector-im/element-android/issues/6843))
|
||||
|
||||
|
||||
Changes in Element v1.4.32 (2022-08-10)
|
||||
=======================================
|
||||
|
||||
|
@ -24,12 +24,12 @@ buildscript {
|
||||
classpath libs.gradle.gradlePlugin
|
||||
classpath libs.gradle.kotlinPlugin
|
||||
classpath libs.gradle.hiltPlugin
|
||||
classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.2'
|
||||
classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.3'
|
||||
classpath 'com.google.gms:google-services:4.3.13'
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513'
|
||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
|
||||
classpath "com.likethesalad.android:stem-plugin:2.1.1"
|
||||
classpath 'org.owasp:dependency-check-gradle:7.1.1'
|
||||
classpath 'org.owasp:dependency-check-gradle:7.1.2'
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10"
|
||||
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
@ -44,7 +44,7 @@ plugins {
|
||||
id "io.gitlab.arturbosch.detekt" version "1.21.0"
|
||||
|
||||
// Dependency Analysis
|
||||
id 'com.autonomousapps.dependency-analysis' version "1.11.2"
|
||||
id 'com.autonomousapps.dependency-analysis' version "1.12.0"
|
||||
}
|
||||
|
||||
// https://github.com/jeremylong/DependencyCheck
|
||||
@ -151,6 +151,8 @@ allprojects {
|
||||
"experimental:comment-wrapping",
|
||||
// - A KDoc comment after any other element on the same line must be separated by a new line
|
||||
"experimental:kdoc-wrapping",
|
||||
// Ignore error "Redundant curly braces", since we use it to fix false positives, for instance in "elementLogs.${i}.txt"
|
||||
"string-template",
|
||||
]
|
||||
}
|
||||
|
||||
|
1
changelog.d/5525.wip
Normal file
1
changelog.d/5525.wip
Normal file
@ -0,0 +1 @@
|
||||
Create DM room only on first message - Create the DM and navigate to the new room after sending an event
|
@ -1 +0,0 @@
|
||||
added filter tabs for new App layout's Home screen
|
1
changelog.d/6565.wip
Normal file
1
changelog.d/6565.wip
Normal file
@ -0,0 +1 @@
|
||||
[App Layout] Bottom navigation tabs are removed for new home screen
|
@ -1 +0,0 @@
|
||||
Enable auto-capitalization for Room creation Title field
|
@ -1 +0,0 @@
|
||||
Adds New App Layout FABs (hidden behind feature flag)
|
@ -1 +0,0 @@
|
||||
[Notification] - Handle creation of notification for live location and poll start
|
1
changelog.d/6750.wip
Normal file
1
changelog.d/6750.wip
Normal file
@ -0,0 +1 @@
|
||||
[App Layout] fixed space switching dialog measured with wrong height sometimes
|
@ -1 +0,0 @@
|
||||
Decouples the variant logic from the vector module
|
@ -1 +0,0 @@
|
||||
Add a developer setting to enable LeakCanary at runtime
|
@ -1 +0,0 @@
|
||||
[Devices management] Add a feature flag and empty screen for future new layout
|
@ -1 +0,0 @@
|
||||
[Create Room] Reduce some boilerplate with room state event contents
|
@ -1 +0,0 @@
|
||||
[Devices management] Other sessions section in new layout
|
@ -1 +0,0 @@
|
||||
[Call] Memory leak after a call
|
1
changelog.d/6889.wip
Normal file
1
changelog.d/6889.wip
Normal file
@ -0,0 +1 @@
|
||||
[App Layout] new room invites screen
|
1
changelog.d/6894.misc
Normal file
1
changelog.d/6894.misc
Normal file
@ -0,0 +1 @@
|
||||
Remove FragmentModule and the Fragment factory. No need to Inject the constructor on your Fragment, just add @AndroidEntryPoint annotation and @Inject class members.
|
1
changelog.d/6926.misc
Normal file
1
changelog.d/6926.misc
Normal file
@ -0,0 +1 @@
|
||||
Focus input field when editing homeserver address to speed up login and registration.
|
@ -22,7 +22,7 @@ def markwon = "4.6.2"
|
||||
def moshi = "1.13.0"
|
||||
def lifecycle = "2.5.1"
|
||||
def flowBinding = "1.2.0"
|
||||
def flipper = "0.156.0"
|
||||
def flipper = "0.161.0"
|
||||
def epoxy = "4.6.2"
|
||||
def mavericks = "2.7.0"
|
||||
def glide = "4.13.2"
|
||||
@ -30,7 +30,7 @@ def bigImageViewer = "1.8.1"
|
||||
def jjwt = "0.11.5"
|
||||
def vanniktechEmoji = "0.15.0"
|
||||
|
||||
def fragment = "1.5.1"
|
||||
def fragment = "1.5.2"
|
||||
|
||||
// Testing
|
||||
def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819
|
||||
@ -104,6 +104,7 @@ ext.libs = [
|
||||
'moshi' : "com.squareup.moshi:moshi:$moshi",
|
||||
'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi",
|
||||
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
|
||||
'moshiAdapters' : "com.squareup.moshi:moshi-adapters:$moshi",
|
||||
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
|
||||
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
|
||||
],
|
||||
|
@ -85,6 +85,8 @@ To let Danger check all the PRs, including PRs form forks, a GitHub account have
|
||||
- password: Stored on Passbolt
|
||||
- GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
|
||||
|
||||
PRs from forks do not always have access to the secret `secrets.DANGER_GITHUB_API_TOKEN`, so `secrets.GITHUB_TOKEN` is also provided to the job environment. If `secrets.DANGER_GITHUB_API_TOKEN` is available, it will be used, so user `ElementBot` will comment the PR. Else `secrets.GITHUB_TOKEN` will be used, and bot `github-actions` will comment the PR.
|
||||
|
||||
## Useful links
|
||||
|
||||
- https://danger.systems/
|
||||
|
@ -7,8 +7,8 @@ Hilt is built on top of Dagger 2 and simplify usage by removing needs to create
|
||||
When you create a new feature, you should have the following:
|
||||
|
||||
Annotate your Activity with @AndroidEntryPoint
|
||||
Annotate your Fragment with @AndroidEntryPoint
|
||||
If you have a BottomSheetFragment => Annotate it with @AndroidEntryPoint
|
||||
Otherwise => Add your Fragment to the FragmentModule
|
||||
Add your ViewModel.Factory to the MavericksViewModelModule
|
||||
Makes sure your ViewModel as the following code:
|
||||
|
||||
|
2
fastlane/metadata/android/cs-CZ/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/cs-CZ/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Hlavní změny v této verzi: Umožňuje vylepšené přihlašování a registraci.
|
||||
Úplný seznam změn: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/cs-CZ/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/cs-CZ/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Hlavní změny v této verzi: Umožňuje vylepšené přihlašování a registraci.
|
||||
Úplný seznam změn: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/en-US/changelogs/40104340.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40104340.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Main changes in this version: Various bug fixes and stability improvements.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/et/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/et/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Põhilised muutused selles versioonis: senisest parem liitumise ja sisselogimise töövoog.
|
||||
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/et/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/et/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Põhilised muutused selles versioonis: senisest parem liitumise ja sisselogimise töövoog.
|
||||
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/fa/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/fa/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
تغییرات عمده در این نگارش: به کار انداختن ورود بهبود یافته و سفرهای ورود.
|
||||
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/fa/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/fa/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
تغییرات عمده در این نگارش: به کار انداختن ورود بهبود یافته و سفرهای ورود.
|
||||
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/fr-FR/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/fr-FR/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Principaux changements pour cette version : Activation de l’authentification et du parcours d’inscription améliorés.
|
||||
Intégralité des changements : https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/fr-FR/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/fr-FR/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Principaux changements pour cette version : Activation de l’authentification et du parcours d’inscription améliorés.
|
||||
Intégralité des changements : https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/id/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/id/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Perubahan utama dalam versi ini: Mengaktifkan perjalanan masuk dan keluar yang diperbaiki.
|
||||
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/id/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/id/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Perubahan utama dalam versi ini: Mengaktifkan perjalanan masuk dan keluar yang diperbaiki.
|
||||
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases
|
@ -1,42 +1,42 @@
|
||||
Element adalah perpesanan yang aman dan aplikasi kolaborasi tim produktivitas yang ideal untuk obrolan grup saat bekerja jarak jauh. Aplikasi perpesanan ini menggunakan enkripsi ujung-ke-ujung untuk memberikan konferensi video, pembagian file, dan panggilan suara yang aman.
|
||||
Element adalah perpesanan yang aman dan aplikasi kolaborasi tim produktivitas yang ideal untuk obrolan grup saat bekerja jarak jauh. Aplikasi perpesanan ini menggunakan enkripsi ujung-ke-ujung untuk menyediakan konferensi video, pembagian berkas, dan panggilan suara yang aman.
|
||||
|
||||
<b>Fitur Element termasuk</b>
|
||||
- Alat komunikasi online yang canggih
|
||||
<b>Fitur Element termasuk:</b>
|
||||
- Alat komunikasi daring yang canggih
|
||||
- Pesan-pesan yang dienkripsi sepenuhnya untuk memungkinkan komunikasi perusahaan yang lebih aman, bahkan untuk pekerja jarak jauh
|
||||
- Obrolan terdesentralisasi berdasarkan kerangka Matrix yang sumber terbuka
|
||||
- Pembagian file aman dengan data terenkripsi saat mengelola proyek
|
||||
- Obrolan terdesentralisasi berdasarkan kerangka kerja Matrix yang sumber terbuka
|
||||
- Pembagian berkas aman dengan data terenkripsi saat mengelola proyek
|
||||
- Obrolan video dengan VoIP dan pembagian layar
|
||||
- Integrasi yang mudah dengan alat kolaborasi online favorit Anda, alat manajemen proyek, layanan VoIP dan aplikasi perpesanan tim lainnya
|
||||
- Integrasi yang mudah dengan alat kolaborasi daring favorit Anda, alat pengelola proyek, layanan VoIP dan aplikasi perpesanan tim lainnya
|
||||
|
||||
Element benar-benar berbeda dari aplikasi perpesanan dan aplikasi kolaborasi lainnya. Element beroperasi pada Matrix, jaringan terbuka untuk pengiriman pesan yang aman dan komunikasi terdesentralisasi.
|
||||
Element benar-benar berbeda dari aplikasi perpesanan dan aplikasi kolaborasi lainnya. Element beroperasi pada Matrix, jaringan terbuka untuk pengiriman pesan yang aman dan komunikasi yang terdesentralisasi.
|
||||
|
||||
<b>Perpesanan dengan privasi dan enkripsi</b>
|
||||
Element melindungi Anda dari iklan yang tidak diinginkan, penambangan data dan taman berdinding. Element juga mengamankan semua data Anda, komunikasi video dan suara satu-ke-satu dengan enkripsi ujung-ke-ujung dan verifikasi perangkat menggunakan penandatanganan silang.
|
||||
Element melindungi Anda dari iklan yang tidak diinginkan, penambangan data, dan taman berdinding. Element juga mengamankan semua data Anda, komunikasi video dan suara satu-ke-satu dengan enkripsi ujung-ke-ujung, dan verifikasi perangkat menggunakan penandatanganan silang.
|
||||
|
||||
Element memberikan Anda kendali atas privasi Anda sambil memungkinkan Anda untuk berkomunikasi dengan siapa saja secara aman di jaringan Matrix, atau alat kolaborasi bisnis lainnya dengan mengintegrasikan aplikasi-aplikasi seperti Slack.
|
||||
Element memberikan Anda kendali atas privasi Anda sambil memungkinkan Anda untuk berkomunikasi dengan siapa saja secara aman di jaringan Matrix, atau alat kolaborasi bisnis lainnya dengan mengintegrasikan aplikasi seperti Slack.
|
||||
|
||||
<b>Element dapat dihost sendiri</b>
|
||||
Untuk memungkinkan lebih banyak kendali atas data dan pesan-pesan sensitif Anda, Element dapat dihost sendiri atau Anda dapat memilih host berbasis Matrix, standar untuk komunikasi terdesentralisasi sumber terbuka. Element memberi Anda privasi, kepatuhan keamanan, dan fleksibilitas integrasi.
|
||||
<b>Element dapat di-host sendiri</b>
|
||||
Untuk memungkinkan lebih banyak kendali atas data dan pesan-pesan sensitif Anda, Element dapat dilayani sendiri atau Anda dapat memilih layanan berbasis Matrix, standar untuk komunikasi terdesentralisasi sumber terbuka. Element memberikan Anda privasi, kepatuhan keamanan, dan fleksibilitas integrasi.
|
||||
|
||||
<b>Miliki data Anda</b>
|
||||
Anda memutuskan di mana untuk menyimpan data dan pesan-pesan Anda, tanpa risiko penambangan data atau akses dari pihak ketiga.
|
||||
|
||||
Element menempatkan Anda dalam kendali dengan cara yang berbeda:
|
||||
1. Dapatkan akun gratis pada server publik matrix.org yang dihost oleh pengembang Matrix, atau memilih dari ribuan server publik yang dihost oleh sukarelawan
|
||||
2. Host sendiri akun Anda dengan menjalankan server pada infrastruktur IT Anda sendiri
|
||||
1. Dapatkan akun gratis pada server publik matrix.org yang dilayani oleh pengembang Matrix, atau memilih dari ribuan server publik yang dilayani oleh sukarelawan
|
||||
2. Layani akun Anda sendiri dengan menjalankan server pada infrastruktur IT Anda sendiri
|
||||
3. Daftar untuk akun di server khusus dengan berlangganan platform hosting Layanan Matrix Element
|
||||
|
||||
<b>Perpesanan dan kolaborasi terbuka</b>
|
||||
Anda dapat mengobrol dengan siapa saja di jaringan Matrix, jika mereka menggunakan Element, aplikasi Matrix lain atau bahkan menggunakan aplikasi perpesanan yang berbeda.
|
||||
Anda dapat mengobrol dengan siapa saja di jaringan Matrix, jika mereka menggunakan Element, aplikasi Matrix lain, atau bahkan menggunakan aplikasi perpesanan yang berbeda.
|
||||
|
||||
<b>Sangat aman</b>
|
||||
Enkripsi ujung-ke-ujung yang nyata (hanya mereka yang dalam obrolan dapat mendekripsi pesan), dan verifikasi perangkat menggunakan penandatanganan silang.
|
||||
Enkripsi ujung-ke-ujung yang nyata (hanya mereka yang di dalam obrolan dapat mendekripsikan pesan), dan verifikasi perangkat menggunakan penandatanganan silang.
|
||||
|
||||
<b>Komunikasi dan integrasi lengkap</b>
|
||||
Perpesanan, panggilan suara dan video, pembagian file, pembagian layar dan banyak integrasi bot dan widget. Buat ruangan dan komunitas, tetap terhubung dan selesaikan hal-hal penting.
|
||||
Perpesanan, panggilan suara dan video, pembagian berkas, pembagian layar dan banyak integrasi bot dan widget. Buat ruangan dan komunitas, tetap terhubung, dan selesaikan hal-hal penting.
|
||||
|
||||
<b>Ambil di mana Anda tinggalkan</b>
|
||||
Tetap terhubung di mana Anda berada, dengan riwayat pesan yang disinkronkan di semua perangkat Anda dan web di https://app.element.io
|
||||
Tetap terhubung di mana Anda berada, dengan riwayat pesan yang disinkronkan pada semua perangkat Anda dan pada web di https://app.element.io
|
||||
|
||||
<b>Sumber terbuka</b>
|
||||
Element Android adalah proyek sumber terbuka, dihost oleh GitHub. Silakan laporkan masalah yang Anda temukan, atau membuat kontribusi ke pengembangannya di https://github.com/vector-im/element-android
|
||||
Element Android adalah proyek sumber terbuka, dilayani oleh GitHub. Silakan laporkan masalah yang Anda temukan, atau membuat kontribusi ke pengembangannya di https://github.com/vector-im/element-android
|
||||
|
2
fastlane/metadata/android/it-IT/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/it-IT/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Modifiche principali in questa versione: introduce i percorsi migliorati di accesso e registrazione.
|
||||
Cronologia completa: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/it-IT/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/it-IT/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Modifiche principali in questa versione: introduce i percorsi migliorati di accesso e registrazione.
|
||||
Cronologia completa: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/pt-BR/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/pt-BR/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Principais mudanças nesta versão: Habilita as jornadas melhoradas de sign in e sign up.
|
||||
Changelog completo: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/pt-BR/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/pt-BR/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Principais mudanças nesta versão: Habilita as jornadas melhoradas de sign in e sign up.
|
||||
Changelog completo: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/sk/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/sk/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Hlavné zmeny v tejto verzii: Umožňuje vylepšené postupy prihlasovania a registrácie.
|
||||
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/sk/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/sk/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Hlavné zmeny v tejto verzii: Umožňuje vylepšené postupy prihlasovania a registrácie.
|
||||
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/uk/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Основні зміни в цій версії: Поліпшені вхід і реєстрація.
|
||||
Перелік усіх змін: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/uk/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Основні зміни в цій версії: Поліпшені вхід і реєстрація.
|
||||
Перелік усіх змін: https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/zh-TW/changelogs/40104300.txt
Normal file
2
fastlane/metadata/android/zh-TW/changelogs/40104300.txt
Normal file
@ -0,0 +1,2 @@
|
||||
此版本中的主要變動:啟用改善的登入與註冊流程。
|
||||
完整的變更紀錄:https://github.com/vector-im/element-android/releases
|
2
fastlane/metadata/android/zh-TW/changelogs/40104310.txt
Normal file
2
fastlane/metadata/android/zh-TW/changelogs/40104310.txt
Normal file
@ -0,0 +1,2 @@
|
||||
此版本中的主要變動:啟用改善的登入與註冊流程。
|
||||
完整的變更紀錄:https://github.com/vector-im/element-android/releases
|
@ -17,7 +17,7 @@ buildscript {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath "io.realm:realm-gradle-plugin:10.11.0"
|
||||
classpath "io.realm:realm-gradle-plugin:10.11.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ android {
|
||||
// that the app's state is completely cleared between tests.
|
||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||
|
||||
buildConfigField "String", "SDK_VERSION", "\"1.4.34\""
|
||||
buildConfigField "String", "SDK_VERSION", "\"1.4.36\""
|
||||
|
||||
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
|
||||
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
|
||||
@ -163,6 +163,7 @@ dependencies {
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
||||
|
||||
implementation libs.squareup.moshi
|
||||
implementation libs.squareup.moshiAdapters
|
||||
kapt libs.squareup.moshiKotlin
|
||||
|
||||
api "com.atlassian.commonmark:commonmark:0.13.0"
|
||||
@ -199,7 +200,7 @@ dependencies {
|
||||
implementation libs.apache.commonsImaging
|
||||
|
||||
// Phone number https://github.com/google/libphonenumber
|
||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.53'
|
||||
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.54'
|
||||
|
||||
testImplementation libs.tests.junit
|
||||
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||
|
@ -28,7 +28,7 @@ interface DebugService {
|
||||
fun getAllRealmConfigurations(): List<RealmConfiguration>
|
||||
|
||||
/**
|
||||
* Prints out info on DB size to logcat.
|
||||
* Get info on DB size.
|
||||
*/
|
||||
fun logDbUsageInfo()
|
||||
fun getDbUsageInfo(): String
|
||||
}
|
||||
|
@ -89,10 +89,14 @@ fun Throwable.isInvalidUIAAuth() = this is Failure.ServerError &&
|
||||
fun Throwable.isHomeserverUnavailable() = this is Failure.NetworkConnection &&
|
||||
this.ioException is UnknownHostException
|
||||
|
||||
fun Throwable.isHomeserverConnectionError() = this is Failure.NetworkConnection
|
||||
|
||||
fun Throwable.isMissingEmailVerification() = this is Failure.ServerError &&
|
||||
error.code == MatrixError.M_UNAUTHORIZED &&
|
||||
error.message == "Unable to get validated threepid"
|
||||
|
||||
fun Throwable.isUnrecognisedCertificate() = this is Failure.UnrecognizedCertificateFailure
|
||||
|
||||
/**
|
||||
* Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible
|
||||
*/
|
||||
|
@ -323,9 +323,9 @@ interface Session {
|
||||
fun getUiaSsoFallbackUrl(authenticationSessionId: String): String
|
||||
|
||||
/**
|
||||
* Debug API, will print out info on DB size to logcat.
|
||||
* Debug API, will return info about the DB.
|
||||
*/
|
||||
fun logDbUsageInfo()
|
||||
fun getDbUsageInfo(): String
|
||||
|
||||
/**
|
||||
* Debug API, return the list of all RealmConfiguration used by this session.
|
||||
|
@ -70,6 +70,9 @@ object EventType {
|
||||
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
|
||||
const val STATE_ROOM_SERVER_ACL = "m.room.server_acl"
|
||||
|
||||
// This type is for local purposes, it should never be processed by the server
|
||||
const val LOCAL_STATE_ROOM_THIRD_PARTY_INVITE = "local.room.third_party_invite"
|
||||
|
||||
// Call Events
|
||||
const val CALL_INVITE = "m.call.invite"
|
||||
const val CALL_CANDIDATES = "m.call.candidates"
|
||||
|
@ -18,10 +18,14 @@ package org.matrix.android.sdk.api.session.identity
|
||||
|
||||
import com.google.i18n.phonenumbers.NumberParseException
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.internal.session.profile.ThirdPartyIdentifier
|
||||
|
||||
sealed class ThreePid(open val value: String) {
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Email(val email: String) : ThreePid(email)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Msisdn(val msisdn: String) : ThreePid(msisdn)
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,16 @@
|
||||
package org.matrix.android.sdk.api.session.room.model.create
|
||||
|
||||
import android.net.Uri
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
open class CreateRoomParams {
|
||||
/**
|
||||
* A public visibility indicates that the room will be shown in the published room list.
|
||||
@ -61,12 +64,12 @@ open class CreateRoomParams {
|
||||
* A list of user IDs to invite to the room.
|
||||
* This will tell the server to invite everyone in the list to the newly created room.
|
||||
*/
|
||||
val invitedUserIds = mutableListOf<String>()
|
||||
var invitedUserIds = mutableListOf<String>()
|
||||
|
||||
/**
|
||||
* A list of objects representing third party IDs to invite into the room.
|
||||
*/
|
||||
val invite3pids = mutableListOf<ThreePid>()
|
||||
var invite3pids = mutableListOf<ThreePid>()
|
||||
|
||||
/**
|
||||
* Initial Guest Access.
|
||||
@ -99,14 +102,14 @@ open class CreateRoomParams {
|
||||
* The server will clobber the following keys: creator.
|
||||
* Future versions of the specification may allow the server to clobber other keys.
|
||||
*/
|
||||
val creationContent = mutableMapOf<String, Any>()
|
||||
var creationContent = mutableMapOf<String, Any>()
|
||||
|
||||
/**
|
||||
* A list of state events to set in the new room. This allows the user to override the default state events
|
||||
* set in the new room. The expected format of the state events are an object with type, state_key and content keys set.
|
||||
* Takes precedence over events set by preset, but gets overridden by name and topic keys.
|
||||
*/
|
||||
val initialStates = mutableListOf<CreateRoomStateEvent>()
|
||||
var initialStates = mutableListOf<CreateRoomStateEvent>()
|
||||
|
||||
/**
|
||||
* Set to true to disable federation of this room.
|
||||
@ -151,7 +154,7 @@ open class CreateRoomParams {
|
||||
* Supported value: MXCRYPTO_ALGORITHM_MEGOLM.
|
||||
*/
|
||||
var algorithm: String? = null
|
||||
private set
|
||||
internal set
|
||||
|
||||
var historyVisibility: RoomHistoryVisibility? = null
|
||||
|
||||
@ -161,10 +164,18 @@ open class CreateRoomParams {
|
||||
|
||||
var roomVersion: String? = null
|
||||
|
||||
var featurePreset: RoomFeaturePreset? = null
|
||||
@Transient var featurePreset: RoomFeaturePreset? = null
|
||||
|
||||
companion object {
|
||||
private const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate"
|
||||
private const val CREATION_CONTENT_KEY_ROOM_TYPE = "type"
|
||||
internal const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate"
|
||||
internal const val CREATION_CONTENT_KEY_ROOM_TYPE = "type"
|
||||
|
||||
fun fromJson(json: String?): CreateRoomParams? {
|
||||
return json?.let { MoshiProvider.providesMoshi().adapter(CreateRoomParams::class.java).fromJson(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun CreateRoomParams.toJSONString(): String {
|
||||
return MoshiProvider.providesMoshi().adapter(CreateRoomParams::class.java).toJson(this)
|
||||
}
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.model.create
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class CreateRoomStateEvent(
|
||||
/**
|
||||
* Required. The type of event to send.
|
||||
|
@ -53,6 +53,11 @@ interface SyncService {
|
||||
*/
|
||||
fun getSyncState(): SyncState
|
||||
|
||||
/**
|
||||
* This method returns true if the sync thread is alive, i.e. started.
|
||||
*/
|
||||
fun isSyncThreadAlive(): Boolean
|
||||
|
||||
/**
|
||||
* This method allows to listen the sync state.
|
||||
* @return a [LiveData] of [SyncState].
|
||||
|
@ -16,10 +16,12 @@
|
||||
package org.matrix.android.sdk.internal.crypto.tasks
|
||||
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomFromLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
|
||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
@ -37,12 +39,17 @@ internal class DefaultSendEventTask @Inject constructor(
|
||||
private val localEchoRepository: LocalEchoRepository,
|
||||
private val encryptEventTask: EncryptEventTask,
|
||||
private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||
private val createRoomFromLocalRoomTask: CreateRoomFromLocalRoomTask,
|
||||
private val roomAPI: RoomAPI,
|
||||
private val globalErrorReceiver: GlobalErrorReceiver
|
||||
) : SendEventTask {
|
||||
|
||||
override suspend fun execute(params: SendEventTask.Params): String {
|
||||
try {
|
||||
if (params.event.isLocalRoomEvent) {
|
||||
return createRoomAndSendEvent(params)
|
||||
}
|
||||
|
||||
// Make sure to load all members in the room before sending the event.
|
||||
params.event.roomId
|
||||
?.takeIf { params.encrypt }
|
||||
@ -78,6 +85,12 @@ internal class DefaultSendEventTask @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun createRoomAndSendEvent(params: SendEventTask.Params): String {
|
||||
val roomId = createRoomFromLocalRoomTask.execute(CreateRoomFromLocalRoomTask.Params(params.event.roomId.orEmpty()))
|
||||
Timber.d("State event: convert local room (${params.event.roomId}) to existing room ($roomId) before sending the event.")
|
||||
return execute(params.copy(event = params.event.copy(roomId = roomId)))
|
||||
}
|
||||
|
||||
@Throws
|
||||
private suspend fun handleEncryption(params: SendEventTask.Params): Event {
|
||||
if (params.encrypt && !params.event.isEncrypted()) {
|
||||
@ -91,4 +104,7 @@ internal class DefaultSendEventTask @Inject constructor(
|
||||
}
|
||||
return params.event
|
||||
}
|
||||
|
||||
private val Event.isLocalRoomEvent
|
||||
get() = RoomLocalEcho.isLocalEchoId(roomId.orEmpty())
|
||||
}
|
||||
|
@ -76,12 +76,12 @@ internal class VerificationTransportToDevice(
|
||||
.configureWith(SendToDeviceTask.Params(MessageType.MSGTYPE_VERIFICATION_REQUEST, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## verification [$tx.transactionId] send toDevice request success")
|
||||
Timber.v("## verification [${tx?.transactionId}] send toDevice request success")
|
||||
callback.invoke(localId, validKeyReq)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e("## verification [$tx.transactionId] failed to send toDevice request")
|
||||
Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,12 +103,12 @@ internal class VerificationTransportToDevice(
|
||||
.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_READY, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## verification [$tx.transactionId] send toDevice request success")
|
||||
Timber.v("## verification [${tx?.transactionId}] send toDevice request success")
|
||||
callback?.invoke()
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e("## verification [$tx.transactionId] failed to send toDevice request")
|
||||
Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ internal class VerificationTransportToDevice(
|
||||
.configureWith(SendToDeviceTask.Params(type, contentMap)) {
|
||||
this.callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("## SAS verification [$tx.transactionId] toDevice type '$type' success.")
|
||||
Timber.v("## SAS verification [${tx.transactionId}] toDevice type '$type' success.")
|
||||
if (onDone != null) {
|
||||
onDone()
|
||||
} else {
|
||||
@ -149,7 +149,7 @@ internal class VerificationTransportToDevice(
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e("## SAS verification [$tx.transactionId] failed to send toDevice in state : $tx.state")
|
||||
Timber.e("## SAS verification [${tx.transactionId}] failed to send toDevice in state : ${tx.state}")
|
||||
tx.cancel(onErrorReason)
|
||||
}
|
||||
}
|
||||
|
28
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmCompactOnLaunch.kt
Normal file
28
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmCompactOnLaunch.kt
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import io.realm.DefaultCompactOnLaunchCallback
|
||||
|
||||
class RealmCompactOnLaunch : DefaultCompactOnLaunchCallback() {
|
||||
/**
|
||||
* Forces all RealmCompactOnLaunch instances to be equal.
|
||||
* Avoids Realm throwing when multiple instances of this class are used.
|
||||
*/
|
||||
override fun equals(other: Any?) = other is RealmCompactOnLaunch
|
||||
override fun hashCode() = 0x1000
|
||||
}
|
2
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt
2
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmLiveEntityObserver.kt
@ -38,7 +38,7 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val r
|
||||
LiveEntityObserver, RealmChangeListener<RealmResults<T>> {
|
||||
|
||||
private companion object {
|
||||
val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND")
|
||||
val BACKGROUND_HANDLER = createBackgroundHandler("Matrix-LIVE_ENTITY_BACKGROUND")
|
||||
}
|
||||
|
||||
protected val observerScope = CoroutineScope(SupervisorJob() + BACKGROUND_HANDLER.asCoroutineDispatcher())
|
||||
|
@ -52,6 +52,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo032
|
||||
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.util.Normalizer
|
||||
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
|
||||
import javax.inject.Inject
|
||||
@ -60,7 +61,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
||||
private val normalizer: Normalizer
|
||||
) : MatrixRealmMigration(
|
||||
dbName = "Session",
|
||||
schemaVersion = 35L,
|
||||
schemaVersion = 36L,
|
||||
) {
|
||||
/**
|
||||
* Forces all RealmSessionStoreMigration instances to be equal.
|
||||
@ -105,5 +106,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
||||
if (oldVersion < 33) MigrateSessionTo033(realm).perform()
|
||||
if (oldVersion < 34) MigrateSessionTo034(realm).perform()
|
||||
if (oldVersion < 35) MigrateSessionTo035(realm).perform()
|
||||
if (oldVersion < 36) MigrateSessionTo036(realm).perform()
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
|
||||
}
|
||||
|
||||
val realmConfiguration = RealmConfiguration.Builder()
|
||||
.compactOnLaunch()
|
||||
.compactOnLaunch(RealmCompactOnLaunch())
|
||||
.directory(directory)
|
||||
.name(REALM_NAME)
|
||||
.apply {
|
||||
@ -93,7 +93,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
|
||||
return
|
||||
}
|
||||
|
||||
listOf(REALM_NAME, "$REALM_NAME.lock", "$REALM_NAME.note", "$REALM_NAME.management").forEach { file ->
|
||||
listOf(REALM_NAME, "${REALM_NAME}.lock", "${REALM_NAME}.note", "${REALM_NAME}.management").forEach { file ->
|
||||
try {
|
||||
File(directory, file).deleteRecursively()
|
||||
} catch (e: Exception) {
|
||||
|
33
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo036.kt
Normal file
33
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo036.kt
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.internal.database.model.LocalRoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
internal class MigrateSessionTo036(realm: DynamicRealm) : RealmMigrator(realm, 36) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("LocalRoomSummaryEntity")
|
||||
.addField(LocalRoomSummaryEntityFields.ROOM_ID, String::class.java)
|
||||
.addPrimaryKey(LocalRoomSummaryEntityFields.ROOM_ID)
|
||||
.setRequired(LocalRoomSummaryEntityFields.ROOM_ID, true)
|
||||
.addField(LocalRoomSummaryEntityFields.CREATE_ROOM_PARAMS_STR, String::class.java)
|
||||
.addRealmObjectField(LocalRoomSummaryEntityFields.ROOM_SUMMARY_ENTITY.`$`, realm.schema.get("RoomSummaryEntity")!!)
|
||||
}
|
||||
}
|
39
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/LocalRoomSummaryEntity.kt
Normal file
39
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/LocalRoomSummaryEntity.kt
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.model
|
||||
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.PrimaryKey
|
||||
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
|
||||
) : RealmObject() {
|
||||
|
||||
var createRoomParams: CreateRoomParams?
|
||||
get() {
|
||||
return CreateRoomParams.fromJson(createRoomParamsStr)
|
||||
}
|
||||
set(value) {
|
||||
createRoomParamsStr = value?.toJSONString()
|
||||
}
|
||||
|
||||
companion object
|
||||
}
|
@ -35,6 +35,7 @@ import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntit
|
||||
ReadReceiptEntity::class,
|
||||
RoomEntity::class,
|
||||
RoomSummaryEntity::class,
|
||||
LocalRoomSummaryEntity::class,
|
||||
RoomTagEntity::class,
|
||||
SyncEntity::class,
|
||||
PendingThreePidEntity::class,
|
||||
|
31
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LocalRoomSummaryEntityQueries.kt
Normal file
31
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/LocalRoomSummaryEntityQueries.kt
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.query
|
||||
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmQuery
|
||||
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
|
||||
}
|
8
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt
8
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/tools/RealmDebugTools.kt
@ -19,16 +19,15 @@ package org.matrix.android.sdk.internal.database.tools
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import org.matrix.android.sdk.BuildConfig
|
||||
import timber.log.Timber
|
||||
|
||||
internal class RealmDebugTools(
|
||||
private val realmConfiguration: RealmConfiguration
|
||||
) {
|
||||
/**
|
||||
* Log info about the DB.
|
||||
* Get info about the DB.
|
||||
*/
|
||||
fun logInfo(baseName: String) {
|
||||
buildString {
|
||||
fun getInfo(baseName: String): String {
|
||||
return buildString {
|
||||
append("\n$baseName Realm located at : ${realmConfiguration.realmDirectory}/${realmConfiguration.realmFileName}")
|
||||
|
||||
if (BuildConfig.LOG_PRIVATE_DATA) {
|
||||
@ -54,7 +53,6 @@ internal class RealmDebugTools(
|
||||
separator()
|
||||
}
|
||||
}
|
||||
.let { Timber.i(it) }
|
||||
}
|
||||
|
||||
private fun StringBuilder.separator() = append("\n==============================================")
|
||||
|
@ -36,9 +36,9 @@ internal class DefaultDebugService @Inject constructor(
|
||||
realmConfigurationGlobal
|
||||
}
|
||||
|
||||
override fun logDbUsageInfo() {
|
||||
RealmDebugTools(realmConfigurationAuth).logInfo("Auth")
|
||||
RealmDebugTools(realmConfigurationGlobal).logInfo("Global")
|
||||
sessionManager.getLastSession()?.logDbUsageInfo()
|
||||
override fun getDbUsageInfo() = buildString {
|
||||
append(RealmDebugTools(realmConfigurationAuth).getInfo("Auth"))
|
||||
append(RealmDebugTools(realmConfigurationGlobal).getInfo("Global"))
|
||||
append(sessionManager.getLastSession()?.getDbUsageInfo())
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ internal object MatrixModule {
|
||||
io = Dispatchers.IO,
|
||||
computation = Dispatchers.Default,
|
||||
main = Dispatchers.Main,
|
||||
crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(),
|
||||
crypto = createBackgroundHandler("Matrix-Crypto_Thread").asCoroutineDispatcher(),
|
||||
dmVerif = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
)
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
package org.matrix.android.sdk.internal.di
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
|
||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageDefaultContent
|
||||
@ -60,6 +62,12 @@ internal object MoshiProvider {
|
||||
.registerSubtype(MessagePollResponseContent::class.java, MessageType.MSGTYPE_POLL_RESPONSE)
|
||||
)
|
||||
.add(SerializeNulls.JSON_ADAPTER_FACTORY)
|
||||
.add(
|
||||
PolymorphicJsonAdapterFactory.of(ThreePid::class.java, "type")
|
||||
.withSubtype(ThreePid.Email::class.java, "email")
|
||||
.withSubtype(ThreePid.Msisdn::class.java, "msisdn")
|
||||
.withDefaultValue(null)
|
||||
)
|
||||
.build()
|
||||
|
||||
fun providesMoshi(): Moshi {
|
||||
|
@ -263,11 +263,11 @@ internal class DefaultSession @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun logDbUsageInfo() {
|
||||
RealmDebugTools(realmConfiguration).logInfo("Session")
|
||||
RealmDebugTools(realmConfigurationCrypto).logInfo("Crypto")
|
||||
RealmDebugTools(realmConfigurationIdentity).logInfo("Identity")
|
||||
RealmDebugTools(realmConfigurationContentScanner).logInfo("ContentScanner")
|
||||
override fun getDbUsageInfo() = buildString {
|
||||
append(RealmDebugTools(realmConfiguration).getInfo("Session"))
|
||||
append(RealmDebugTools(realmConfigurationCrypto).getInfo("Crypto"))
|
||||
append(RealmDebugTools(realmConfigurationIdentity).getInfo("Identity"))
|
||||
append(RealmDebugTools(realmConfigurationContentScanner).getInfo("ContentScanner"))
|
||||
}
|
||||
|
||||
override fun getRealmConfigurations(): List<RealmConfiguration> {
|
||||
|
@ -43,9 +43,13 @@ import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomLocalAli
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomLocalAliasesTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomStateEventsTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomFromLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomStateEventsTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomFromLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.delete.DefaultDeleteLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.delete.DeleteLocalRoomTask
|
||||
@ -213,6 +217,12 @@ internal abstract class RoomModule {
|
||||
@Binds
|
||||
abstract fun bindCreateLocalRoomTask(task: DefaultCreateLocalRoomTask): CreateLocalRoomTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindCreateLocalRoomStateEventsTask(task: DefaultCreateLocalRoomStateEventsTask): CreateLocalRoomStateEventsTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindCreateRoomFromLocalRoomTask(task: DefaultCreateRoomFromLocalRoomTask): CreateRoomFromLocalRoomTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindDeleteLocalRoomTask(task: DefaultDeleteLocalRoomTask): DeleteLocalRoomTask
|
||||
|
||||
|
299
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomStateEventsTask.kt
Normal file
299
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateLocalRoomStateEventsTask.kt
Normal file
@ -0,0 +1,299 @@
|
||||
/*
|
||||
* 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.session.room.create
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
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.toContent
|
||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||
import org.matrix.android.sdk.api.session.room.model.banOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.inviteOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.kickOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.redactOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.user.UserService
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomStateEventsTask.Params
|
||||
import org.matrix.android.sdk.internal.session.room.membership.threepid.toThreePid
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Generate a list of local state events from the given [CreateRoomBody].
|
||||
* The states events are generated according to the given configuration and following the matrix specification.
|
||||
* This list reflects as much as possible a list of state events related to a real room configured and got from the server.
|
||||
*
|
||||
* Ref: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3createroom
|
||||
*/
|
||||
internal interface CreateLocalRoomStateEventsTask : Task<Params, List<Event>> {
|
||||
data class Params(val createRoomBody: CreateRoomBody)
|
||||
}
|
||||
|
||||
internal class DefaultCreateLocalRoomStateEventsTask @Inject constructor(
|
||||
@UserId private val myUserId: String,
|
||||
private val userService: UserService,
|
||||
private val clock: Clock,
|
||||
) : CreateLocalRoomStateEventsTask {
|
||||
|
||||
private lateinit var createRoomBody: CreateRoomBody
|
||||
|
||||
override suspend fun execute(params: Params): List<Event> {
|
||||
createRoomBody = params.createRoomBody
|
||||
|
||||
// Build the list of the state events following the priorities from the matrix specification
|
||||
// Changing the order of the events might break the correct display of the room on the client side
|
||||
return buildList {
|
||||
createRoomCreateEvent()
|
||||
createRoomMemberEvents(listOf(myUserId))
|
||||
createRoomPowerLevelsEvent()
|
||||
createRoomAliasEvent()
|
||||
createRoomPresetEvents()
|
||||
createRoomInitialStateEvents()
|
||||
createRoomNameAndTopicStateEvents()
|
||||
createRoomMemberEvents(createRoomBody.invitedUserIds.orEmpty())
|
||||
createRoomThreePidEvents()
|
||||
createRoomDefaultEvents()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the create state event related to this room.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomCreateEvent() {
|
||||
val roomCreateEvent = createLocalStateEvent(
|
||||
type = EventType.STATE_ROOM_CREATE,
|
||||
content = RoomCreateContent(
|
||||
creator = myUserId,
|
||||
roomVersion = createRoomBody.roomVersion,
|
||||
type = (createRoomBody.creationContent as? Map<*, *>)?.get(CreateRoomParams.CREATION_CONTENT_KEY_ROOM_TYPE) as? String
|
||||
|
||||
).toContent(),
|
||||
)
|
||||
add(roomCreateEvent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the create state event related to the power levels using the given overridden values or the default values according to the specification.
|
||||
* Ref: https://spec.matrix.org/latest/client-server-api/#mroompower_levels
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomPowerLevelsEvent() {
|
||||
val powerLevelsContent = createLocalStateEvent(
|
||||
type = EventType.STATE_ROOM_POWER_LEVELS,
|
||||
content = (createRoomBody.powerLevelContentOverride ?: PowerLevelsContent()).let {
|
||||
it.copy(
|
||||
ban = it.banOrDefault(),
|
||||
eventsDefault = it.eventsDefaultOrDefault(),
|
||||
invite = it.inviteOrDefault(),
|
||||
kick = it.kickOrDefault(),
|
||||
redact = it.redactOrDefault(),
|
||||
stateDefault = it.stateDefaultOrDefault(),
|
||||
usersDefault = it.usersDefaultOrDefault(),
|
||||
)
|
||||
}.toContent(),
|
||||
)
|
||||
add(powerLevelsContent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local room member state events related to the given user ids, if any.
|
||||
*/
|
||||
private suspend fun MutableList<Event>.createRoomMemberEvents(userIds: List<String>) {
|
||||
val memberEvents = userIds
|
||||
.mapNotNull { tryOrNull { userService.resolveUser(it) } }
|
||||
.map { user ->
|
||||
createLocalStateEvent(
|
||||
type = EventType.STATE_ROOM_MEMBER,
|
||||
content = RoomMemberContent(
|
||||
isDirect = createRoomBody.isDirect.takeUnless { user.userId == myUserId }.orFalse(),
|
||||
membership = if (user.userId == myUserId) Membership.JOIN else Membership.INVITE,
|
||||
displayName = user.displayName,
|
||||
avatarUrl = user.avatarUrl
|
||||
).toContent(),
|
||||
stateKey = user.userId
|
||||
)
|
||||
}
|
||||
addAll(memberEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given third party invites, if any.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomThreePidEvents() {
|
||||
createRoomBody.invite3pids.orEmpty().forEach { body ->
|
||||
val localThirdPartyInviteEvent = createLocalStateEvent(
|
||||
type = EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
content = LocalRoomThirdPartyInviteContent(
|
||||
isDirect = createRoomBody.isDirect.orFalse(),
|
||||
membership = Membership.INVITE,
|
||||
displayName = body.address,
|
||||
thirdPartyInvite = body.toThreePid()
|
||||
).toContent(),
|
||||
)
|
||||
val thirdPartyInviteEvent = createLocalStateEvent(
|
||||
type = EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
content = RoomThirdPartyInviteContent(
|
||||
displayName = body.address,
|
||||
keyValidityUrl = null,
|
||||
publicKey = null,
|
||||
publicKeys = null
|
||||
).toContent(),
|
||||
)
|
||||
add(localThirdPartyInviteEvent)
|
||||
add(thirdPartyInviteEvent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state event related to the given alias, if any.
|
||||
*/
|
||||
fun MutableList<Event>.createRoomAliasEvent() {
|
||||
if (createRoomBody.roomAliasName != null) {
|
||||
val canonicalAliasContent = createLocalStateEvent(
|
||||
type = EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||
content = RoomCanonicalAliasContent(
|
||||
canonicalAlias = "${createRoomBody.roomAliasName}:${myUserId.getServerName()}"
|
||||
).toContent(),
|
||||
)
|
||||
add(canonicalAliasContent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given [CreateRoomPreset].
|
||||
* Ref: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3createroom
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomPresetEvents() {
|
||||
val preset = createRoomBody.preset ?: return
|
||||
|
||||
var joinRules: RoomJoinRules? = null
|
||||
var historyVisibility: RoomHistoryVisibility? = null
|
||||
var guestAccess: GuestAccess? = null
|
||||
when (preset) {
|
||||
CreateRoomPreset.PRESET_PRIVATE_CHAT,
|
||||
CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT -> {
|
||||
joinRules = RoomJoinRules.INVITE
|
||||
historyVisibility = RoomHistoryVisibility.SHARED
|
||||
guestAccess = GuestAccess.CanJoin
|
||||
}
|
||||
CreateRoomPreset.PRESET_PUBLIC_CHAT -> {
|
||||
joinRules = RoomJoinRules.PUBLIC
|
||||
historyVisibility = RoomHistoryVisibility.SHARED
|
||||
guestAccess = GuestAccess.Forbidden
|
||||
}
|
||||
}
|
||||
|
||||
add(createLocalStateEvent(EventType.STATE_ROOM_JOIN_RULES, RoomJoinRulesContent(joinRules.value).toContent()))
|
||||
add(createLocalStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY, RoomHistoryVisibilityContent(historyVisibility.value).toContent()))
|
||||
add(createLocalStateEvent(EventType.STATE_ROOM_GUEST_ACCESS, RoomGuestAccessContent(guestAccess.value).toContent()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given initial states, if any.
|
||||
* The given initial state events override the potential existing ones of the same type.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomInitialStateEvents() {
|
||||
val initialStates = createRoomBody.initialStates ?: return
|
||||
|
||||
val initialStateEvents = initialStates.map { createLocalStateEvent(it.type, it.content, it.stateKey) }
|
||||
// Erase existing events of the same type
|
||||
removeAll { event -> event.type in initialStateEvents.map { it.type } }
|
||||
// Add the initial state events to the list
|
||||
addAll(initialStateEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local events related to the given room name and topic, if any.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomNameAndTopicStateEvents() {
|
||||
if (createRoomBody.name != null) {
|
||||
add(createLocalStateEvent(EventType.STATE_ROOM_NAME, RoomNameContent(createRoomBody.name).toContent()))
|
||||
}
|
||||
if (createRoomBody.topic != null) {
|
||||
add(createLocalStateEvent(EventType.STATE_ROOM_TOPIC, RoomTopicContent(createRoomBody.topic).toContent()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local events which have not been set and are in that case provided by the server with default values.
|
||||
* Default events:
|
||||
* - m.room.history_visibility (https://spec.matrix.org/latest/client-server-api/#server-behaviour-5)
|
||||
* - m.room.guest_access (https://spec.matrix.org/latest/client-server-api/#mroomguest_access)
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomDefaultEvents() {
|
||||
// HistoryVisibility
|
||||
if (none { it.type == EventType.STATE_ROOM_HISTORY_VISIBILITY }) {
|
||||
add(
|
||||
createLocalStateEvent(
|
||||
type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
content = RoomHistoryVisibilityContent(RoomHistoryVisibility.SHARED.value).toContent(),
|
||||
)
|
||||
)
|
||||
}
|
||||
// GuestAccess
|
||||
if (none { it.type == EventType.STATE_ROOM_GUEST_ACCESS }) {
|
||||
add(
|
||||
createLocalStateEvent(
|
||||
type = EventType.STATE_ROOM_GUEST_ACCESS,
|
||||
content = RoomGuestAccessContent(GuestAccess.Forbidden.value).toContent(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a local state event from the given parameters.
|
||||
*
|
||||
* @param type the event type, see [EventType]
|
||||
* @param content the content of the event
|
||||
* @param stateKey the stateKey, if any
|
||||
*
|
||||
* @return a local state event
|
||||
*/
|
||||
private fun createLocalStateEvent(type: String?, content: Content?, stateKey: String? = ""): Event {
|
||||
return Event(
|
||||
type = type,
|
||||
senderId = myUserId,
|
||||
stateKey = stateKey,
|
||||
content = content,
|
||||
originServerTs = clock.epochMillis(),
|
||||
eventId = LocalEcho.createLocalEchoId()
|
||||
)
|
||||
}
|
||||
}
|
@ -21,26 +21,15 @@ import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import io.realm.kotlin.createObject
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
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.toContent
|
||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
|
||||
import org.matrix.android.sdk.api.session.user.UserService
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
|
||||
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
||||
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||
@ -48,6 +37,7 @@ import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||
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.EventInsertType
|
||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||
@ -56,7 +46,6 @@ 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.getOrNull
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.events.getFixedRoomMemberContent
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberEventHandler
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater
|
||||
@ -70,22 +59,22 @@ import javax.inject.Inject
|
||||
internal interface CreateLocalRoomTask : Task<CreateRoomParams, String>
|
||||
|
||||
internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val roomMemberEventHandler: RoomMemberEventHandler,
|
||||
private val roomSummaryUpdater: RoomSummaryUpdater,
|
||||
@SessionDatabase private val realmConfiguration: RealmConfiguration,
|
||||
private val createRoomBodyBuilder: CreateRoomBodyBuilder,
|
||||
private val userService: UserService,
|
||||
private val cryptoService: DefaultCryptoService,
|
||||
private val clock: Clock,
|
||||
private val createLocalRoomStateEventsTask: CreateLocalRoomStateEventsTask,
|
||||
) : CreateLocalRoomTask {
|
||||
|
||||
override suspend fun execute(params: CreateRoomParams): String {
|
||||
val createRoomBody = createRoomBodyBuilder.build(params.withDefault())
|
||||
val createRoomBody = createRoomBodyBuilder.build(params)
|
||||
val roomId = RoomLocalEcho.createLocalEchoId()
|
||||
monarchy.awaitTransaction { realm ->
|
||||
createLocalRoomEntity(realm, roomId, createRoomBody)
|
||||
createLocalRoomSummaryEntity(realm, roomId, createRoomBody)
|
||||
createLocalRoomSummaryEntity(realm, roomId, params, createRoomBody)
|
||||
}
|
||||
|
||||
// Wait for room to be created in DB
|
||||
@ -114,14 +103,29 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLocalRoomSummaryEntity(realm: Realm, roomId: String, createRoomBody: CreateRoomBody) {
|
||||
val otherUserId = createRoomBody.getDirectUserId()
|
||||
if (otherUserId != null) {
|
||||
RoomSummaryEntity.getOrCreate(realm, roomId).apply {
|
||||
private fun createLocalRoomSummaryEntity(realm: Realm, roomId: String, createRoomParams: CreateRoomParams, createRoomBody: CreateRoomBody) {
|
||||
// Create the room summary entity
|
||||
val roomSummaryEntity = realm.createObject<RoomSummaryEntity>(roomId).apply {
|
||||
val otherUserId = createRoomBody.getDirectUserId()
|
||||
if (otherUserId != null) {
|
||||
isDirect = true
|
||||
directUserId = otherUserId
|
||||
}
|
||||
}
|
||||
|
||||
// Update the createRoomParams from the potential feature preset before saving
|
||||
createRoomParams.featurePreset?.let { featurePreset ->
|
||||
featurePreset.updateRoomParams(createRoomParams)
|
||||
createRoomParams.initialStates.addAll(featurePreset.setupInitialStates().orEmpty())
|
||||
}
|
||||
|
||||
// Create a LocalRoomSummaryEntity decorated by the related RoomSummaryEntity and the updated CreateRoomParams
|
||||
realm.createObject<LocalRoomSummaryEntity>(roomId).also {
|
||||
it.roomSummaryEntity = roomSummaryEntity
|
||||
it.createRoomParams = createRoomParams
|
||||
}
|
||||
|
||||
// Update the RoomSummaryEntity by simulating a fake sync response
|
||||
roomSummaryUpdater.update(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
@ -150,7 +154,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
isLastForward = true
|
||||
}
|
||||
|
||||
val eventList = createLocalRoomEvents(createRoomBody)
|
||||
val eventList = createLocalRoomStateEventsTask.execute(CreateLocalRoomStateEventsTask.Params(createRoomBody))
|
||||
val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
|
||||
|
||||
for (event in eventList) {
|
||||
@ -169,6 +173,9 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
roomMemberContentsByUser[event.stateKey] = event.getFixedRoomMemberContent()
|
||||
roomMemberEventHandler.handle(realm, roomId, event, false)
|
||||
}
|
||||
|
||||
// Give info to crypto module
|
||||
cryptoService.onStateEvent(roomId, event)
|
||||
}
|
||||
|
||||
roomMemberContentsByUser.getOrPut(event.senderId) {
|
||||
@ -187,81 +194,4 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
|
||||
return chunkEntity
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the list of the events related to the room creation params.
|
||||
*
|
||||
* @param createRoomBody the room creation params
|
||||
*
|
||||
* @return the list of events
|
||||
*/
|
||||
private suspend fun createLocalRoomEvents(createRoomBody: CreateRoomBody): List<Event> {
|
||||
val myUser = userService.getUser(userId) ?: User(userId)
|
||||
val invitedUsers = createRoomBody.invitedUserIds.orEmpty()
|
||||
.mapNotNull { tryOrNull { userService.resolveUser(it) } }
|
||||
|
||||
val createRoomEvent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_CREATE,
|
||||
content = RoomCreateContent(
|
||||
creator = userId
|
||||
).toContent()
|
||||
)
|
||||
val myRoomMemberEvent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_MEMBER,
|
||||
content = RoomMemberContent(
|
||||
membership = Membership.JOIN,
|
||||
displayName = myUser.displayName,
|
||||
avatarUrl = myUser.avatarUrl
|
||||
).toContent(),
|
||||
stateKey = userId
|
||||
)
|
||||
val roomMemberEvents = invitedUsers.map {
|
||||
createLocalEvent(
|
||||
type = EventType.STATE_ROOM_MEMBER,
|
||||
content = RoomMemberContent(
|
||||
isDirect = createRoomBody.isDirect.orFalse(),
|
||||
membership = Membership.INVITE,
|
||||
displayName = it.displayName,
|
||||
avatarUrl = it.avatarUrl
|
||||
).toContent(),
|
||||
stateKey = it.userId
|
||||
)
|
||||
}
|
||||
|
||||
return buildList {
|
||||
add(createRoomEvent)
|
||||
add(myRoomMemberEvent)
|
||||
addAll(createRoomBody.initialStates.orEmpty().map { createLocalEvent(it.type, it.content, it.stateKey) })
|
||||
addAll(roomMemberEvents)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a local event from the given parameters.
|
||||
*
|
||||
* @param type the event type, see [EventType]
|
||||
* @param content the content of the Event
|
||||
* @param stateKey the stateKey, if any
|
||||
*
|
||||
* @return a fake event
|
||||
*/
|
||||
private fun createLocalEvent(type: String?, content: Content?, stateKey: String? = ""): Event {
|
||||
return Event(
|
||||
type = type,
|
||||
senderId = userId,
|
||||
stateKey = stateKey,
|
||||
content = content,
|
||||
originServerTs = clock.epochMillis(),
|
||||
eventId = LocalEcho.createLocalEchoId()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup default values to the CreateRoomParams as the room is created locally (the default values will not be defined by the server).
|
||||
*/
|
||||
private fun CreateRoomParams.withDefault() = this.apply {
|
||||
if (visibility == null) visibility = RoomDirectoryVisibility.PRIVATE
|
||||
if (historyVisibility == null) historyVisibility = RoomHistoryVisibility.SHARED
|
||||
if (guestAccess == null) guestAccess = GuestAccess.Forbidden
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.session.room.membership.threepid.ThreePidInviteBody
|
||||
|
||||
/**
|
||||
@ -119,7 +120,13 @@ internal data class CreateRoomBody(
|
||||
*/
|
||||
@Json(name = "room_version")
|
||||
val roomVersion: String?
|
||||
)
|
||||
) {
|
||||
companion object {
|
||||
fun fromJson(json: String?): CreateRoomBody? {
|
||||
return json?.let { MoshiProvider.providesMoshi().adapter(CreateRoomBody::class.java).fromJson(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the created room can be a direct chat one.
|
||||
|
149
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt
Normal file
149
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomFromLocalRoomTask.kt
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.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.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.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.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
|
||||
|
||||
/**
|
||||
* 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,
|
||||
) : 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
|
||||
|
||||
if (replacementRoomId != null) {
|
||||
return 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()
|
||||
}
|
||||
}
|
||||
val roomId = createRoomTask.execute(createRoomParams!!)
|
||||
|
||||
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)
|
||||
}
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
EventEntity.whereRoomId(realm, roomId)
|
||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_HISTORY_VISIBILITY)
|
||||
}
|
||||
if (isEncrypted) {
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
EventEntity.whereRoomId(realm, roomId)
|
||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION)
|
||||
}
|
||||
}
|
||||
} catch (exception: TimeoutCancellationException) {
|
||||
throw CreateRoomFailure.CreatedWithTimeout(roomId)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -54,8 +54,7 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
||||
private val directChatsHelper: DirectChatsHelper,
|
||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||
private val readMarkersTask: SetReadMarkersTask,
|
||||
@SessionDatabase
|
||||
private val realmConfiguration: RealmConfiguration,
|
||||
@SessionDatabase private val realmConfiguration: RealmConfiguration,
|
||||
private val createRoomBodyBuilder: CreateRoomBodyBuilder,
|
||||
private val globalErrorReceiver: GlobalErrorReceiver,
|
||||
private val clock: Clock,
|
||||
@ -71,7 +70,6 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
||||
}
|
||||
|
||||
val createRoomBody = createRoomBodyBuilder.build(params)
|
||||
|
||||
val createRoomResponse = try {
|
||||
executeRequest(globalErrorReceiver) {
|
||||
roomAPI.createRoom(createRoomBody)
|
||||
@ -90,6 +88,7 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
||||
}
|
||||
throw throwable
|
||||
}
|
||||
|
||||
val roomId = createRoomResponse.roomId
|
||||
// Wait for room to come back from the sync (but it can maybe be in the DB if the sync response is received before)
|
||||
try {
|
||||
|
34
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/LocalRoomThirdPartyInviteContent.kt
Normal file
34
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/LocalRoomThirdPartyInviteContent.kt
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.session.room.create
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
|
||||
/**
|
||||
* Class representing the EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE state event content
|
||||
* This class is only used to store the third party invite data of a local room.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class LocalRoomThirdPartyInviteContent(
|
||||
@Json(name = "membership") val membership: Membership,
|
||||
@Json(name = "displayname") val displayName: String? = null,
|
||||
@Json(name = "is_direct") val isDirect: Boolean = false,
|
||||
@Json(name = "third_party_invite") val thirdPartyInvite: ThreePid? = null,
|
||||
)
|
@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
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.RoomEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||
@ -70,6 +71,9 @@ internal class DefaultDeleteLocalRoomTask @Inject constructor(
|
||||
RoomEntity.where(realm, roomId = roomId).findAll()
|
||||
?.also { Timber.i("## DeleteLocalRoomTask - RoomEntity - delete ${it.size} entries") }
|
||||
?.deleteAllFromRealm()
|
||||
LocalRoomSummaryEntity.where(realm, roomId = roomId).findAll()
|
||||
?.also { Timber.i("## DeleteLocalRoomTask - LocalRoomSummaryEntity - delete ${it.size} entries") }
|
||||
?.deleteAllFromRealm()
|
||||
}
|
||||
} else {
|
||||
Timber.i("## DeleteLocalRoomTask - Failed to remove room with id $roomId: not a local room")
|
||||
|
@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.session.room.membership.threepid
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||
import org.matrix.android.sdk.internal.auth.data.ThreePidMedium
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class ThreePidInviteBody(
|
||||
@ -43,3 +45,9 @@ internal data class ThreePidInviteBody(
|
||||
@Json(name = "address")
|
||||
val address: String
|
||||
)
|
||||
|
||||
internal fun ThreePidInviteBody.toThreePid() = when (medium) {
|
||||
ThreePidMedium.EMAIL -> ThreePid.Email(address)
|
||||
ThreePidMedium.MSISDN -> ThreePid.Msisdn(address)
|
||||
else -> null
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
|
||||
@Inject lateinit var timelineSendEventWorkCommon: TimelineSendEventWorkCommon
|
||||
@Inject lateinit var localEchoRepository: LocalEchoRepository
|
||||
|
||||
override fun doOnError(params: Params): Result {
|
||||
override fun doOnError(params: Params, failureMessage: String): Result {
|
||||
params.localEchoIds.forEach { localEchoIds ->
|
||||
localEchoRepository.updateSendState(
|
||||
eventId = localEchoIds.eventId,
|
||||
@ -63,7 +63,7 @@ internal class MultipleEventSendingDispatcherWorker(context: Context, params: Wo
|
||||
)
|
||||
}
|
||||
|
||||
return super.doOnError(params)
|
||||
return super.doOnError(params, failureMessage)
|
||||
}
|
||||
|
||||
override fun injectWith(injector: SessionComponent) {
|
||||
|
@ -55,7 +55,7 @@ internal class EventSenderProcessorThread @Inject constructor(
|
||||
private val queuedTaskFactory: QueuedTaskFactory,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val memento: QueueMemento
|
||||
) : Thread("SENDER_THREAD_SID_${sessionParams.credentials.sessionId()}"), EventSenderProcessor {
|
||||
) : Thread("Matrix-SENDER_THREAD_SID_${sessionParams.credentials.sessionId()}"), EventSenderProcessor {
|
||||
|
||||
private fun markAsManaged(task: QueuedTask) {
|
||||
memento.track(task)
|
||||
|
46
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt
46
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/SendStateTask.kt
@ -16,10 +16,12 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.room.state
|
||||
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomFromLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
@ -35,28 +37,40 @@ internal interface SendStateTask : Task<SendStateTask.Params, String> {
|
||||
|
||||
internal class DefaultSendStateTask @Inject constructor(
|
||||
private val roomAPI: RoomAPI,
|
||||
private val globalErrorReceiver: GlobalErrorReceiver
|
||||
private val globalErrorReceiver: GlobalErrorReceiver,
|
||||
private val createRoomFromLocalRoomTask: CreateRoomFromLocalRoomTask,
|
||||
) : SendStateTask {
|
||||
|
||||
override suspend fun execute(params: SendStateTask.Params): String {
|
||||
return executeRequest(globalErrorReceiver) {
|
||||
val response = if (params.stateKey.isEmpty()) {
|
||||
roomAPI.sendStateEvent(
|
||||
roomId = params.roomId,
|
||||
stateEventType = params.eventType,
|
||||
params = params.body
|
||||
)
|
||||
if (RoomLocalEcho.isLocalEchoId(params.roomId)) {
|
||||
// Room is local, so create a real one and send the event to this new room
|
||||
createRoomAndSendEvent(params)
|
||||
} else {
|
||||
roomAPI.sendStateEvent(
|
||||
roomId = params.roomId,
|
||||
stateEventType = params.eventType,
|
||||
stateKey = params.stateKey,
|
||||
params = params.body
|
||||
)
|
||||
}
|
||||
response.eventId.also {
|
||||
Timber.d("State event: $it just sent in room ${params.roomId}")
|
||||
val response = if (params.stateKey.isEmpty()) {
|
||||
roomAPI.sendStateEvent(
|
||||
roomId = params.roomId,
|
||||
stateEventType = params.eventType,
|
||||
params = params.body
|
||||
)
|
||||
} else {
|
||||
roomAPI.sendStateEvent(
|
||||
roomId = params.roomId,
|
||||
stateEventType = params.eventType,
|
||||
stateKey = params.stateKey,
|
||||
params = params.body
|
||||
)
|
||||
}
|
||||
response.eventId.also {
|
||||
Timber.d("State event: $it just sent in room ${params.roomId}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun createRoomAndSendEvent(params: SendStateTask.Params): String {
|
||||
val roomId = createRoomFromLocalRoomTask.execute(CreateRoomFromLocalRoomTask.Params(params.roomId))
|
||||
Timber.d("State event: convert local room (${params.roomId}) to existing room ($roomId) before sending the event.")
|
||||
return execute(params.copy(roomId = roomId))
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ internal class DefaultTimeline(
|
||||
) : Timeline {
|
||||
|
||||
companion object {
|
||||
val BACKGROUND_HANDLER = createBackgroundHandler("DefaultTimeline_Thread")
|
||||
val BACKGROUND_HANDLER = createBackgroundHandler("Matrix-DefaultTimeline_Thread")
|
||||
}
|
||||
|
||||
override val timelineID = UUID.randomUUID().toString()
|
||||
|
2
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt
2
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt
@ -73,6 +73,8 @@ internal class DefaultSyncService @Inject constructor(
|
||||
|
||||
override fun getSyncState() = getSyncThread().currentState()
|
||||
|
||||
override fun isSyncThreadAlive() = getSyncThread().isAlive
|
||||
|
||||
override fun getSyncRequestStateFlow() = syncRequestStateTracker.syncRequestState
|
||||
|
||||
override fun hasAlreadySynced(): Boolean {
|
||||
|
@ -62,7 +62,7 @@ internal class SyncThread @Inject constructor(
|
||||
private val backgroundDetectionObserver: BackgroundDetectionObserver,
|
||||
private val activeCallHandler: ActiveCallHandler,
|
||||
private val lightweightSettingsStorage: DefaultLightweightSettingsStorage
|
||||
) : Thread("SyncThread"), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
|
||||
) : Thread("Matrix-SyncThread"), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
|
||||
|
||||
private var state: SyncState = SyncState.Idle
|
||||
private var liveState = MutableLiveData(state)
|
||||
|
@ -30,6 +30,7 @@ import org.matrix.android.sdk.internal.session.sync.SyncTask
|
||||
import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker
|
||||
import org.matrix.android.sdk.internal.worker.SessionWorkerParams
|
||||
import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
|
||||
import org.matrix.android.sdk.internal.worker.startChain
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
@ -136,6 +137,7 @@ internal class SyncWorker(context: Context, workerParameters: WorkerParameters,
|
||||
.setConstraints(WorkManagerProvider.workConstraints)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS)
|
||||
.setInputData(data)
|
||||
.startChain(true)
|
||||
.build()
|
||||
workManagerProvider.workManager
|
||||
.enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user