mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 09:25:49 +03:00
Merge branch 'develop' into feature/fga/voip_v1_start
This commit is contained in:
commit
efec711ced
458 changed files with 11172 additions and 4630 deletions
|
@ -31,6 +31,7 @@
|
|||
<w>ssss</w>
|
||||
<w>sygnal</w>
|
||||
<w>threepid</w>
|
||||
<w>unpublish</w>
|
||||
<w>unwedging</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
|
19
AUTHORS.md
19
AUTHORS.md
|
@ -4,7 +4,7 @@ A full developer contributors list can be found [here](https://github.com/vector
|
|||
|
||||
Even if we try to be able to work on all the functionalities, we have more knowledge about what we have developed ourselves.
|
||||
|
||||
## Benoit: Android team leader
|
||||
## [Benoit](https://github.com/bmarty): Android team leader
|
||||
|
||||
[@benoit.marty:matrix.org](https://matrix.to/#/@benoit.marty:matrix.org)
|
||||
- Android team leader and project leader, Android developer, GitHub community manager.
|
||||
|
@ -12,7 +12,7 @@ Even if we try to be able to work on all the functionalities, we have more knowl
|
|||
- Reviewing and polishing developed features, code quality manager, PRs reviewer, GitHub community manager.
|
||||
- Release manager on the Play Store
|
||||
|
||||
## François: Software architect
|
||||
## [Ganfra](https://github.com/ganfra) (aka François): Software architect
|
||||
|
||||
[@ganfra:matrix.org](https://matrix.to/#/@ganfra:matrix.org)
|
||||
- Software architect, Android developer
|
||||
|
@ -20,12 +20,17 @@ Even if we try to be able to work on all the functionalities, we have more knowl
|
|||
- Work mainly on the global architecture of the project.
|
||||
- Specialist of the timeline, and lots of other features.
|
||||
|
||||
## Valere: Product manager, Android developer
|
||||
## [Valere](https://github.com/BillCarsonFr): Product manager, Android developer
|
||||
|
||||
[@valere35:matrix.org](https://matrix.to/#/@valere35:matrix.org)
|
||||
- Product manager, Android developer
|
||||
- Specialist on the crypto implementation.
|
||||
|
||||
## [Onuray](https://github.com/onurays): Android developer
|
||||
|
||||
[@onurays:matrix.org](https://matrix.to/#/@onurays:matrix.org)
|
||||
- Android developer
|
||||
|
||||
# Other contributors
|
||||
|
||||
First of all, we thank all contributors who use Element and report problems on this GitHub project or via the integrated rageshake function.
|
||||
|
@ -34,7 +39,7 @@ We do not forget all translators, for their work of translating Element into man
|
|||
|
||||
Feel free to add your name below, when you contribute to the project!
|
||||
|
||||
Name | Matrix ID | GitHub
|
||||
--------|---------------------|--------------------------------------
|
||||
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
||||
|
||||
Name | Matrix ID | GitHub
|
||||
----------|-----------------------------|--------------------------------------
|
||||
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
||||
TR_SLimey | @tr_slimey:an-atom-in.space | [TR-SLimey](https://github.com/TR-SLimey)
|
||||
|
|
63
CHANGES.md
63
CHANGES.md
|
@ -1,25 +1,73 @@
|
|||
Changes in Element 1.0.11 (2020-XX-XX)
|
||||
Changes in Element 1.0.12 (2020-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
-
|
||||
- Add room aliases management, and room directory visibility management in a dedicated screen (#1579, #2428)
|
||||
- Room setting: update join rules and guest access (#2442)
|
||||
|
||||
Improvements 🙌:
|
||||
- Open an existing DM instead of creating a new one (#2319)
|
||||
- Add Setting Item to Change PIN (#2462)
|
||||
- Improve room history visibility setting UX (#1579)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix issue when updating the avatar of a room (new avatar vanishing)
|
||||
- Discard change dialog displayed by mistake when avatar has been updated
|
||||
- Double bottomsheet effect after verify with passphrase
|
||||
- EditText cursor jumps to the start while typing fast (#2469)
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- AccountService now exposes suspendable function instead of using MatrixCallback (#2354). Note: We will incrementally migrate all the SDK API in a near future.
|
||||
-
|
||||
|
||||
Build 🧱:
|
||||
- Upgrade some dependencies and Kotlin version
|
||||
- Use fragment-ktx and preference-ktx dependencies (fix lint issue KtxExtensionAvailable)
|
||||
|
||||
Test:
|
||||
-
|
||||
|
||||
Other changes:
|
||||
- Remove "Status.im" theme #2424
|
||||
|
||||
Changes in Element 1.0.11 (2020-11-27)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Create DMs with users by scanning their QR code (#2025)
|
||||
- Add Invite friends quick invite actions (#2348)
|
||||
- Add friend by scanning QR code, show your code to friends (#2025)
|
||||
|
||||
Improvements 🙌:
|
||||
- New room creation tile with quick action (#2346)
|
||||
- Open an existing DM instead of creating a new one (#2319)
|
||||
- Use RoomMember instead of User in the context of a Room.
|
||||
- Ask for explicit user consent to send their contact details to the identity server (#2375)
|
||||
- Handle events of type "m.room.server_acl" (#890)
|
||||
- Room creation form: add advanced section to disable federation (#1314)
|
||||
- Move "Enable Encryption" from room setting screen to room profile screen (#2394)
|
||||
- Home empty screens quick design update (#2347)
|
||||
- Improve Invite user screen (seamless search for matrix ID)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix crash on AttachmentViewer (#2365)
|
||||
- Exclude yourself when decorating rooms which are direct or don't have more than 2 users (#2370)
|
||||
- F-Droid version: ensure timeout of sync request can be more than 60 seconds (#2169)
|
||||
- Fix issue when restoring draft after sharing (#2287)
|
||||
- Fix issue when updating the avatar of a room (new avatar vanishing)
|
||||
- Discard change dialog displayed by mistake when avatar has been updated
|
||||
- Try to fix cropped image in timeline (#2126)
|
||||
- Registration: annoying error message scares every new user when they add an email (#2391)
|
||||
- Fix jitsi integration for those with non-vanilla dialler frameworks
|
||||
- Update profile has no effect if user is in zero rooms
|
||||
- Fix issues with matrix.to deep linking (#2349)
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- AccountService now exposes suspendable function instead of using MatrixCallback (#2354).
|
||||
Note: We will incrementally migrate all the SDK API in a near future (#2449)
|
||||
|
||||
Test:
|
||||
- Add `allScreensTest` to cover all screens of the app
|
||||
|
||||
Other changes:
|
||||
- Upgrade Realm dependency to 10.0.0
|
||||
|
||||
|
@ -1033,5 +1081,8 @@ SDK API changes ⚠️:
|
|||
Build 🧱:
|
||||
-
|
||||
|
||||
Test:
|
||||
-
|
||||
|
||||
Other changes:
|
||||
-
|
||||
|
|
|
@ -66,7 +66,6 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
buildscript {
|
||||
// Ref: https://kotlinlang.org/releases.html
|
||||
ext.kotlin_version = '1.4.10'
|
||||
ext.kotlin_coroutines_version = "1.3.9"
|
||||
ext.kotlin_version = '1.4.20'
|
||||
ext.kotlin_coroutines_version = "1.4.1"
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
@ -12,7 +12,7 @@ buildscript {
|
|||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||
classpath 'com.google.gms:google-services:4.3.4'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
||||
|
|
1
fastlane/metadata/android/ca/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/ca/changelogs/40100100.txt
Normal file
|
@ -0,0 +1 @@
|
|||
// TODO
|
30
fastlane/metadata/android/ca/full_description.txt
Normal file
30
fastlane/metadata/android/ca/full_description.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
Element és un nou tipus d'aplicació de missatgeria i col·laboració que:
|
||||
|
||||
1. Et dóna a tu el control per preservar la teva privadesa
|
||||
2. Et permet comunicar-te amb qualsevol persona de la xarxa Matrix i, fins i tot més enllà gràcies a integracions amb altres aplicacions com Slack
|
||||
3. Et protegeix de la publicitat, l'obtenció no desitjada de dades i dels navegadors amb accés controlat
|
||||
4. T'assegura a tu mitjançant l'encriptació d'extrem a extrem i amb signatures creuades per verificar els altres
|
||||
|
||||
Element és completament diferent a les altres aplicacions de missatgeria i col·laboració ja que és descentralitzat i de codi obert.
|
||||
|
||||
Element et deixa triar l'allotjament perquè disposis de privadesa, propietat i control de les teves dades i converses. Et dóna accés a una xarxa oberta perquè no et quedis únicament parlant amb els usuaris d'Element.
|
||||
|
||||
Element pot fer tot això ja que opera sobre Matrix - l'estàndard per a les comunicacions obertes i descentralitzades.
|
||||
|
||||
Element et dóna el control perquè et deixa escollir qui vols que allotgi les teves converses. Des de l'aplicació d'Element, pots triar l'allotjament de diferents maneres:
|
||||
|
||||
1. Crea un compte gratuït al servidor públic de matrix.org allotjat pels desenvolupadors de Matrix o tria'n un entre els milers de servidors públics creats per voluntaris
|
||||
2. Allotja tu mateix el teu compte en el teu propi servidor
|
||||
3. Registra el compte en un servidor personalitzat subscrivint-te a la plataforma d'Element Matrix Services (EMS)
|
||||
|
||||
<b>Per què escollir Element?</b>
|
||||
|
||||
<b>PROPIETAT DE LES TEVES DADES</b>: Tu decideixes a on desar les teves dades i missatges. Tu les controles i n'ets el propietari, no una mega-corporació que s'aprofita de les teves dades o les cedeix a tercers.
|
||||
|
||||
<b>MISSATGERIA I COL·LABORACIÓ OBERTA</b>: Pots parlar amb qualsevol que estigui a la xarxa Matrix, ja sigui amb Element o amb qualsevol altre aplicació Matrix, fins i tot encara que utilitzin sistemes de missatgeria diferents com Slack, IRC o XMPP.
|
||||
|
||||
<b>SUPER-SEGUR</b>: Encriptació d'extrem a extrem real (només qui està conversant pot desxifrar els missatges), i amb signatures creuades per a verificar els dispositius dels participants en les converses.
|
||||
|
||||
<b>COMUNICACIÓ COMPLETA</b>: Missatgeria, veu i video-trucades, compartició de fitxers, compartició de pantalla i un munt d'integracions, bots i ginys. Crea sales, comunitats, mantén-te en contacte i enllesteix el que et proposes.
|
||||
|
||||
<b>A TOT ARREU</b>: Mantingues el contacte des de qualsevol lloc on siguis, amb un historial de missatges totalment sincronitzat entre tots els teus dispositius i també a la web: https://app.element.io.
|
1
fastlane/metadata/android/ca/short_description.txt
Normal file
1
fastlane/metadata/android/ca/short_description.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Xat i VoIP segurs i descentralitzats. Protegeix les teves dades de tercers.
|
1
fastlane/metadata/android/ca/title.txt
Normal file
1
fastlane/metadata/android/ca/title.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Element (anteriorment Riot.im)
|
1
fastlane/metadata/android/de/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/de/changelogs/40100100.txt
Normal file
|
@ -0,0 +1 @@
|
|||
// TODO
|
2
fastlane/metadata/android/en-US/changelogs/40100110.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40100110.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
This new version mainly contains user interface and user experience improvements. Now you can invite friends, and create DM very fast by scanning QR codes.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
1
fastlane/metadata/android/es/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/es/changelogs/40100100.txt
Normal file
|
@ -0,0 +1 @@
|
|||
// TODO
|
|
@ -1,30 +1,30 @@
|
|||
Element es un nuevo tipo de aplicación de mensajería y colaboración que:
|
||||
|
||||
1. Le da el control para preservar su privacidad
|
||||
2. Le permite comunicarse con cualquier persona en la red Matrix e incluso más allá al integrarse con aplicaciones como Slack.
|
||||
3. Te protege de la publicidad, la minería de datos y los jardines vallados.
|
||||
4. Lo protege a través del cifrado de un extremo a otro, con firma cruzada para verificar a otros
|
||||
1. Te da el control para preservar su privacidad
|
||||
2. Te permite comunicarse con cualquier persona en la red Matrix e incluso más allá al integrarse con aplicaciones como Slack
|
||||
3. Te protege de la publicidad, la minería de datos y los jardines vallados
|
||||
4. Te protege a través de encriptación de Extremo-a-Extremo, con firma cruzada para verificar a otros
|
||||
|
||||
Element es completamente diferente de otras aplicaciones de mensajería y colaboración porque es descentralizado y de código abierto.
|
||||
|
||||
Element le permite autohospedarse, o elegir un host, para que tenga privacidad, propiedad y control de sus datos y conversaciones. Te da acceso a una red abierta; para que no se quede atascado hablando solo con otros usuarios de Element. Y es muy seguro.
|
||||
Element te permite tener su propio servidor privado, o elegir uno público, para que tenga privacidad, posesión, y control de sus datos y conversaciones. Te da acceso a una red abierta; para que no se quede atrapado hablando solo con otros usuarios de Element. Y es muy seguro.
|
||||
|
||||
Element puede hacer todo esto porque opera en Matrix, el estándar para la comunicación abierta y descentralizada.
|
||||
|
||||
Element te da el control permitiéndote elegir quién aloja tus conversaciones. Desde la aplicación Element, puede elegir hospedar de diferentes maneras:
|
||||
Element te da el control permitiéndote elegir quién aloja tus conversaciones. Desde la aplicación Element, puedes elegir hospedar de diferentes maneras:
|
||||
|
||||
1. Obtenga una cuenta gratuita en el servidor público de matrix.org alojado por los desarrolladores de Matrix, o elija entre miles de servidores públicos alojados por voluntarios
|
||||
2. Autohospede su cuenta ejecutando un servidor en su propio hardware
|
||||
3. Regístrese para obtener una cuenta en un servidor personalizado simplemente suscribiéndose a la plataforma de alojamiento de Element Matrix Services
|
||||
1. Obtén una cuenta gratuita en el servidor público de matrix.org alojado por los desarrolladores de Matrix, o elije entre miles de servidores públicos alojados por voluntarios
|
||||
2. Autohospeda tu cuenta con un servidor en tu propio hardware
|
||||
3. Regístrate para obtener una cuenta en un servidor personalizado simplemente suscribiéndote a la plataforma de alojamiento de Element Matrix Services
|
||||
|
||||
<b>¿Por qué elegir Element?</b>
|
||||
|
||||
<b>POSEE SUS DATOS</b>: Tú decides dónde guardar tus datos y mensajes. Usted es el propietario y lo controla, no algún MEGACORP que extraiga sus datos o dé acceso a terceros.
|
||||
<b>TOMA POSESIÓN DE TUS DATOS</b>: Tú decides dónde guardar tus datos y mensajes. Tú eres el propietario y quien lo controla, no alguna MEGACORP que extrae tu datos o da acceso a terceros.
|
||||
|
||||
<b>MENSAJERÍA ABIERTA Y COLABORACIÓN</b>: Puede chatear con cualquier otra persona en la red de Matrix, ya sea que estén usando Element u otra aplicación de Matrix, e incluso si están usando un sistema de mensajería diferente como Slack, IRC o XMPP.
|
||||
<b>MENSAJERÍA ABIERTA Y COLABORACIÓN</b>: Puede chatear con cualquier otra persona en la red de Matrix, tanto si usan Element u otra aplicación de Matrix, e incluso si están usando un sistema de mensajería diferente como Slack, IRC o XMPP.
|
||||
|
||||
<b>SUPER SEGURO</b>: Cifrado real de extremo a extremo (solo aquellos en la conversación pueden descifrar mensajes) y firma cruzada para verificar los dispositivos de los participantes de la conversación.
|
||||
<b>SUPER SEGURO</b>: Encriptación de Extremo-a-Extremo real (solo aquellos en la conversación pueden descifrar mensajes) y firma cruzada para verificar los dispositivos de los participantes de la conversación.
|
||||
|
||||
<b>COMUNICACIÓN COMPLETA</b>: Mensajería, llamadas de voz y video, uso compartido de archivos, uso compartido de pantalla y un montón de integraciones, bots y widgets. Construya salas, comunidades, manténgase en contacto y haga las cosas.
|
||||
<b>COMUNICACIÓN COMPLETA</b>: Mensajería, llamadas de voz y video, uso compartido de archivos, uso compartido de pantalla y un montón de integraciones, bots y widgets. Crea salas, comunidades, mantente en contacto y organízate con eficacia.
|
||||
|
||||
<b>EN TODAS PARTES</b>: Manténgase en contacto donde quiera que esté con un historial de mensajes totalmente sincronizado en todos sus dispositivos y en la web en https://app.element.io.
|
||||
<b>EN TODAS PARTES</b>: Mantente en contacto donde quiera que estés con un historial de mensajes totalmente sincronizado en todos sus dispositivos y en la web en https://app.element.io.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Chat y VoIP descentralizados seguros. Mantenga sus datos a salvo de terceros.
|
||||
Chat y VoIP descentralizados y seguros. Mantén tus datos a salvo de terceros.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Element (anteriorment Riot.im)
|
||||
Element (previamente Riot.im)
|
||||
|
|
1
fastlane/metadata/android/fa/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/fa/changelogs/40100100.txt
Normal file
|
@ -0,0 +1 @@
|
|||
// برای انجام
|
1
fastlane/metadata/android/it/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/it/changelogs/40100100.txt
Normal file
|
@ -0,0 +1 @@
|
|||
// DA FARE
|
1
fastlane/metadata/android/nb/short_description.txt
Normal file
1
fastlane/metadata/android/nb/short_description.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Sikker desentralisert chat & VoIP. Beskytt dataene dine fra tredjeparter.
|
1
fastlane/metadata/android/nb/title.txt
Normal file
1
fastlane/metadata/android/nb/title.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Element (tidligere Riot.im)
|
1
fastlane/metadata/android/pt_BR/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/pt_BR/changelogs/40100100.txt
Normal file
|
@ -0,0 +1 @@
|
|||
// A FAZER
|
1
fastlane/metadata/android/sv/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/sv/changelogs/40100100.txt
Normal file
|
@ -0,0 +1 @@
|
|||
// ATT GÖRA
|
|
@ -0,0 +1 @@
|
|||
// 待辦事項
|
30
fastlane/metadata/android/zh_Hant/full_description.txt
Normal file
30
fastlane/metadata/android/zh_Hant/full_description.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
Element 是一種新型態的即時通訊軟體與協作應用程式:
|
||||
|
||||
1. 自己的隱私自己掌控
|
||||
2. 讓您與任何在 Matrix 網路中的人通訊,甚至可與如 Slack 等的應用程式整合
|
||||
3. 保護您免受廣告、資料採礦與圍牆花園的侵害
|
||||
4. 透過端到端加密保護您,並使用交叉簽章來驗證其他人
|
||||
|
||||
Element 是去中心化且開放原始碼的應用程式,因此與其他即時通訊與協作軟體完全不同。
|
||||
|
||||
Element 讓您可以自架(或是自行選擇服務提供者)所以您擁有您資料與對話的隱私、所有權與控制權。它讓您可以存取開放的網路;因此,您不僅可以與其他 Matrix 使用者聊天。而且非常安全。
|
||||
|
||||
Element 能作到這些事情是因為它在 Matrix 上執行,這是一個開放的去中心化通訊的標準。
|
||||
|
||||
Element 讓您選擇您要在哪裡託管您的對話來將控制權還給您。在 Element 應用程式中,您可以選擇其他方式來託管:
|
||||
|
||||
1. 在由 Matrix 開發者架設的 matrix.org 公開伺服器上取得免費的帳號,或是從數千個由志願者所架設的公開伺服器中選擇
|
||||
2. 在您自己的硬體上自行架設伺服器並建立帳號
|
||||
3. 訂閱 Element Matrix 服務託管平台並在自訂伺服氣上註冊帳號
|
||||
|
||||
<b>為何選擇 Element?</b>
|
||||
|
||||
<b>擁有您的資料</b>:您決定您的資料與訊息要放在哪裡。您擁有並控制它,而非某些科技巨頭會挖掘您的資料並將其售予第三方。
|
||||
|
||||
<b>開放的即時通訊與協作</b>:您可以與 Matrix 網路中的任何人聊天,不管他們是使用 Element 或其他 Matrix 應用程式都可以,或甚至是其他的訊息系統,如 Slack、IRC 或 XMPP 也都可以。
|
||||
|
||||
<b>超級安全</b>:即時的端到端加密(僅有參與對話的人可以解密訊息),以及交叉簽章以驗證對話參與者的裝置。
|
||||
|
||||
<b>完整通訊</b>:即時通訊、語音與視訊通話、檔案分享、畫面分享與超多的整合、機器人與小工具。建立聊天室、保持聯繫並完成工作。
|
||||
|
||||
<b>無論您身在何處</b>:無論您身在何處,都可以透過 https://app.element.io 來在所有裝置與網路上保持訊息歷史同步。
|
1
fastlane/metadata/android/zh_Hant/short_description.txt
Normal file
1
fastlane/metadata/android/zh_Hant/short_description.txt
Normal file
|
@ -0,0 +1 @@
|
|||
安全的去中心化聊天與 VoIP。確保您的資料不受第三方的影響。
|
1
fastlane/metadata/android/zh_Hant/title.txt
Normal file
1
fastlane/metadata/android/zh_Hant/title.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Element(曾名為 Riot.im)
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=0080de8491f0918e4f529a6db6820fa0b9e818ee2386117f4394f95feb1d5583
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||
distributionSha256Sum=22449f5231796abd892c98b2a07c9ceebe4688d192cd2d6763f8e3bf8acbedeb
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -36,9 +36,9 @@ android {
|
|||
dependencies {
|
||||
implementation project(":matrix-sdk-android")
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
|
||||
// Paging
|
||||
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
|
||||
|
||||
|
|
|
@ -21,34 +21,36 @@ import org.matrix.android.sdk.api.util.Cancelable
|
|||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
|
||||
fun <T> singleBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Single<T> = Single.create {
|
||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
||||
fun <T> singleBuilder(builder: (MatrixCallback<T>) -> Cancelable): Single<T> = Single.create { emitter ->
|
||||
val callback = object : MatrixCallback<T> {
|
||||
override fun onSuccess(data: T) {
|
||||
it.onSuccess(data)
|
||||
// Add `!!` to fix the warning:
|
||||
// "Type mismatch: type parameter with nullable bounds is used T is used where T was expected. This warning will become an error soon"
|
||||
emitter.onSuccess(data!!)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
it.tryOnError(failure)
|
||||
emitter.tryOnError(failure)
|
||||
}
|
||||
}
|
||||
val cancelable = builder(callback)
|
||||
it.setCancellable {
|
||||
emitter.setCancellable {
|
||||
cancelable.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> completableBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Completable = Completable.create {
|
||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
||||
fun <T> completableBuilder(builder: (MatrixCallback<T>) -> Cancelable): Completable = Completable.create { emitter ->
|
||||
val callback = object : MatrixCallback<T> {
|
||||
override fun onSuccess(data: T) {
|
||||
it.onComplete()
|
||||
emitter.onComplete()
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
it.tryOnError(failure)
|
||||
emitter.tryOnError(failure)
|
||||
}
|
||||
}
|
||||
val cancelable = builder(callback)
|
||||
it.setCancellable {
|
||||
emitter.setCancellable {
|
||||
cancelable.cancel()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ import org.matrix.android.sdk.api.util.toOptional
|
|||
import io.reactivex.Completable
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
|
||||
class RxRoom(private val room: Room) {
|
||||
|
||||
|
@ -127,18 +129,14 @@ class RxRoom(private val room: Room) {
|
|||
room.updateName(name, it)
|
||||
}
|
||||
|
||||
fun addRoomAlias(alias: String): Completable = completableBuilder<Unit> {
|
||||
room.addRoomAlias(alias, it)
|
||||
}
|
||||
|
||||
fun updateCanonicalAlias(alias: String): Completable = completableBuilder<Unit> {
|
||||
room.updateCanonicalAlias(alias, it)
|
||||
}
|
||||
|
||||
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = completableBuilder<Unit> {
|
||||
room.updateHistoryReadability(readability, it)
|
||||
}
|
||||
|
||||
fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?): Completable = completableBuilder<Unit> {
|
||||
room.updateJoinRule(joinRules, guestAccess, it)
|
||||
}
|
||||
|
||||
fun updateAvatar(avatarUri: Uri, fileName: String): Completable = completableBuilder<Unit> {
|
||||
room.updateAvatar(avatarUri, fileName, it)
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.identity.ThreePid
|
|||
import org.matrix.android.sdk.api.session.pushers.Pusher
|
||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
||||
|
@ -92,6 +93,13 @@ class RxSession(private val session: Session) {
|
|||
}
|
||||
}
|
||||
|
||||
fun liveRoomMember(userId: String, roomId: String): Observable<Optional<RoomMemberSummary>> {
|
||||
return session.getRoomMemberLive(userId, roomId).asObservable()
|
||||
.startWithCallable {
|
||||
session.getRoomMember(userId, roomId).toOptional()
|
||||
}
|
||||
}
|
||||
|
||||
fun liveUsers(): Observable<List<User>> {
|
||||
return session.getUsersLive().asObservable()
|
||||
}
|
||||
|
|
|
@ -125,7 +125,6 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
||||
implementation "androidx.core:core-ktx:1.3.2"
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||
|
@ -146,7 +145,7 @@ dependencies {
|
|||
implementation "ru.noties.markwon:core:$markwon_version"
|
||||
|
||||
// Image
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.0'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.1'
|
||||
|
||||
// Database
|
||||
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
|
||||
|
|
|
@ -68,8 +68,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
|||
if (encryptedRoom) {
|
||||
val room = aliceSession.getRoom(roomId)!!
|
||||
|
||||
mTestHelper.doSync<Unit> {
|
||||
room.enableEncryption(callback = it)
|
||||
mTestHelper.runBlockingTest {
|
||||
room.enableEncryption()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,38 +71,27 @@ class SearchMessagesTest : InstrumentedTest {
|
|||
commonTestHelper.await(lock)
|
||||
|
||||
lock = CountDownLatch(1)
|
||||
aliceSession
|
||||
.searchService()
|
||||
.search(
|
||||
searchTerm = "lore",
|
||||
limit = 10,
|
||||
includeProfile = true,
|
||||
afterLimit = 0,
|
||||
beforeLimit = 10,
|
||||
orderByRecent = true,
|
||||
nextBatch = null,
|
||||
roomId = aliceRoomId,
|
||||
callback = object : MatrixCallback<SearchResult> {
|
||||
override fun onSuccess(data: SearchResult) {
|
||||
super.onSuccess(data)
|
||||
assertTrue(data.results?.size == 2)
|
||||
assertTrue(
|
||||
data.results
|
||||
?.all {
|
||||
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
||||
}.orFalse()
|
||||
)
|
||||
lock.countDown()
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
super.onFailure(failure)
|
||||
fail(failure.localizedMessage)
|
||||
lock.countDown()
|
||||
}
|
||||
}
|
||||
)
|
||||
lock.await(TestConstants.timeOutMillis, TimeUnit.MILLISECONDS)
|
||||
val data = commonTestHelper.runBlockingTest {
|
||||
aliceSession
|
||||
.searchService()
|
||||
.search(
|
||||
searchTerm = "lore",
|
||||
limit = 10,
|
||||
includeProfile = true,
|
||||
afterLimit = 0,
|
||||
beforeLimit = 10,
|
||||
orderByRecent = true,
|
||||
nextBatch = null,
|
||||
roomId = aliceRoomId
|
||||
)
|
||||
}
|
||||
assertTrue(data.results?.size == 2)
|
||||
assertTrue(
|
||||
data.results
|
||||
?.all {
|
||||
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
||||
}.orFalse()
|
||||
)
|
||||
|
||||
aliceTimeline.removeAllListeners()
|
||||
cryptoTestData.cleanUp(commonTestHelper)
|
||||
|
|
|
@ -66,9 +66,9 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
|||
}
|
||||
|
||||
private fun logJson(formattedJson: String) {
|
||||
val arr = formattedJson.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (s in arr) {
|
||||
Timber.v(s)
|
||||
}
|
||||
formattedJson
|
||||
.lines()
|
||||
.dropLastWhile { it.isEmpty() }
|
||||
.forEach { Timber.v(it) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ interface LoginWizard {
|
|||
* @param password the password field
|
||||
* @param deviceName the initial device name
|
||||
* @param callback the matrix callback on which you'll receive the result of authentication.
|
||||
* @return return a [Cancelable]
|
||||
* @return a [Cancelable]
|
||||
*/
|
||||
fun login(login: String,
|
||||
password: String,
|
||||
|
|
|
@ -22,3 +22,8 @@ fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
|
|||
else -> "$prefix$this"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a new line and then the provided string
|
||||
*/
|
||||
fun StringBuilder.appendNl(str: String) = append("\n").append(str)
|
||||
|
|
|
@ -15,11 +15,9 @@
|
|||
*/
|
||||
package org.matrix.android.sdk.api.pushrules
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.pushrules.rest.PushRule
|
||||
import org.matrix.android.sdk.api.pushrules.rest.RuleSet
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
interface PushRuleService {
|
||||
/**
|
||||
|
@ -29,13 +27,13 @@ interface PushRuleService {
|
|||
|
||||
fun getPushRules(scope: String = RuleScope.GLOBAL): RuleSet
|
||||
|
||||
fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean)
|
||||
|
||||
fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun addPushRule(kind: RuleKind, pushRule: PushRule)
|
||||
|
||||
fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule)
|
||||
|
||||
fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun removePushRule(kind: RuleKind, pushRule: PushRule)
|
||||
|
||||
fun addPushRuleListener(listener: PushRuleListener)
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.raw
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* Useful methods to fetch raw data from the server. The access token will not be used to fetched the data
|
||||
*/
|
||||
|
@ -26,17 +23,15 @@ interface RawService {
|
|||
/**
|
||||
* Get a URL, either from cache or from the remote server, depending on the cache strategy
|
||||
*/
|
||||
fun getUrl(url: String,
|
||||
rawCacheStrategy: RawCacheStrategy,
|
||||
matrixCallback: MatrixCallback<String>): Cancelable
|
||||
suspend fun getUrl(url: String, rawCacheStrategy: RawCacheStrategy): String
|
||||
|
||||
/**
|
||||
* Specific case for the well-known file. Cache validity is 8 hours
|
||||
*/
|
||||
fun getWellknown(userId: String, matrixCallback: MatrixCallback<String>): Cancelable
|
||||
suspend fun getWellknown(userId: String): String
|
||||
|
||||
/**
|
||||
* Clear all the cache data
|
||||
*/
|
||||
fun clearCache(matrixCallback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun clearCache()
|
||||
}
|
||||
|
|
|
@ -49,6 +49,12 @@ object EventType {
|
|||
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
||||
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
||||
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
||||
|
||||
/**
|
||||
* Note that this Event has been deprecated, see
|
||||
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||
*/
|
||||
const val STATE_ROOM_ALIASES = "m.room.aliases"
|
||||
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
||||
const val STATE_ROOM_CANONICAL_ALIAS = "m.room.canonical_alias"
|
||||
|
@ -56,6 +62,7 @@ object EventType {
|
|||
const val STATE_ROOM_RELATED_GROUPS = "m.room.related_groups"
|
||||
const val STATE_ROOM_PINNED_EVENT = "m.room.pinned_events"
|
||||
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
|
||||
const val STATE_ROOM_SERVER_ACL = "m.room.server_acl"
|
||||
|
||||
// Call Events
|
||||
const val CALL_INVITE = "m.call.invite"
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.group
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to interact within a group.
|
||||
*/
|
||||
|
@ -28,8 +25,7 @@ interface Group {
|
|||
/**
|
||||
* This methods allows you to refresh data about this group. It will be reflected on the GroupSummary.
|
||||
* The SDK also takes care of refreshing group data every hour.
|
||||
* @param callback : the matrix callback to be notified of success or failure
|
||||
* @return a Cancelable to be able to cancel requests.
|
||||
*/
|
||||
fun fetchGroupData(callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun fetchGroupData()
|
||||
}
|
||||
|
|
|
@ -92,9 +92,29 @@ interface IdentityService {
|
|||
|
||||
/**
|
||||
* Search MatrixId of users providing email and phone numbers
|
||||
* Note the the user consent has to be set to true, or it will throw a UserConsentNotProvided failure
|
||||
* Application has to explicitly ask for the user consent, and the answer can be stored using [setUserConsent]
|
||||
* Please see https://support.google.com/googleplay/android-developer/answer/9888076?hl=en for more details.
|
||||
*/
|
||||
fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable
|
||||
|
||||
/**
|
||||
* Return the current user consent for the current identity server, which has been stored using [setUserConsent].
|
||||
* If [setUserConsent] has not been called, the returned value will be false.
|
||||
* Note that if the identity server is changed, the user consent is reset to false.
|
||||
* @return the value stored using [setUserConsent] or false if [setUserConsent] has never been called, or if the identity server
|
||||
* has been changed
|
||||
*/
|
||||
fun getUserConsent(): Boolean
|
||||
|
||||
/**
|
||||
* Set the user consent to the provided value. Application MUST explicitly ask for the user consent to send their private data
|
||||
* (email and phone numbers) to the identity server.
|
||||
* Please see https://support.google.com/googleplay/android-developer/answer/9888076?hl=en for more details.
|
||||
* @param newValue true if the user explicitly give their consent, false if the user wants to revoke their consent.
|
||||
*/
|
||||
fun setUserConsent(newValue: Boolean)
|
||||
|
||||
/**
|
||||
* Get the status of the current user's threePid
|
||||
* A lookup will be performed, but also pending binding state will be restored
|
||||
|
|
|
@ -24,6 +24,7 @@ sealed class IdentityServiceError : Failure.FeatureFailure() {
|
|||
object NoIdentityServerConfigured : IdentityServiceError()
|
||||
object TermsNotSignedException : IdentityServiceError()
|
||||
object BulkLookupSha256NotSupported : IdentityServiceError()
|
||||
object UserConsentNotProvided : IdentityServiceError()
|
||||
object BindingError : IdentityServiceError()
|
||||
object NoCurrentBindingError : IdentityServiceError()
|
||||
}
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.integrationmanager
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This is the entry point to manage integration. You can grab an instance of this service through an active session.
|
||||
*/
|
||||
|
@ -80,19 +77,17 @@ interface IntegrationManagerService {
|
|||
/**
|
||||
* Offers to enable or disable the integration.
|
||||
* @param enable the param to change
|
||||
* @param callback the matrix callback to listen for result.
|
||||
* @return Cancelable
|
||||
*/
|
||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun setIntegrationEnabled(enable: Boolean)
|
||||
|
||||
/**
|
||||
* Offers to allow or disallow a widget.
|
||||
* @param stateEventId the eventId of the state event defining the widget.
|
||||
* @param allowed the param to change
|
||||
* @param callback the matrix callback to listen for result.
|
||||
* @return Cancelable
|
||||
*/
|
||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean)
|
||||
|
||||
/**
|
||||
* Returns true if the widget is allowed, false otherwise.
|
||||
|
@ -105,7 +100,7 @@ interface IntegrationManagerService {
|
|||
* @param widgetType the widget type to check for
|
||||
* @param domain the domain to check for
|
||||
*/
|
||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean)
|
||||
|
||||
/**
|
||||
* Returns true if the widget domain is allowed, false otherwise.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.api.session.permalinks
|
||||
|
||||
import android.text.Spannable
|
||||
import org.matrix.android.sdk.api.MatrixPatterns
|
||||
|
||||
/**
|
||||
* MatrixLinkify take a piece of text and turns all of the
|
||||
|
@ -35,7 +36,7 @@ object MatrixLinkify {
|
|||
* I disable it because it mess up with pills, and even with pills, it does not work correctly:
|
||||
* The url is not correct. Ex: for @user:matrix.org, the url will be @user:matrix.org, instead of a matrix.to
|
||||
*/
|
||||
/*
|
||||
|
||||
// sanity checks
|
||||
if (spannable.isEmpty()) {
|
||||
return false
|
||||
|
@ -48,14 +49,21 @@ object MatrixLinkify {
|
|||
val startPos = match.range.first
|
||||
if (startPos == 0 || text[startPos - 1] != '/') {
|
||||
val endPos = match.range.last + 1
|
||||
val url = text.substring(match.range)
|
||||
var url = text.substring(match.range)
|
||||
if (MatrixPatterns.isUserId(url)
|
||||
|| MatrixPatterns.isRoomAlias(url)
|
||||
|| MatrixPatterns.isRoomId(url)
|
||||
|| MatrixPatterns.isGroupId(url)
|
||||
|| MatrixPatterns.isEventId(url)) {
|
||||
url = PermalinkService.MATRIX_TO_URL_BASE + url
|
||||
}
|
||||
val span = MatrixPermalinkSpan(url, callback)
|
||||
spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasMatch
|
||||
*/
|
||||
return false
|
||||
|
||||
// return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,13 +44,12 @@ object PermalinkParser {
|
|||
if (fragment.isNullOrEmpty()) {
|
||||
return PermalinkData.FallbackLink(uri)
|
||||
}
|
||||
val indexOfQuery = fragment.indexOf("?")
|
||||
val safeFragment = if (indexOfQuery != -1) fragment.substring(0, indexOfQuery) else fragment
|
||||
val safeFragment = fragment.substringBefore('?')
|
||||
val viaQueryParameters = fragment.getViaParameters()
|
||||
|
||||
// we are limiting to 2 params
|
||||
val params = safeFragment
|
||||
.split(MatrixPatterns.SEP_REGEX.toRegex())
|
||||
.split(MatrixPatterns.SEP_REGEX)
|
||||
.filter { it.isNotEmpty() }
|
||||
.take(2)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room
|
|||
|
||||
import androidx.lifecycle.LiveData
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||
|
@ -46,6 +47,7 @@ interface Room :
|
|||
DraftService,
|
||||
ReadService,
|
||||
TypingService,
|
||||
AliasService,
|
||||
TagsService,
|
||||
MembershipService,
|
||||
StateService,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.api.session.room
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
|
@ -39,4 +40,14 @@ interface RoomDirectoryService {
|
|||
* Includes both the available protocols and all fields required for queries against each protocol.
|
||||
*/
|
||||
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
||||
|
||||
/**
|
||||
* Get the visibility of a room in the directory
|
||||
*/
|
||||
suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility
|
||||
|
||||
/**
|
||||
* Set the visibility of a room in the directory
|
||||
*/
|
||||
suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.session.room
|
|||
import androidx.lifecycle.LiveData
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
@ -121,6 +122,11 @@ interface RoomService {
|
|||
searchOnServer: Boolean,
|
||||
callback: MatrixCallback<Optional<String>>): Cancelable
|
||||
|
||||
/**
|
||||
* Delete a room alias
|
||||
*/
|
||||
suspend fun deleteRoomAlias(roomAlias: String)
|
||||
|
||||
/**
|
||||
* Return a live data of all local changes membership that happened since the session has been opened.
|
||||
* It allows you to track this in your client to known what is currently being processed by the SDK.
|
||||
|
@ -141,4 +147,20 @@ interface RoomService {
|
|||
* - the power level of the users are not taken into account. Normally in a DM, the 2 members are admins of the room
|
||||
*/
|
||||
fun getExistingDirectRoomWithUser(otherUserId: String): String?
|
||||
|
||||
/**
|
||||
* Get a room member for the tuple {userId,roomId}
|
||||
* @param userId the userId to look for.
|
||||
* @param roomId the roomId to look for.
|
||||
* @return the room member or null
|
||||
*/
|
||||
fun getRoomMember(userId: String, roomId: String): RoomMemberSummary?
|
||||
|
||||
/**
|
||||
* Observe a live room member for the tuple {userId,roomId}
|
||||
* @param userId the userId to look for.
|
||||
* @param roomId the roomId to look for.
|
||||
* @return a LiveData of the optional found room member
|
||||
*/
|
||||
fun getRoomMemberLive(userId: String, roomId: String): LiveData<Optional<RoomMemberSummary>>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.alias
|
||||
|
||||
interface AliasService {
|
||||
/**
|
||||
* Get list of local alias of the room
|
||||
* @return the list of the aliases (full aliases, not only the local part)
|
||||
*/
|
||||
suspend fun getRoomAliases(): List<String>
|
||||
|
||||
/**
|
||||
* Add local alias to the room
|
||||
* @param aliasLocalPart the local part of the alias.
|
||||
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||
*/
|
||||
suspend fun addAlias(aliasLocalPart: String)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.alias
|
||||
|
||||
sealed class RoomAliasError : Throwable() {
|
||||
object AliasEmpty : RoomAliasError()
|
||||
object AliasNotAvailable : RoomAliasError()
|
||||
object AliasInvalid : RoomAliasError()
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.room.crypto
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
|
||||
interface RoomCryptoService {
|
||||
|
@ -30,6 +29,5 @@ interface RoomCryptoService {
|
|||
/**
|
||||
* Enable encryption of the room
|
||||
*/
|
||||
fun enableEncryption(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM,
|
||||
callback: MatrixCallback<Unit>)
|
||||
suspend fun enableEncryption(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM)
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ package org.matrix.android.sdk.api.session.room.failure
|
|||
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.failure.MatrixError
|
||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||
|
||||
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
||||
object CreatedWithTimeout : CreateRoomFailure()
|
||||
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
|
||||
data class AliasError(val aliasError: RoomAliasError) : CreateRoomFailure()
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ import com.squareup.moshi.JsonClass
|
|||
|
||||
/**
|
||||
* Class representing the EventType.STATE_ROOM_ALIASES state event content
|
||||
* Note that this Event has been deprecated, see
|
||||
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomAliasesContent(
|
||||
|
|
|
@ -24,5 +24,14 @@ import com.squareup.moshi.JsonClass
|
|||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomCanonicalAliasContent(
|
||||
@Json(name = "alias") val canonicalAlias: String? = null
|
||||
/**
|
||||
* The canonical alias for the room. If not present, null, or empty the room should be considered to have no canonical alias.
|
||||
*/
|
||||
@Json(name = "alias") val canonicalAlias: String? = null,
|
||||
|
||||
/**
|
||||
* Alternative aliases the room advertises.
|
||||
* This list can have aliases despite the alias field being null, empty, or otherwise not present.
|
||||
*/
|
||||
@Json(name = "alt_aliases") val alternativeAliases: List<String>? = null
|
||||
)
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Class representing the EventType.STATE_ROOM_SERVER_ACL state event content
|
||||
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#m-room-server-acl
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomServerAclContent(
|
||||
/**
|
||||
* True to allow server names that are IP address literals. False to deny.
|
||||
* Defaults to true if missing or otherwise not a boolean.
|
||||
* This is strongly recommended to be set to false as servers running with IP literal names are strongly
|
||||
* discouraged in order to require legitimate homeservers to be backed by a valid registered domain name.
|
||||
*/
|
||||
@Json(name = "allow_ip_literals")
|
||||
val allowIpLiterals: Boolean = true,
|
||||
|
||||
/**
|
||||
* The server names to allow in the room, excluding any port information. Wildcards may be used to cover
|
||||
* a wider range of hosts, where * matches zero or more characters and ? matches exactly one character.
|
||||
*
|
||||
* This defaults to an empty list when not provided, effectively disallowing every server.
|
||||
*/
|
||||
@Json(name = "allow")
|
||||
val allowList: List<String> = emptyList(),
|
||||
|
||||
/**
|
||||
* The server names to disallow in the room, excluding any port information. Wildcards may be used to cover
|
||||
* a wider range of hosts, where * matches zero or more characters and ? matches exactly one character.
|
||||
*
|
||||
* This defaults to an empty list when not provided.
|
||||
*/
|
||||
@Json(name = "deny")
|
||||
val denyList: List<String> = emptyList()
|
||||
|
||||
) {
|
||||
companion object {
|
||||
const val ALL = "*"
|
||||
}
|
||||
}
|
|
@ -94,7 +94,22 @@ class CreateRoomParams {
|
|||
* The server will clobber the following keys: creator.
|
||||
* Future versions of the specification may allow the server to clobber other keys.
|
||||
*/
|
||||
var creationContent: Any? = null
|
||||
val creationContent = mutableMapOf<String, Any>()
|
||||
|
||||
/**
|
||||
* Set to true to disable federation of this room.
|
||||
* Default: false
|
||||
*/
|
||||
var disableFederation = false
|
||||
set(value) {
|
||||
field = value
|
||||
if (value) {
|
||||
creationContent[CREATION_CONTENT_KEY_M_FEDERATE] = false
|
||||
} else {
|
||||
// This is the default value, we remove the field
|
||||
creationContent.remove(CREATION_CONTENT_KEY_M_FEDERATE)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The power level content to override in the default power level event
|
||||
|
@ -120,4 +135,8 @@ class CreateRoomParams {
|
|||
fun enableEncryption() {
|
||||
algorithm = MXCRYPTO_ALGORITHM_MEGOLM
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
package org.matrix.android.sdk.api.session.room.notification
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
interface RoomPushRuleService {
|
||||
|
||||
fun getLiveRoomNotificationState(): LiveData<RoomNotificationState>
|
||||
|
||||
fun setRoomNotificationState(roomNotificationState: RoomNotificationState, matrixCallback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun setRoomNotificationState(roomNotificationState: RoomNotificationState)
|
||||
}
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.room.reporting
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to report content of an event.
|
||||
*/
|
||||
|
@ -28,5 +25,5 @@ interface ReportingService {
|
|||
* Report content
|
||||
* Ref: https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-rooms-roomid-report-eventid
|
||||
*/
|
||||
fun reportContent(eventId: String, score: Int, reason: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun reportContent(eventId: String, score: Int, reason: String)
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
package org.matrix.android.sdk.api.session.room.send
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
||||
interface DraftService {
|
||||
|
@ -26,12 +24,12 @@ interface DraftService {
|
|||
/**
|
||||
* Save or update a draft to the room
|
||||
*/
|
||||
fun saveDraft(draft: UserDraft, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun saveDraft(draft: UserDraft)
|
||||
|
||||
/**
|
||||
* Delete the last draft, basically just after sending the message
|
||||
*/
|
||||
fun deleteDraft(callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun deleteDraft()
|
||||
|
||||
/**
|
||||
* Return the current draft or null
|
||||
|
|
|
@ -21,7 +21,9 @@ import androidx.lifecycle.LiveData
|
|||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
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.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
@ -38,21 +40,23 @@ interface StateService {
|
|||
*/
|
||||
fun updateName(name: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Add new alias to the room.
|
||||
*/
|
||||
fun addRoomAlias(roomAlias: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Update the canonical alias of the room
|
||||
* @param alias the canonical alias, or null to reset the canonical alias of this room
|
||||
* @param altAliases the alternative aliases for this room. It should include the canonical alias if any.
|
||||
*/
|
||||
fun updateCanonicalAlias(alias: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
fun updateCanonicalAlias(alias: String?, altAliases: List<String>, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Update the history readability of the room
|
||||
*/
|
||||
fun updateHistoryReadability(readability: RoomHistoryVisibility, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Update the join rule and/or the guest access
|
||||
*/
|
||||
fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
/**
|
||||
* Update the avatar of the room
|
||||
*/
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.room.tags
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to handle tags of a room. It's implemented at the room level.
|
||||
*/
|
||||
|
@ -26,10 +23,10 @@ interface TagsService {
|
|||
/**
|
||||
* Add a tag to a room
|
||||
*/
|
||||
fun addTag(tag: String, order: Double?, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun addTag(tag: String, order: Double?)
|
||||
|
||||
/**
|
||||
* Remove tag from a room
|
||||
*/
|
||||
fun deleteTag(tag: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun deleteTag(tag: String)
|
||||
}
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.room.uploads
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to get event with uploads (= attachments) sent to a room. It's implemented at the room level.
|
||||
*/
|
||||
|
@ -29,7 +26,5 @@ interface UploadsService {
|
|||
* @param numberOfEvents the expected number of events to retrieve. The result can contain less events.
|
||||
* @param since token to get next page, or null to get the first page
|
||||
*/
|
||||
fun getUploads(numberOfEvents: Int,
|
||||
since: String?,
|
||||
callback: MatrixCallback<GetUploadsResult>): Cancelable
|
||||
suspend fun getUploads(numberOfEvents: Int, since: String?): GetUploadsResult
|
||||
}
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.search
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to search messages in rooms.
|
||||
*/
|
||||
|
@ -35,15 +32,13 @@ interface SearchService {
|
|||
* @param beforeLimit how many events before the result are returned.
|
||||
* @param afterLimit how many events after the result are returned.
|
||||
* @param includeProfile requests that the server returns the historic profile information for the users that sent the events that were returned.
|
||||
* @param callback Callback to get the search result
|
||||
*/
|
||||
fun search(searchTerm: String,
|
||||
roomId: String,
|
||||
nextBatch: String?,
|
||||
orderByRecent: Boolean,
|
||||
limit: Int,
|
||||
beforeLimit: Int,
|
||||
afterLimit: Int,
|
||||
includeProfile: Boolean,
|
||||
callback: MatrixCallback<SearchResult>): Cancelable
|
||||
suspend fun search(searchTerm: String,
|
||||
roomId: String,
|
||||
nextBatch: String?,
|
||||
orderByRecent: Boolean,
|
||||
limit: Int,
|
||||
beforeLimit: Int,
|
||||
afterLimit: Int,
|
||||
includeProfile: Boolean): SearchResult
|
||||
}
|
||||
|
|
|
@ -16,22 +16,16 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.terms
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
interface TermsService {
|
||||
enum class ServiceType {
|
||||
IntegrationManager,
|
||||
IdentityService
|
||||
}
|
||||
|
||||
fun getTerms(serviceType: ServiceType,
|
||||
baseUrl: String,
|
||||
callback: MatrixCallback<GetTermsResponse>): Cancelable
|
||||
suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse
|
||||
|
||||
fun agreeToTerms(serviceType: ServiceType,
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
token: String?,
|
||||
callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun agreeToTerms(serviceType: ServiceType,
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
token: String?)
|
||||
}
|
||||
|
|
|
@ -35,6 +35,11 @@ interface UserService {
|
|||
*/
|
||||
fun getUser(userId: String): User?
|
||||
|
||||
/**
|
||||
* Try to resolve user from known users, or using profile api
|
||||
*/
|
||||
fun resolveUser(userId: String, callback: MatrixCallback<User>)
|
||||
|
||||
/**
|
||||
* Search list of users on server directory.
|
||||
* @param search the searched term
|
||||
|
|
|
@ -767,9 +767,9 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
*/
|
||||
private fun onRoomKeyEvent(event: Event) {
|
||||
val roomKeyContent = event.getClearContent().toModel<RoomKeyContent>() ?: return
|
||||
Timber.v("## CRYPTO | GOSSIP onRoomKeyEvent() : type<${event.getClearType()}> , sessionId<${roomKeyContent.sessionId}>")
|
||||
Timber.i("## CRYPTO | onRoomKeyEvent() from: ${event.senderId} type<${event.getClearType()}> , sessionId<${roomKeyContent.sessionId}>")
|
||||
if (roomKeyContent.roomId.isNullOrEmpty() || roomKeyContent.algorithm.isNullOrEmpty()) {
|
||||
Timber.e("## CRYPTO | GOSSIP onRoomKeyEvent() : missing fields")
|
||||
Timber.e("## CRYPTO | onRoomKeyEvent() : missing fields")
|
||||
return
|
||||
}
|
||||
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(roomKeyContent.roomId, roomKeyContent.algorithm)
|
||||
|
@ -782,20 +782,20 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
|
||||
private fun onKeyWithHeldReceived(event: Event) {
|
||||
val withHeldContent = event.getClearContent().toModel<RoomKeyWithHeldContent>() ?: return Unit.also {
|
||||
Timber.e("## CRYPTO | Malformed onKeyWithHeldReceived() : missing fields")
|
||||
Timber.i("## CRYPTO | Malformed onKeyWithHeldReceived() : missing fields")
|
||||
}
|
||||
Timber.d("## CRYPTO | onKeyWithHeldReceived() received : content <$withHeldContent>")
|
||||
Timber.i("## CRYPTO | onKeyWithHeldReceived() received from:${event.senderId}, content <$withHeldContent>")
|
||||
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(withHeldContent.roomId, withHeldContent.algorithm)
|
||||
if (alg is IMXWithHeldExtension) {
|
||||
alg.onRoomKeyWithHeldEvent(withHeldContent)
|
||||
} else {
|
||||
Timber.e("## CRYPTO | onKeyWithHeldReceived() : Unable to handle WithHeldContent for ${withHeldContent.algorithm}")
|
||||
Timber.e("## CRYPTO | onKeyWithHeldReceived() from:${event.senderId}: Unable to handle WithHeldContent for ${withHeldContent.algorithm}")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSecretSendReceived(event: Event) {
|
||||
Timber.i("## CRYPTO | GOSSIP onSecretSend() : onSecretSendReceived ${event.content?.get("sender_key")}")
|
||||
Timber.i("## CRYPTO | GOSSIP onSecretSend() from ${event.senderId} : onSecretSendReceived ${event.content?.get("sender_key")}")
|
||||
if (!event.isEncrypted()) {
|
||||
// secret send messages must be encrypted
|
||||
Timber.e("## CRYPTO | GOSSIP onSecretSend() :Received unencrypted secret send event")
|
||||
|
|
|
@ -119,7 +119,7 @@ internal class EventDecryptor @Inject constructor(
|
|||
markOlmSessionForUnwedging(event.senderId ?: "", it)
|
||||
}
|
||||
?: run {
|
||||
Timber.v("## CRYPTO | markOlmSessionForUnwedging() : Failed to find sender crypto device")
|
||||
Timber.i("## CRYPTO | internalDecryptEvent() : Failed to find sender crypto device for unwedging")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,16 +137,18 @@ internal class EventDecryptor @Inject constructor(
|
|||
val lastForcedDate = lastNewSessionForcedDates.getObject(senderId, deviceKey) ?: 0
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastForcedDate < DefaultCryptoService.CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) {
|
||||
Timber.d("## CRYPTO | markOlmSessionForUnwedging: New session already forced with device at $lastForcedDate. Not forcing another")
|
||||
Timber.w("## CRYPTO | markOlmSessionForUnwedging: New session already forced with device at $lastForcedDate. Not forcing another")
|
||||
return
|
||||
}
|
||||
|
||||
Timber.d("## CRYPTO | markOlmSessionForUnwedging from $senderId:${deviceInfo.deviceId}")
|
||||
Timber.i("## CRYPTO | markOlmSessionForUnwedging from $senderId:${deviceInfo.deviceId}")
|
||||
lastNewSessionForcedDates.setObject(senderId, deviceKey, now)
|
||||
|
||||
// offload this from crypto thread (?)
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.computation) {
|
||||
ensureOlmSessionsForDevicesAction.handle(mapOf(senderId to listOf(deviceInfo)), force = true)
|
||||
val ensured = ensureOlmSessionsForDevicesAction.handle(mapOf(senderId to listOf(deviceInfo)), force = true)
|
||||
|
||||
Timber.i("## CRYPTO | markOlmSessionForUnwedging() : ensureOlmSessionsForDevicesAction isEmpty:${ensured.isEmpty}")
|
||||
|
||||
// Now send a blank message on that session so the other side knows about it.
|
||||
// (The keyshare request is sent in the clear so that won't do)
|
||||
|
@ -159,10 +161,14 @@ internal class EventDecryptor @Inject constructor(
|
|||
val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo))
|
||||
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
||||
sendToDeviceMap.setObject(senderId, deviceInfo.deviceId, encodedPayload)
|
||||
Timber.v("## CRYPTO | markOlmSessionForUnwedging() : sending to $senderId:${deviceInfo.deviceId}")
|
||||
Timber.i("## CRYPTO | markOlmSessionForUnwedging() : sending dummy to $senderId:${deviceInfo.deviceId}")
|
||||
withContext(coroutineDispatchers.io) {
|
||||
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
|
||||
sendToDeviceTask.execute(sendToDeviceParams)
|
||||
try {
|
||||
sendToDeviceTask.execute(sendToDeviceParams)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## CRYPTO | markOlmSessionForUnwedging() : failed to send dummy to $senderId:${deviceInfo.deviceId}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ internal class IncomingGossipingRequestManager @Inject constructor(
|
|||
private val cryptoCoroutineScope: CoroutineScope) {
|
||||
|
||||
private val executor = Executors.newSingleThreadExecutor()
|
||||
|
||||
// list of IncomingRoomKeyRequests/IncomingRoomKeyRequestCancellations
|
||||
// we received in the current sync.
|
||||
private val receivedGossipingRequests = ArrayList<IncomingShareRequestCommon>()
|
||||
|
@ -103,11 +104,11 @@ internal class IncomingGossipingRequestManager @Inject constructor(
|
|||
* @param event the announcement event.
|
||||
*/
|
||||
fun onGossipingRequestEvent(event: Event) {
|
||||
Timber.v("## CRYPTO | GOSSIP onGossipingRequestEvent type ${event.type} from user ${event.senderId}")
|
||||
val roomKeyShare = event.getClearContent().toModel<GossipingDefaultContent>()
|
||||
Timber.i("## CRYPTO | GOSSIP onGossipingRequestEvent received type ${event.type} from user:${event.senderId}, content:$roomKeyShare")
|
||||
// val ageLocalTs = event.unsignedData?.age?.let { System.currentTimeMillis() - it }
|
||||
when (roomKeyShare?.action) {
|
||||
GossipingToDeviceObject.ACTION_SHARE_REQUEST -> {
|
||||
GossipingToDeviceObject.ACTION_SHARE_REQUEST -> {
|
||||
if (event.getClearType() == EventType.REQUEST_SECRET) {
|
||||
IncomingSecretShareRequest.fromEvent(event)?.let {
|
||||
if (event.senderId == credentials.userId && it.deviceId == credentials.deviceId) {
|
||||
|
@ -324,7 +325,7 @@ internal class IncomingGossipingRequestManager @Inject constructor(
|
|||
val isDeviceLocallyVerified = cryptoStore.getUserDevice(userId, deviceId)?.trustLevel?.isLocallyVerified()
|
||||
|
||||
when (secretName) {
|
||||
MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master
|
||||
MASTER_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.master
|
||||
SELF_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.selfSigned
|
||||
USER_SIGNING_KEY_SSSS_NAME -> cryptoStore.getCrossSigningPrivateKeys()?.user
|
||||
KEYBACKUP_SECRET_SSSS_NAME -> cryptoStore.getKeyBackupRecoveryKeyInfo()?.recoveryKey
|
||||
|
|
|
@ -760,7 +760,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
return session
|
||||
}
|
||||
} else {
|
||||
Timber.v("## getInboundGroupSession() : Cannot retrieve inbound group session $sessionId")
|
||||
Timber.w("## getInboundGroupSession() : Cannot retrieve inbound group session $sessionId")
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID, MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ internal class SendGossipWorker(context: Context,
|
|||
requestId = params.requestId,
|
||||
state = GossipingRequestState.FAILED_TO_ACCEPTED
|
||||
)
|
||||
Timber.e("no session with this device, probably because there were no one-time keys.")
|
||||
Timber.e("no session with this device $requestingDeviceId, probably because there were no one-time keys.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ internal class EnsureOlmSessionsForDevicesAction @Inject constructor(
|
|||
//
|
||||
// That should eventually resolve itself, but it's poor form.
|
||||
|
||||
Timber.v("## CRYPTO | claimOneTimeKeysForUsersDevices() : $usersDevicesToClaim")
|
||||
Timber.i("## CRYPTO | claimOneTimeKeysForUsersDevices() : $usersDevicesToClaim")
|
||||
|
||||
val claimParams = ClaimOneTimeKeysForUsersDeviceTask.Params(usersDevicesToClaim)
|
||||
val oneTimeKeys = oneTimeKeysForUsersDeviceTask.execute(claimParams)
|
||||
|
@ -90,7 +90,7 @@ internal class EnsureOlmSessionsForDevicesAction @Inject constructor(
|
|||
oneTimeKey = key
|
||||
}
|
||||
if (oneTimeKey == null) {
|
||||
Timber.v("## CRYPTO | ensureOlmSessionsForDevices() : No one-time keys " + oneTimeKeyAlgorithm
|
||||
Timber.w("## CRYPTO | ensureOlmSessionsForDevices() : No one-time keys " + oneTimeKeyAlgorithm
|
||||
+ " for device " + userId + " : " + deviceId)
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -243,8 +243,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
return
|
||||
}
|
||||
if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
|
||||
Timber.v("## CRYPTO | onRoomKeyEvent(), forward adding key : roomId ${roomKeyContent.roomId}" +
|
||||
" sessionId ${roomKeyContent.sessionId} sessionKey ${roomKeyContent.sessionKey}")
|
||||
Timber.i("## CRYPTO | onRoomKeyEvent(), forward adding key : ${roomKeyContent.roomId}|${roomKeyContent.sessionId}")
|
||||
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>()
|
||||
?: return
|
||||
|
||||
|
@ -273,9 +272,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
|
||||
keysClaimed["ed25519"] = forwardedRoomKeyContent.senderClaimedEd25519Key
|
||||
} else {
|
||||
Timber.v("## CRYPTO | onRoomKeyEvent(), Adding key : roomId " + roomKeyContent.roomId + " sessionId " + roomKeyContent.sessionId
|
||||
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);
|
||||
|
||||
Timber.i("## CRYPTO | onRoomKeyEvent(), Adding key : ${roomKeyContent.roomId}|${roomKeyContent.sessionId}")
|
||||
if (null == senderKey) {
|
||||
Timber.e("## onRoomKeyEvent() : key event has no sender key (not encrypted?)")
|
||||
return
|
||||
|
@ -285,7 +282,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
keysClaimed = event.getKeysClaimed().toMutableMap()
|
||||
}
|
||||
|
||||
Timber.e("## CRYPTO | onRoomKeyEvent addInboundGroupSession ${roomKeyContent.sessionId}")
|
||||
Timber.i("## CRYPTO | onRoomKeyEvent addInboundGroupSession ${roomKeyContent.sessionId}")
|
||||
val added = olmDevice.addInboundGroupSession(roomKeyContent.sessionId,
|
||||
roomKeyContent.sessionKey,
|
||||
roomKeyContent.roomId,
|
||||
|
@ -349,10 +346,10 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
if (olmSessionResult?.sessionId == null) {
|
||||
// no session with this device, probably because there
|
||||
// were no one-time keys.
|
||||
Timber.e("no session with this device $deviceId, probably because there were no one-time keys.")
|
||||
return@mapCatching
|
||||
}
|
||||
Timber.v("## CRYPTO | shareKeysWithDevice() : sharing keys for session" +
|
||||
" ${body.senderKey}|${body.sessionId} with device $userId:$deviceId")
|
||||
Timber.i("## CRYPTO | shareKeysWithDevice() : sharing session ${body.sessionId} with device $userId:$deviceId")
|
||||
|
||||
val payloadJson = mutableMapOf<String, Any>("type" to EventType.FORWARDED_ROOM_KEY)
|
||||
runCatching { olmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId) }
|
||||
|
@ -363,6 +360,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
},
|
||||
{
|
||||
// TODO
|
||||
Timber.e(it, "## CRYPTO | shareKeysWithDevice: failed to get session for request $body")
|
||||
}
|
||||
|
||||
)
|
||||
|
@ -370,9 +368,13 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo))
|
||||
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
||||
sendToDeviceMap.setObject(userId, deviceId, encodedPayload)
|
||||
Timber.v("## CRYPTO | shareKeysWithDevice() : sending to $userId:$deviceId")
|
||||
Timber.i("## CRYPTO | shareKeysWithDevice() : sending ${body.sessionId} to $userId:$deviceId")
|
||||
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
|
||||
sendToDeviceTask.execute(sendToDeviceParams)
|
||||
try {
|
||||
sendToDeviceTask.execute(sendToDeviceParams)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## CRYPTO | shareKeysWithDevice() : Failed to send ${body.sessionId} to $userId:$deviceId")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,8 +217,10 @@ internal class MXMegolmEncryption(
|
|||
Timber.v("## CRYPTO | shareUserDevicesKey() : starts")
|
||||
|
||||
val results = ensureOlmSessionsForDevicesAction.handle(devicesByUser)
|
||||
Timber.v("## CRYPTO | shareUserDevicesKey() : ensureOlmSessionsForDevices succeeds after "
|
||||
+ (System.currentTimeMillis() - t0) + " ms")
|
||||
Timber.v(
|
||||
"""## CRYPTO | shareUserDevicesKey(): ensureOlmSessionsForDevices succeeds after ${System.currentTimeMillis() - t0} ms"""
|
||||
.trimMargin()
|
||||
)
|
||||
val contentMap = MXUsersDevicesMap<Any>()
|
||||
var haveTargets = false
|
||||
val userIds = results.userIds
|
||||
|
@ -242,7 +244,7 @@ internal class MXMegolmEncryption(
|
|||
|
||||
continue
|
||||
}
|
||||
Timber.v("## CRYPTO | shareUserDevicesKey() : Sharing keys with device $userId:$deviceID")
|
||||
Timber.i("## CRYPTO | shareUserDevicesKey() : Sharing keys with device $userId:$deviceID")
|
||||
contentMap.setObject(userId, deviceID, messageEncrypter.encryptMessage(payload, listOf(sessionResult.deviceInfo)))
|
||||
haveTargets = true
|
||||
}
|
||||
|
@ -270,21 +272,22 @@ internal class MXMegolmEncryption(
|
|||
|
||||
if (haveTargets) {
|
||||
t0 = System.currentTimeMillis()
|
||||
Timber.v("## CRYPTO | shareUserDevicesKey() : has target")
|
||||
Timber.i("## CRYPTO | shareUserDevicesKey() ${session.sessionId} : has target")
|
||||
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap)
|
||||
try {
|
||||
sendToDeviceTask.execute(sendToDeviceParams)
|
||||
Timber.v("## CRYPTO | shareUserDevicesKey() : sendToDevice succeeds after ${System.currentTimeMillis() - t0} ms")
|
||||
Timber.i("## CRYPTO | shareUserDevicesKey() : sendToDevice succeeds after ${System.currentTimeMillis() - t0} ms")
|
||||
} catch (failure: Throwable) {
|
||||
// What to do here...
|
||||
Timber.e("## CRYPTO | shareUserDevicesKey() : Failed to share session <${session.sessionId}> with $devicesByUser ")
|
||||
}
|
||||
} else {
|
||||
Timber.v("## CRYPTO | shareUserDevicesKey() : no need to sharekey")
|
||||
Timber.i("## CRYPTO | shareUserDevicesKey() : no need to sharekey")
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyKeyWithHeld(targets: List<UserDevice>, sessionId: String, senderKey: String?, code: WithHeldCode) {
|
||||
Timber.i("## CRYPTO | notifyKeyWithHeld() :sending withheld key for $targets session:$sessionId ")
|
||||
val withHeldContent = RoomKeyWithHeldContent(
|
||||
roomId = roomId,
|
||||
senderKey = senderKey,
|
||||
|
@ -393,16 +396,16 @@ internal class MXMegolmEncryption(
|
|||
userId: String,
|
||||
deviceId: String,
|
||||
senderKey: String): Boolean {
|
||||
Timber.d("[MXMegolmEncryption] reshareKey: $sessionId to $userId:$deviceId")
|
||||
Timber.i("## Crypto process reshareKey for $sessionId to $userId:$deviceId")
|
||||
val deviceInfo = cryptoStore.getUserDevice(userId, deviceId) ?: return false
|
||||
.also { Timber.w("Device not found") }
|
||||
.also { Timber.w("## Crypto reshareKey: Device not found") }
|
||||
|
||||
// Get the chain index of the key we previously sent this device
|
||||
val chainIndex = outboundSession?.sharedWithHelper?.wasSharedWith(userId, deviceId) ?: return false
|
||||
.also {
|
||||
// Send a room key with held
|
||||
notifyKeyWithHeld(listOf(UserDevice(userId, deviceId)), sessionId, senderKey, WithHeldCode.UNAUTHORISED)
|
||||
Timber.w("[MXMegolmEncryption] reshareKey : ERROR : Never share megolm with this device")
|
||||
Timber.w("## Crypto reshareKey: ERROR : Never share megolm with this device")
|
||||
}
|
||||
|
||||
val devicesByUser = mapOf(userId to listOf(deviceInfo))
|
||||
|
@ -411,9 +414,11 @@ internal class MXMegolmEncryption(
|
|||
olmSessionResult?.sessionId
|
||||
?: // no session with this device, probably because there were no one-time keys.
|
||||
// ensureOlmSessionsForDevicesAction has already done the logging, so just skip it.
|
||||
return false
|
||||
return false.also {
|
||||
Timber.w("## Crypto reshareKey: no session with this device, probably because there were no one-time keys")
|
||||
}
|
||||
|
||||
Timber.d("[MXMegolmEncryption] reshareKey: sharing keys for session $senderKey|$sessionId:$chainIndex with device $userId:$deviceId")
|
||||
Timber.i("[MXMegolmEncryption] reshareKey: sharing keys for session $senderKey|$sessionId:$chainIndex with device $userId:$deviceId")
|
||||
|
||||
val payloadJson = mutableMapOf<String, Any>("type" to EventType.FORWARDED_ROOM_KEY)
|
||||
|
||||
|
@ -425,6 +430,7 @@ internal class MXMegolmEncryption(
|
|||
},
|
||||
{
|
||||
// TODO
|
||||
Timber.e(it, "[MXMegolmEncryption] reshareKey: failed to get session $sessionId|$senderKey|$roomId")
|
||||
}
|
||||
|
||||
)
|
||||
|
@ -432,13 +438,14 @@ internal class MXMegolmEncryption(
|
|||
val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo))
|
||||
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
||||
sendToDeviceMap.setObject(userId, deviceId, encodedPayload)
|
||||
Timber.v("## CRYPTO | CRYPTO | reshareKey() : sending to $userId:$deviceId")
|
||||
Timber.i("## CRYPTO | reshareKey() : sending session $sessionId to $userId:$deviceId")
|
||||
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
|
||||
return try {
|
||||
sendToDeviceTask.execute(sendToDeviceParams)
|
||||
Timber.i("## CRYPTO reshareKey() : successfully send <$sessionId> to $userId:$deviceId")
|
||||
true
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## CRYPTO | CRYPTO | reshareKey() : fail to send <$sessionId> to $userId:$deviceId")
|
||||
Timber.e(failure, "## CRYPTO reshareKey() : fail to send <$sessionId> to $userId:$deviceId")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.matrix.android.sdk.internal.task.TaskThread
|
|||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.internal.util.withoutPrefix
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
|
@ -444,7 +443,7 @@ internal class DefaultCrossSigningService @Inject constructor(
|
|||
} else {
|
||||
// Maybe it's signed by a locally trusted device?
|
||||
myMasterKey.signatures?.get(userId)?.forEach { (key, value) ->
|
||||
val potentialDeviceId = key.withoutPrefix("ed25519:")
|
||||
val potentialDeviceId = key.removePrefix("ed25519:")
|
||||
val potentialDevice = myDevices?.firstOrNull { it.deviceId == potentialDeviceId } // cryptoStore.getUserDevice(userId, potentialDeviceId)
|
||||
if (potentialDevice != null && potentialDevice.isVerified) {
|
||||
// Check signature validity?
|
||||
|
|
|
@ -241,9 +241,9 @@ internal class UpdateTrustWorker(context: Context,
|
|||
private fun computeRoomShield(activeMemberUserIds: List<String>, roomSummaryEntity: RoomSummaryEntity): RoomEncryptionTrustLevel {
|
||||
Timber.d("## CrossSigning - computeRoomShield ${roomSummaryEntity.roomId} -> $activeMemberUserIds")
|
||||
// The set of “all users” depends on the type of room:
|
||||
// For regular / topic rooms, all users including yourself, are considered when decorating a room
|
||||
// For regular / topic rooms which have more than 2 members (including yourself) are considered when decorating a room
|
||||
// For 1:1 and group DM rooms, all other users (i.e. excluding yourself) are considered when decorating a room
|
||||
val listToCheck = if (roomSummaryEntity.isDirect) {
|
||||
val listToCheck = if (roomSummaryEntity.isDirect || activeMemberUserIds.size <= 2) {
|
||||
activeMemberUserIds.filter { it != myUserId }
|
||||
} else {
|
||||
activeMemberUserIds
|
||||
|
|
|
@ -1679,27 +1679,24 @@ internal class RealmCryptoStore @Inject constructor(
|
|||
// Only keep one week history
|
||||
realm.where<IncomingGossipingRequestEntity>()
|
||||
.lessThan(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, prevWeekTs)
|
||||
.findAll().let {
|
||||
Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity")
|
||||
it.deleteAllFromRealm()
|
||||
}
|
||||
.findAll()
|
||||
.also { Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity") }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
// Clean the cancelled ones?
|
||||
realm.where<OutgoingGossipingRequestEntity>()
|
||||
.equalTo(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, OutgoingGossipingRequestState.CANCELLED.name)
|
||||
.equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name)
|
||||
.findAll().let {
|
||||
Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity")
|
||||
it.deleteAllFromRealm()
|
||||
}
|
||||
.findAll()
|
||||
.also { Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity") }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
// Only keep one week history
|
||||
realm.where<GossipingEventEntity>()
|
||||
.lessThan(GossipingEventEntityFields.AGE_LOCAL_TS, prevWeekTs)
|
||||
.findAll().let {
|
||||
Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields")
|
||||
it.deleteAllFromRealm()
|
||||
}
|
||||
.findAll()
|
||||
.also { Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields") }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
// Can we do something for WithHeldSessionEntity?
|
||||
}
|
||||
|
|
|
@ -1204,7 +1204,7 @@ internal class DefaultVerificationService @Inject constructor(
|
|||
Timber.i("## Requesting verification to user: $otherUserId with device list $otherDevices")
|
||||
|
||||
val targetDevices = otherDevices ?: cryptoStore.getUserDevices(otherUserId)
|
||||
?.values?.map { it.deviceId } ?: emptyList()
|
||||
?.values?.map { it.deviceId }.orEmpty()
|
||||
|
||||
val requestsForUser = pendingRequests.getOrPut(otherUserId) { mutableListOf() }
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager
|
|||
import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction
|
||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||
import org.matrix.android.sdk.internal.extensions.toUnsignedInt
|
||||
import org.matrix.android.sdk.internal.util.withoutPrefix
|
||||
import org.matrix.olm.OlmSAS
|
||||
import org.matrix.olm.OlmUtility
|
||||
import timber.log.Timber
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Represents an ongoing short code interactive key verification between two devices.
|
||||
|
@ -250,7 +250,7 @@ internal abstract class SASDefaultVerificationTransaction(
|
|||
|
||||
// cannot be empty because it has been validated
|
||||
theirMacSafe.mac.keys.forEach {
|
||||
val keyIDNoPrefix = it.withoutPrefix("ed25519:")
|
||||
val keyIDNoPrefix = it.removePrefix("ed25519:")
|
||||
val otherDeviceKey = otherUserKnownDevices?.get(keyIDNoPrefix)?.fingerprint()
|
||||
if (otherDeviceKey == null) {
|
||||
Timber.w("## SAS Verification: Could not find device $keyIDNoPrefix to verify")
|
||||
|
@ -273,7 +273,7 @@ internal abstract class SASDefaultVerificationTransaction(
|
|||
if (otherCrossSigningMasterKeyPublic != null) {
|
||||
// Did the user signed his master key
|
||||
theirMacSafe.mac.keys.forEach {
|
||||
val keyIDNoPrefix = it.withoutPrefix("ed25519:")
|
||||
val keyIDNoPrefix = it.removePrefix("ed25519:")
|
||||
if (keyIDNoPrefix == otherCrossSigningMasterKeyPublic) {
|
||||
// Check the signature
|
||||
val mac = macUsingAgreedMethod(otherCrossSigningMasterKeyPublic, baseInfo + it)
|
||||
|
@ -345,7 +345,7 @@ internal abstract class SASDefaultVerificationTransaction(
|
|||
}
|
||||
|
||||
protected fun hashUsingAgreedHashMethod(toHash: String): String? {
|
||||
if ("sha256".toLowerCase() == accepted?.hash?.toLowerCase()) {
|
||||
if ("sha256" == accepted?.hash?.toLowerCase(Locale.ROOT)) {
|
||||
val olmUtil = OlmUtility()
|
||||
val hashBytes = olmUtil.sha256(toHash)
|
||||
olmUtil.releaseUtility()
|
||||
|
@ -355,12 +355,11 @@ internal abstract class SASDefaultVerificationTransaction(
|
|||
}
|
||||
|
||||
private fun macUsingAgreedMethod(message: String, info: String): String? {
|
||||
if (SAS_MAC_SHA256_LONGKDF.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
|
||||
return getSAS().calculateMacLongKdf(message, info)
|
||||
} else if (SAS_MAC_SHA256.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
|
||||
return getSAS().calculateMac(message, info)
|
||||
return when (accepted?.messageAuthenticationCode?.toLowerCase(Locale.ROOT)) {
|
||||
SAS_MAC_SHA256_LONGKDF -> getSAS().calculateMacLongKdf(message, info)
|
||||
SAS_MAC_SHA256 -> getSAS().calculateMac(message, info)
|
||||
else -> null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getDecimalCodeRepresentation(): String {
|
||||
|
|
|
@ -52,5 +52,8 @@ internal class TimeOutInterceptor @Inject constructor() : Interceptor {
|
|||
const val CONNECT_TIMEOUT = "CONNECT_TIMEOUT"
|
||||
const val READ_TIMEOUT = "READ_TIMEOUT"
|
||||
const val WRITE_TIMEOUT = "WRITE_TIMEOUT"
|
||||
|
||||
// 1 minute
|
||||
const val DEFAULT_LONG_TIMEOUT: Long = 60_000
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,45 +16,28 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.raw
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.raw.RawCacheStrategy
|
||||
import org.matrix.android.sdk.api.raw.RawService
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultRawService @Inject constructor(
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val getUrlTask: GetUrlTask,
|
||||
private val cleanRawCacheTask: CleanRawCacheTask
|
||||
) : RawService {
|
||||
override fun getUrl(url: String,
|
||||
rawCacheStrategy: RawCacheStrategy,
|
||||
matrixCallback: MatrixCallback<String>): Cancelable {
|
||||
return getUrlTask
|
||||
.configureWith(GetUrlTask.Params(url, rawCacheStrategy)) {
|
||||
callback = matrixCallback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
override suspend fun getUrl(url: String, rawCacheStrategy: RawCacheStrategy): String {
|
||||
return getUrlTask.execute(GetUrlTask.Params(url, rawCacheStrategy))
|
||||
}
|
||||
|
||||
override fun getWellknown(userId: String,
|
||||
matrixCallback: MatrixCallback<String>): Cancelable {
|
||||
override suspend fun getWellknown(userId: String): String {
|
||||
val homeServerDomain = userId.substringAfter(":")
|
||||
return getUrl(
|
||||
"https://$homeServerDomain/.well-known/matrix/client",
|
||||
RawCacheStrategy.TtlCache(TimeUnit.HOURS.toMillis(8), false),
|
||||
matrixCallback
|
||||
RawCacheStrategy.TtlCache(TimeUnit.HOURS.toMillis(8), false)
|
||||
)
|
||||
}
|
||||
|
||||
override fun clearCache(matrixCallback: MatrixCallback<Unit>): Cancelable {
|
||||
return cleanRawCacheTask
|
||||
.configureWith(Unit) {
|
||||
callback = matrixCallback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
override suspend fun clearCache() {
|
||||
cleanRawCacheTask.execute(Unit)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.session.directory
|
||||
|
||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||
import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasBody
|
||||
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Path
|
||||
|
||||
internal interface DirectoryAPI {
|
||||
/**
|
||||
* Get the room ID associated to the room alias.
|
||||
*
|
||||
* @param roomAlias the room alias.
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun getRoomIdByAlias(@Path("roomAlias") roomAlias: String): Call<RoomAliasDescription>
|
||||
|
||||
/**
|
||||
* Get the room directory visibility.
|
||||
*
|
||||
* @param roomId the room id.
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}")
|
||||
fun getRoomDirectoryVisibility(@Path("roomId") roomId: String): Call<RoomDirectoryVisibilityJson>
|
||||
|
||||
/**
|
||||
* Set the room directory visibility.
|
||||
*
|
||||
* @param roomId the room id.
|
||||
* @param body the body containing the new directory visibility
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}")
|
||||
fun setRoomDirectoryVisibility(@Path("roomId") roomId: String,
|
||||
@Body body: RoomDirectoryVisibilityJson): Call<Unit>
|
||||
|
||||
/**
|
||||
* Add alias to the room.
|
||||
* @param roomAlias the room alias.
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun addRoomAlias(@Path("roomAlias") roomAlias: String,
|
||||
@Body body: AddRoomAliasBody): Call<Unit>
|
||||
|
||||
/**
|
||||
* Delete a room alias
|
||||
* @param roomAlias the room alias.
|
||||
*/
|
||||
@DELETE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
fun deleteRoomAlias(@Path("roomAlias") roomAlias: String): Call<Unit>
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.session.directory
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class RoomDirectoryVisibilityJson(
|
||||
/**
|
||||
* The visibility of the room in the directory. One of: ["private", "public"]
|
||||
*/
|
||||
@Json(name = "visibility") val visibility: RoomDirectoryVisibility
|
||||
)
|
|
@ -16,20 +16,13 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.group
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.group.Group
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
|
||||
internal class DefaultGroup(override val groupId: String,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val getGroupDataTask: GetGroupDataTask) : Group {
|
||||
|
||||
override fun fetchGroupData(callback: MatrixCallback<Unit>): Cancelable {
|
||||
override suspend fun fetchGroupData() {
|
||||
val params = GetGroupDataTask.Params.FetchWithIds(listOf(groupId))
|
||||
return getGroupDataTask.configureWith(params) {
|
||||
this.callback = callback
|
||||
}.executeBy(taskExecutor)
|
||||
getGroupDataTask.execute(params)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.group
|
|||
|
||||
import org.matrix.android.sdk.api.session.group.Group
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface GroupFactory {
|
||||
|
@ -26,14 +25,12 @@ internal interface GroupFactory {
|
|||
}
|
||||
|
||||
@SessionScope
|
||||
internal class DefaultGroupFactory @Inject constructor(private val getGroupDataTask: GetGroupDataTask,
|
||||
private val taskExecutor: TaskExecutor) :
|
||||
internal class DefaultGroupFactory @Inject constructor(private val getGroupDataTask: GetGroupDataTask) :
|
||||
GroupFactory {
|
||||
|
||||
override fun create(groupId: String): Group {
|
||||
return DefaultGroup(
|
||||
groupId = groupId,
|
||||
taskExecutor = taskExecutor,
|
||||
getGroupDataTask = getGroupDataTask
|
||||
)
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
|||
import org.matrix.android.sdk.internal.util.ensureProtocol
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
|
@ -243,7 +244,20 @@ internal class DefaultIdentityService @Inject constructor(
|
|||
))
|
||||
}
|
||||
|
||||
override fun getUserConsent(): Boolean {
|
||||
return identityStore.getIdentityData()?.userConsent.orFalse()
|
||||
}
|
||||
|
||||
override fun setUserConsent(newValue: Boolean) {
|
||||
identityStore.setUserConsent(newValue)
|
||||
}
|
||||
|
||||
override fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable {
|
||||
if (!getUserConsent()) {
|
||||
callback.onFailure(IdentityServiceError.UserConsentNotProvided)
|
||||
return NoOpCancellable
|
||||
}
|
||||
|
||||
if (threePids.isEmpty()) {
|
||||
callback.onSuccess(emptyList())
|
||||
return NoOpCancellable
|
||||
|
@ -255,6 +269,9 @@ internal class DefaultIdentityService @Inject constructor(
|
|||
}
|
||||
|
||||
override fun getShareStatus(threePids: List<ThreePid>, callback: MatrixCallback<Map<ThreePid, SharedState>>): Cancelable {
|
||||
// Note: we do not require user consent here, because it is used for emails and phone numbers that the user has already sent
|
||||
// to the home server, and not emails and phone numbers from the contact book of the user
|
||||
|
||||
if (threePids.isEmpty()) {
|
||||
callback.onSuccess(emptyMap())
|
||||
return NoOpCancellable
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.matrix.android.sdk.internal.session.identity.db.IdentityRealmModule
|
|||
import org.matrix.android.sdk.internal.session.identity.db.RealmIdentityStore
|
||||
import io.realm.RealmConfiguration
|
||||
import okhttp3.OkHttpClient
|
||||
import org.matrix.android.sdk.internal.session.identity.db.RealmIdentityStoreMigration
|
||||
import java.io.File
|
||||
|
||||
@Module
|
||||
|
@ -59,6 +60,7 @@ internal abstract class IdentityModule {
|
|||
@SessionScope
|
||||
fun providesIdentityRealmConfiguration(realmKeysUtils: RealmKeysUtils,
|
||||
@SessionFilesDirectory directory: File,
|
||||
migration: RealmIdentityStoreMigration,
|
||||
@UserMd5 userMd5: String): RealmConfiguration {
|
||||
return RealmConfiguration.Builder()
|
||||
.directory(directory)
|
||||
|
@ -66,6 +68,8 @@ internal abstract class IdentityModule {
|
|||
.apply {
|
||||
realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5))
|
||||
}
|
||||
.schemaVersion(RealmIdentityStoreMigration.IDENTITY_STORE_SCHEMA_VERSION)
|
||||
.migration(migration)
|
||||
.allowWritesOnUiThread(true)
|
||||
.modules(IdentityRealmModule())
|
||||
.build()
|
||||
|
|
|
@ -20,5 +20,6 @@ internal data class IdentityData(
|
|||
val identityServerUrl: String?,
|
||||
val token: String?,
|
||||
val hashLookupPepper: String?,
|
||||
val hashLookupAlgorithm: List<String>
|
||||
val hashLookupAlgorithm: List<String>,
|
||||
val userConsent: Boolean
|
||||
)
|
||||
|
|
|
@ -27,6 +27,8 @@ internal interface IdentityStore {
|
|||
|
||||
fun setToken(token: String?)
|
||||
|
||||
fun setUserConsent(consent: Boolean)
|
||||
|
||||
fun setHashDetails(hashDetailResponse: IdentityHashDetailResponse)
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,7 +23,8 @@ internal open class IdentityDataEntity(
|
|||
var identityServerUrl: String? = null,
|
||||
var token: String? = null,
|
||||
var hashLookupPepper: String? = null,
|
||||
var hashLookupAlgorithm: RealmList<String> = RealmList()
|
||||
var hashLookupAlgorithm: RealmList<String> = RealmList(),
|
||||
var userConsent: Boolean = false
|
||||
) : RealmObject() {
|
||||
|
||||
companion object
|
||||
|
|
|
@ -52,6 +52,13 @@ internal fun IdentityDataEntity.Companion.setToken(realm: Realm,
|
|||
}
|
||||
}
|
||||
|
||||
internal fun IdentityDataEntity.Companion.setUserConsent(realm: Realm,
|
||||
newConsent: Boolean) {
|
||||
get(realm)?.apply {
|
||||
userConsent = newConsent
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IdentityDataEntity.Companion.setHashDetails(realm: Realm,
|
||||
pepper: String,
|
||||
algorithms: List<String>) {
|
||||
|
|
|
@ -26,7 +26,8 @@ internal object IdentityMapper {
|
|||
identityServerUrl = entity.identityServerUrl,
|
||||
token = entity.token,
|
||||
hashLookupPepper = entity.hashLookupPepper,
|
||||
hashLookupAlgorithm = entity.hashLookupAlgorithm.toList()
|
||||
hashLookupAlgorithm = entity.hashLookupAlgorithm.toList(),
|
||||
userConsent = entity.userConsent
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,14 @@ internal class RealmIdentityStore @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun setUserConsent(consent: Boolean) {
|
||||
Realm.getInstance(realmConfiguration).use {
|
||||
it.executeTransaction { realm ->
|
||||
IdentityDataEntity.setUserConsent(realm, consent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setHashDetails(hashDetailResponse: IdentityHashDetailResponse) {
|
||||
Realm.getInstance(realmConfiguration).use {
|
||||
it.executeTransaction { realm ->
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.session.identity.db
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.RealmMigration
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class RealmIdentityStoreMigration @Inject constructor() : RealmMigration {
|
||||
|
||||
companion object {
|
||||
const val IDENTITY_STORE_SCHEMA_VERSION = 1L
|
||||
}
|
||||
|
||||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.v("Migrating Realm Identity from $oldVersion to $newVersion")
|
||||
|
||||
if (oldVersion <= 0) migrateTo1(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1(realm: DynamicRealm) {
|
||||
Timber.d("Step 0 -> 1")
|
||||
Timber.d("Add field userConsent (Boolean) and set the value to false")
|
||||
|
||||
realm.schema.get("IdentityDataEntity")
|
||||
?.addField(IdentityDataEntityFields.USER_CONSENT, Boolean::class.java)
|
||||
}
|
||||
}
|
|
@ -16,10 +16,8 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.integrationmanager
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultIntegrationManagerService @Inject constructor(private val integrationManager: IntegrationManager) : IntegrationManagerService {
|
||||
|
@ -44,20 +42,20 @@ internal class DefaultIntegrationManagerService @Inject constructor(private val
|
|||
return integrationManager.isIntegrationEnabled()
|
||||
}
|
||||
|
||||
override fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setIntegrationEnabled(enable, callback)
|
||||
override suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||
integrationManager.setIntegrationEnabled(enable)
|
||||
}
|
||||
|
||||
override fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setWidgetAllowed(stateEventId, allowed, callback)
|
||||
override suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean) {
|
||||
integrationManager.setWidgetAllowed(stateEventId, allowed)
|
||||
}
|
||||
|
||||
override fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||
return integrationManager.isWidgetAllowed(stateEventId)
|
||||
}
|
||||
|
||||
override fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed, callback)
|
||||
override suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean) {
|
||||
integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed)
|
||||
}
|
||||
|
||||
override fun isNativeWidgetDomainAllowed(widgetType: String, domain: String): Boolean {
|
||||
|
|
|
@ -20,15 +20,12 @@ import androidx.lifecycle.Lifecycle
|
|||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.api.util.NoOpCancellable
|
||||
import org.matrix.android.sdk.internal.database.model.WellknownIntegrationManagerConfigEntity
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.extensions.observeNotNull
|
||||
|
@ -41,7 +38,6 @@ import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccoun
|
|||
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
||||
import org.matrix.android.sdk.internal.session.widgets.helper.extractWidgetSequence
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -137,22 +133,17 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
return integrationProvisioningContent?.enabled ?: false
|
||||
}
|
||||
|
||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||
val isIntegrationEnabled = isIntegrationEnabled()
|
||||
if (enable == isIntegrationEnabled) {
|
||||
callback.onSuccess(Unit)
|
||||
return NoOpCancellable
|
||||
return
|
||||
}
|
||||
val integrationProvisioningContent = IntegrationProvisioningContent(enabled = enable)
|
||||
val params = UpdateUserAccountDataTask.IntegrationProvisioning(integrationProvisioningContent = integrationProvisioningContent)
|
||||
return updateUserAccountDataTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
return updateUserAccountDataTask.execute(params)
|
||||
}
|
||||
|
||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean) {
|
||||
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||
val newContent = if (currentContent == null) {
|
||||
|
@ -165,11 +156,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
currentContent.copy(widgets = allowedWidgets)
|
||||
}
|
||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||
return updateUserAccountDataTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
return updateUserAccountDataTask.execute(params)
|
||||
}
|
||||
|
||||
fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||
|
@ -178,7 +165,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
return currentContent?.widgets?.get(stateEventId) ?: false
|
||||
}
|
||||
|
||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean) {
|
||||
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||
val newContent = if (currentContent == null) {
|
||||
|
@ -195,11 +182,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
currentContent.copy(native = nativeAllowedWidgets)
|
||||
}
|
||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||
return updateUserAccountDataTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
return updateUserAccountDataTask.execute(params)
|
||||
}
|
||||
|
||||
fun isNativeWidgetDomainAllowed(widgetType: String, domain: String?): Boolean {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.matrix.android.sdk.internal.session.notification
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.pushrules.PushRuleService
|
||||
import org.matrix.android.sdk.api.pushrules.RuleKind
|
||||
import org.matrix.android.sdk.api.pushrules.RuleSetKey
|
||||
|
@ -24,7 +23,6 @@ import org.matrix.android.sdk.api.pushrules.getActions
|
|||
import org.matrix.android.sdk.api.pushrules.rest.PushRule
|
||||
import org.matrix.android.sdk.api.pushrules.rest.RuleSet
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper
|
||||
import org.matrix.android.sdk.internal.database.model.PushRulesEntity
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
|
@ -103,37 +101,21 @@ internal class DefaultPushRuleService @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
override suspend fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean) {
|
||||
// The rules will be updated, and will come back from the next sync response
|
||||
return updatePushRuleEnableStatusTask
|
||||
.configureWith(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled)) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
updatePushRuleEnableStatusTask.execute(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled))
|
||||
}
|
||||
|
||||
override fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return addPushRuleTask
|
||||
.configureWith(AddPushRuleTask.Params(kind, pushRule)) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
override suspend fun addPushRule(kind: RuleKind, pushRule: PushRule) {
|
||||
addPushRuleTask.execute(AddPushRuleTask.Params(kind, pushRule))
|
||||
}
|
||||
|
||||
override fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return updatePushRuleActionsTask
|
||||
.configureWith(UpdatePushRuleActionsTask.Params(kind, oldPushRule, newPushRule)) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
override suspend fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule) {
|
||||
updatePushRuleActionsTask.execute(UpdatePushRuleActionsTask.Params(kind, oldPushRule, newPushRule))
|
||||
}
|
||||
|
||||
override fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return removePushRuleTask
|
||||
.configureWith(RemovePushRuleTask.Params(kind, pushRule)) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
override suspend fun removePushRule(kind: RuleKind, pushRule: PushRule) {
|
||||
removePushRuleTask.execute(RemovePushRuleTask.Params(kind, pushRule))
|
||||
}
|
||||
|
||||
override fun removePushRuleListener(listener: PushRuleService.PushRuleListener) {
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.matrix.android.sdk.internal.database.model.PendingThreePidEntity
|
|||
import org.matrix.android.sdk.internal.database.model.UserThreePidEntity
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.session.content.FileUploader
|
||||
import org.matrix.android.sdk.internal.session.user.UserStore
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import org.matrix.android.sdk.internal.task.launchToCallback
|
||||
|
@ -49,6 +50,7 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
|
|||
private val finalizeAddingThreePidTask: FinalizeAddingThreePidTask,
|
||||
private val deleteThreePidTask: DeleteThreePidTask,
|
||||
private val pendingThreePidMapper: PendingThreePidMapper,
|
||||
private val userStore: UserStore,
|
||||
private val fileUploader: FileUploader) : ProfileService {
|
||||
|
||||
override fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable {
|
||||
|
@ -70,17 +72,17 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
|
|||
}
|
||||
|
||||
override fun setDisplayName(userId: String, newDisplayName: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
|
||||
return setDisplayNameTask
|
||||
.configureWith(SetDisplayNameTask.Params(userId = userId, newDisplayName = newDisplayName)) {
|
||||
callback = matrixCallback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.io, matrixCallback) {
|
||||
setDisplayNameTask.execute(SetDisplayNameTask.Params(userId = userId, newDisplayName = newDisplayName))
|
||||
userStore.updateDisplayName(userId, newDisplayName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
|
||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, matrixCallback) {
|
||||
val response = fileUploader.uploadFromUri(newAvatarUri, fileName, "image/jpeg")
|
||||
setAvatarUrlTask.execute(SetAvatarUrlTask.Params(userId = userId, newAvatarUrl = response.contentUri))
|
||||
userStore.updateAvatar(userId, response.contentUri)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.MatrixCallback
|
|||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
@ -58,6 +59,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||
private val roomCallService: RoomCallService,
|
||||
private val readService: ReadService,
|
||||
private val typingService: TypingService,
|
||||
private val aliasService: AliasService,
|
||||
private val tagsService: TagsService,
|
||||
private val cryptoService: CryptoService,
|
||||
private val relationService: RelationService,
|
||||
|
@ -76,6 +78,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||
RoomCallService by roomCallService,
|
||||
ReadService by readService,
|
||||
TypingService by typingService,
|
||||
AliasService by aliasService,
|
||||
TagsService by tagsService,
|
||||
RelationService by relationService,
|
||||
MembershipService by roomMembersService,
|
||||
|
@ -101,13 +104,13 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||
return cryptoService.shouldEncryptForInvitedMembers(roomId)
|
||||
}
|
||||
|
||||
override fun enableEncryption(algorithm: String, callback: MatrixCallback<Unit>) {
|
||||
override suspend fun enableEncryption(algorithm: String) {
|
||||
when {
|
||||
isEncrypted() -> {
|
||||
callback.onFailure(IllegalStateException("Encryption is already enabled for this room"))
|
||||
throw IllegalStateException("Encryption is already enabled for this room")
|
||||
}
|
||||
algorithm != MXCRYPTO_ALGORITHM_MEGOLM -> {
|
||||
callback.onFailure(InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported"))
|
||||
throw InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported")
|
||||
}
|
||||
else -> {
|
||||
val params = SendStateTask.Params(
|
||||
|
@ -118,11 +121,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||
"algorithm" to algorithm
|
||||
))
|
||||
|
||||
sendStateTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
sendStateTask.execute(params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,19 +18,25 @@ package org.matrix.android.sdk.internal.session.room
|
|||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.GetRoomDirectoryVisibilityTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.GetThirdPartyProtocolsTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask,
|
||||
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
||||
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
||||
internal class DefaultRoomDirectoryService @Inject constructor(
|
||||
private val getPublicRoomTask: GetPublicRoomTask,
|
||||
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
||||
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
|
||||
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask,
|
||||
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
||||
|
||||
override fun getPublicRooms(server: String?,
|
||||
publicRoomsParams: PublicRoomsParams,
|
||||
|
@ -49,4 +55,12 @@ internal class DefaultRoomDirectoryService @Inject constructor(private val getPu
|
|||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility {
|
||||
return getRoomDirectoryVisibilityTask.execute(GetRoomDirectoryVisibilityTask.Params(roomId))
|
||||
}
|
||||
|
||||
override suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility) {
|
||||
setRoomDirectoryVisibilityTask.execute(SetRoomDirectoryVisibilityTask.Params(roomId, roomDirectoryVisibility))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,32 +17,44 @@
|
|||
package org.matrix.android.sdk.internal.session.room
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.api.session.room.RoomService
|
||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.api.util.toOptional
|
||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
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.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
|
||||
import org.matrix.android.sdk.internal.session.room.membership.joining.JoinRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateBreadcrumbsTask
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import org.matrix.android.sdk.internal.util.fetchCopied
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultRoomService @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val createRoomTask: CreateRoomTask,
|
||||
private val joinRoomTask: JoinRoomTask,
|
||||
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
|
||||
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
||||
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
||||
private val deleteRoomAliasTask: DeleteRoomAliasTask,
|
||||
private val roomGetter: RoomGetter,
|
||||
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
||||
|
@ -115,7 +127,31 @@ internal class DefaultRoomService @Inject constructor(
|
|||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override suspend fun deleteRoomAlias(roomAlias: String) {
|
||||
deleteRoomAliasTask.execute(DeleteRoomAliasTask.Params(roomAlias))
|
||||
}
|
||||
|
||||
override fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> {
|
||||
return roomChangeMembershipStateDataSource.getLiveStates()
|
||||
}
|
||||
|
||||
override fun getRoomMember(userId: String, roomId: String): RoomMemberSummary? {
|
||||
val roomMemberEntity = monarchy.fetchCopied {
|
||||
RoomMemberHelper(it, roomId).getLastRoomMember(userId)
|
||||
}
|
||||
return roomMemberEntity?.asDomain()
|
||||
}
|
||||
|
||||
override fun getRoomMemberLive(userId: String, roomId: String): LiveData<Optional<RoomMemberSummary>> {
|
||||
val liveData = monarchy.findAllMappedWithChanges(
|
||||
{ realm ->
|
||||
RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
|
||||
.equalTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||
},
|
||||
{ it.asDomain() }
|
||||
)
|
||||
return Transformations.map(liveData) { results ->
|
||||
results.firstOrNull().toOptional()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue