mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-29 14:38:45 +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>ssss</w>
|
||||||
<w>sygnal</w>
|
<w>sygnal</w>
|
||||||
<w>threepid</w>
|
<w>threepid</w>
|
||||||
|
<w>unpublish</w>
|
||||||
<w>unwedging</w>
|
<w>unwedging</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
15
AUTHORS.md
15
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.
|
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)
|
[@benoit.marty:matrix.org](https://matrix.to/#/@benoit.marty:matrix.org)
|
||||||
- Android team leader and project leader, Android developer, GitHub community manager.
|
- 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.
|
- Reviewing and polishing developed features, code quality manager, PRs reviewer, GitHub community manager.
|
||||||
- Release manager on the Play Store
|
- 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)
|
[@ganfra:matrix.org](https://matrix.to/#/@ganfra:matrix.org)
|
||||||
- Software architect, Android developer
|
- 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.
|
- Work mainly on the global architecture of the project.
|
||||||
- Specialist of the timeline, and lots of other features.
|
- 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)
|
[@valere35:matrix.org](https://matrix.to/#/@valere35:matrix.org)
|
||||||
- Product manager, Android developer
|
- Product manager, Android developer
|
||||||
- Specialist on the crypto implementation.
|
- 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
|
# 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.
|
First of all, we thank all contributors who use Element and report problems on this GitHub project or via the integrated rageshake function.
|
||||||
|
@ -35,6 +40,6 @@ 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!
|
Feel free to add your name below, when you contribute to the project!
|
||||||
|
|
||||||
Name | Matrix ID | GitHub
|
Name | Matrix ID | GitHub
|
||||||
--------|---------------------|--------------------------------------
|
----------|-----------------------------|--------------------------------------
|
||||||
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
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 ✨:
|
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 🙌:
|
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 🐛:
|
Bugfix 🐛:
|
||||||
- Fix issue when updating the avatar of a room (new avatar vanishing)
|
- Double bottomsheet effect after verify with passphrase
|
||||||
- Discard change dialog displayed by mistake when avatar has been updated
|
- EditText cursor jumps to the start while typing fast (#2469)
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
||||||
SDK API changes ⚠️:
|
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 🧱:
|
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:
|
Other changes:
|
||||||
- Upgrade Realm dependency to 10.0.0
|
- Upgrade Realm dependency to 10.0.0
|
||||||
|
|
||||||
|
@ -1033,5 +1081,8 @@ SDK API changes ⚠️:
|
||||||
Build 🧱:
|
Build 🧱:
|
||||||
-
|
-
|
||||||
|
|
||||||
|
Test:
|
||||||
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
-
|
||||||
|
|
|
@ -66,7 +66,6 @@ dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
// Ref: https://kotlinlang.org/releases.html
|
// Ref: https://kotlinlang.org/releases.html
|
||||||
ext.kotlin_version = '1.4.10'
|
ext.kotlin_version = '1.4.20'
|
||||||
ext.kotlin_coroutines_version = "1.3.9"
|
ext.kotlin_coroutines_version = "1.4.1"
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
@ -12,7 +12,7 @@ buildscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
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 'com.google.gms:google-services:4.3.4'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
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:
|
Element es un nuevo tipo de aplicación de mensajería y colaboración que:
|
||||||
|
|
||||||
1. Le da el control para preservar su privacidad
|
1. Te 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.
|
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.
|
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
|
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 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 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
|
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. Autohospede su cuenta ejecutando un servidor en su propio hardware
|
2. Autohospeda tu cuenta con un servidor en tu 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
|
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>¿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
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=0080de8491f0918e4f529a6db6820fa0b9e818ee2386117f4394f95feb1d5583
|
distributionSha256Sum=22449f5231796abd892c98b2a07c9ceebe4688d192cd2d6763f8e3bf8acbedeb
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -36,9 +36,9 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":matrix-sdk-android")
|
implementation project(":matrix-sdk-android")
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
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:rxkotlin:2.3.0'
|
||||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||||
|
|
||||||
// Paging
|
// Paging
|
||||||
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
|
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.Completable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
|
||||||
fun <T> singleBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Single<T> = Single.create {
|
fun <T> singleBuilder(builder: (MatrixCallback<T>) -> Cancelable): Single<T> = Single.create { emitter ->
|
||||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
val callback = object : MatrixCallback<T> {
|
||||||
override fun onSuccess(data: 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) {
|
override fun onFailure(failure: Throwable) {
|
||||||
it.tryOnError(failure)
|
emitter.tryOnError(failure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val cancelable = builder(callback)
|
val cancelable = builder(callback)
|
||||||
it.setCancellable {
|
emitter.setCancellable {
|
||||||
cancelable.cancel()
|
cancelable.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> completableBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Completable = Completable.create {
|
fun <T> completableBuilder(builder: (MatrixCallback<T>) -> Cancelable): Completable = Completable.create { emitter ->
|
||||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
val callback = object : MatrixCallback<T> {
|
||||||
override fun onSuccess(data: T) {
|
override fun onSuccess(data: T) {
|
||||||
it.onComplete()
|
emitter.onComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
override fun onFailure(failure: Throwable) {
|
||||||
it.tryOnError(failure)
|
emitter.tryOnError(failure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val cancelable = builder(callback)
|
val cancelable = builder(callback)
|
||||||
it.setCancellable {
|
emitter.setCancellable {
|
||||||
cancelable.cancel()
|
cancelable.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ import org.matrix.android.sdk.api.util.toOptional
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
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) {
|
class RxRoom(private val room: Room) {
|
||||||
|
|
||||||
|
@ -127,18 +129,14 @@ class RxRoom(private val room: Room) {
|
||||||
room.updateName(name, it)
|
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> {
|
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = completableBuilder<Unit> {
|
||||||
room.updateHistoryReadability(readability, it)
|
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> {
|
fun updateAvatar(avatarUri: Uri, fileName: String): Completable = completableBuilder<Unit> {
|
||||||
room.updateAvatar(avatarUri, fileName, it)
|
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.pushers.Pusher
|
||||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
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.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.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
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>> {
|
fun liveUsers(): Observable<List<User>> {
|
||||||
return session.getUsersLive().asObservable()
|
return session.getUsersLive().asObservable()
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,6 @@ dependencies {
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
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.core:core-ktx:1.3.2"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
|
@ -146,7 +145,7 @@ dependencies {
|
||||||
implementation "ru.noties.markwon:core:$markwon_version"
|
implementation "ru.noties.markwon:core:$markwon_version"
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
implementation 'androidx.exifinterface:exifinterface:1.3.0'
|
implementation 'androidx.exifinterface:exifinterface:1.3.1'
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
|
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
|
||||||
|
|
|
@ -68,8 +68,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
||||||
if (encryptedRoom) {
|
if (encryptedRoom) {
|
||||||
val room = aliceSession.getRoom(roomId)!!
|
val room = aliceSession.getRoom(roomId)!!
|
||||||
|
|
||||||
mTestHelper.doSync<Unit> {
|
mTestHelper.runBlockingTest {
|
||||||
room.enableEncryption(callback = it)
|
room.enableEncryption()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ class SearchMessagesTest : InstrumentedTest {
|
||||||
commonTestHelper.await(lock)
|
commonTestHelper.await(lock)
|
||||||
|
|
||||||
lock = CountDownLatch(1)
|
lock = CountDownLatch(1)
|
||||||
|
val data = commonTestHelper.runBlockingTest {
|
||||||
aliceSession
|
aliceSession
|
||||||
.searchService()
|
.searchService()
|
||||||
.search(
|
.search(
|
||||||
|
@ -81,10 +82,9 @@ class SearchMessagesTest : InstrumentedTest {
|
||||||
beforeLimit = 10,
|
beforeLimit = 10,
|
||||||
orderByRecent = true,
|
orderByRecent = true,
|
||||||
nextBatch = null,
|
nextBatch = null,
|
||||||
roomId = aliceRoomId,
|
roomId = aliceRoomId
|
||||||
callback = object : MatrixCallback<SearchResult> {
|
)
|
||||||
override fun onSuccess(data: SearchResult) {
|
}
|
||||||
super.onSuccess(data)
|
|
||||||
assertTrue(data.results?.size == 2)
|
assertTrue(data.results?.size == 2)
|
||||||
assertTrue(
|
assertTrue(
|
||||||
data.results
|
data.results
|
||||||
|
@ -92,17 +92,6 @@ class SearchMessagesTest : InstrumentedTest {
|
||||||
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
||||||
}.orFalse()
|
}.orFalse()
|
||||||
)
|
)
|
||||||
lock.countDown()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
|
||||||
super.onFailure(failure)
|
|
||||||
fail(failure.localizedMessage)
|
|
||||||
lock.countDown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
lock.await(TestConstants.timeOutMillis, TimeUnit.MILLISECONDS)
|
|
||||||
|
|
||||||
aliceTimeline.removeAllListeners()
|
aliceTimeline.removeAllListeners()
|
||||||
cryptoTestData.cleanUp(commonTestHelper)
|
cryptoTestData.cleanUp(commonTestHelper)
|
||||||
|
|
|
@ -66,9 +66,9 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logJson(formattedJson: String) {
|
private fun logJson(formattedJson: String) {
|
||||||
val arr = formattedJson.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
formattedJson
|
||||||
for (s in arr) {
|
.lines()
|
||||||
Timber.v(s)
|
.dropLastWhile { it.isEmpty() }
|
||||||
}
|
.forEach { Timber.v(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ interface LoginWizard {
|
||||||
* @param password the password field
|
* @param password the password field
|
||||||
* @param deviceName the initial device name
|
* @param deviceName the initial device name
|
||||||
* @param callback the matrix callback on which you'll receive the result of authentication.
|
* @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,
|
fun login(login: String,
|
||||||
password: String,
|
password: String,
|
||||||
|
|
|
@ -22,3 +22,8 @@ fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
|
||||||
else -> "$prefix$this"
|
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
|
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.PushRule
|
||||||
import org.matrix.android.sdk.api.pushrules.rest.RuleSet
|
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.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
interface PushRuleService {
|
interface PushRuleService {
|
||||||
/**
|
/**
|
||||||
|
@ -29,13 +27,13 @@ interface PushRuleService {
|
||||||
|
|
||||||
fun getPushRules(scope: String = RuleScope.GLOBAL): RuleSet
|
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)
|
fun addPushRuleListener(listener: PushRuleListener)
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.raw
|
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
|
* 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
|
* Get a URL, either from cache or from the remote server, depending on the cache strategy
|
||||||
*/
|
*/
|
||||||
fun getUrl(url: String,
|
suspend fun getUrl(url: String, rawCacheStrategy: RawCacheStrategy): String
|
||||||
rawCacheStrategy: RawCacheStrategy,
|
|
||||||
matrixCallback: MatrixCallback<String>): Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific case for the well-known file. Cache validity is 8 hours
|
* 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
|
* 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_JOIN_RULES = "m.room.join_rules"
|
||||||
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
||||||
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
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_ALIASES = "m.room.aliases"
|
||||||
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
||||||
const val STATE_ROOM_CANONICAL_ALIAS = "m.room.canonical_alias"
|
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_RELATED_GROUPS = "m.room.related_groups"
|
||||||
const val STATE_ROOM_PINNED_EVENT = "m.room.pinned_events"
|
const val STATE_ROOM_PINNED_EVENT = "m.room.pinned_events"
|
||||||
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
|
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
|
||||||
|
const val STATE_ROOM_SERVER_ACL = "m.room.server_acl"
|
||||||
|
|
||||||
// Call Events
|
// Call Events
|
||||||
const val CALL_INVITE = "m.call.invite"
|
const val CALL_INVITE = "m.call.invite"
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.session.group
|
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.
|
* 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.
|
* 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.
|
* 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.
|
* @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
|
* 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
|
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
|
* Get the status of the current user's threePid
|
||||||
* A lookup will be performed, but also pending binding state will be restored
|
* 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 NoIdentityServerConfigured : IdentityServiceError()
|
||||||
object TermsNotSignedException : IdentityServiceError()
|
object TermsNotSignedException : IdentityServiceError()
|
||||||
object BulkLookupSha256NotSupported : IdentityServiceError()
|
object BulkLookupSha256NotSupported : IdentityServiceError()
|
||||||
|
object UserConsentNotProvided : IdentityServiceError()
|
||||||
object BindingError : IdentityServiceError()
|
object BindingError : IdentityServiceError()
|
||||||
object NoCurrentBindingError : IdentityServiceError()
|
object NoCurrentBindingError : IdentityServiceError()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.session.integrationmanager
|
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.
|
* 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.
|
* Offers to enable or disable the integration.
|
||||||
* @param enable the param to change
|
* @param enable the param to change
|
||||||
* @param callback the matrix callback to listen for result.
|
|
||||||
* @return Cancelable
|
* @return Cancelable
|
||||||
*/
|
*/
|
||||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun setIntegrationEnabled(enable: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offers to allow or disallow a widget.
|
* Offers to allow or disallow a widget.
|
||||||
* @param stateEventId the eventId of the state event defining the widget.
|
* @param stateEventId the eventId of the state event defining the widget.
|
||||||
* @param allowed the param to change
|
* @param allowed the param to change
|
||||||
* @param callback the matrix callback to listen for result.
|
|
||||||
* @return Cancelable
|
* @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.
|
* Returns true if the widget is allowed, false otherwise.
|
||||||
|
@ -105,7 +100,7 @@ interface IntegrationManagerService {
|
||||||
* @param widgetType the widget type to check for
|
* @param widgetType the widget type to check for
|
||||||
* @param domain the domain 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.
|
* Returns true if the widget domain is allowed, false otherwise.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.matrix.android.sdk.api.session.permalinks
|
package org.matrix.android.sdk.api.session.permalinks
|
||||||
|
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
|
import org.matrix.android.sdk.api.MatrixPatterns
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MatrixLinkify take a piece of text and turns all of the
|
* 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:
|
* 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
|
* The url is not correct. Ex: for @user:matrix.org, the url will be @user:matrix.org, instead of a matrix.to
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
if (spannable.isEmpty()) {
|
if (spannable.isEmpty()) {
|
||||||
return false
|
return false
|
||||||
|
@ -48,14 +49,21 @@ object MatrixLinkify {
|
||||||
val startPos = match.range.first
|
val startPos = match.range.first
|
||||||
if (startPos == 0 || text[startPos - 1] != '/') {
|
if (startPos == 0 || text[startPos - 1] != '/') {
|
||||||
val endPos = match.range.last + 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)
|
val span = MatrixPermalinkSpan(url, callback)
|
||||||
spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hasMatch
|
return hasMatch
|
||||||
*/
|
|
||||||
return false
|
// return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,13 +44,12 @@ object PermalinkParser {
|
||||||
if (fragment.isNullOrEmpty()) {
|
if (fragment.isNullOrEmpty()) {
|
||||||
return PermalinkData.FallbackLink(uri)
|
return PermalinkData.FallbackLink(uri)
|
||||||
}
|
}
|
||||||
val indexOfQuery = fragment.indexOf("?")
|
val safeFragment = fragment.substringBefore('?')
|
||||||
val safeFragment = if (indexOfQuery != -1) fragment.substring(0, indexOfQuery) else fragment
|
|
||||||
val viaQueryParameters = fragment.getViaParameters()
|
val viaQueryParameters = fragment.getViaParameters()
|
||||||
|
|
||||||
// we are limiting to 2 params
|
// we are limiting to 2 params
|
||||||
val params = safeFragment
|
val params = safeFragment
|
||||||
.split(MatrixPatterns.SEP_REGEX.toRegex())
|
.split(MatrixPatterns.SEP_REGEX)
|
||||||
.filter { it.isNotEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
.take(2)
|
.take(2)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
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.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
|
@ -46,6 +47,7 @@ interface Room :
|
||||||
DraftService,
|
DraftService,
|
||||||
ReadService,
|
ReadService,
|
||||||
TypingService,
|
TypingService,
|
||||||
|
AliasService,
|
||||||
TagsService,
|
TagsService,
|
||||||
MembershipService,
|
MembershipService,
|
||||||
StateService,
|
StateService,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.matrix.android.sdk.api.session.room
|
package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
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.PublicRoomsParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
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.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.
|
* Includes both the available protocols and all fields required for queries against each protocol.
|
||||||
*/
|
*/
|
||||||
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
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 androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
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.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.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
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.Cancelable
|
||||||
|
@ -121,6 +122,11 @@ interface RoomService {
|
||||||
searchOnServer: Boolean,
|
searchOnServer: Boolean,
|
||||||
callback: MatrixCallback<Optional<String>>): Cancelable
|
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.
|
* 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.
|
* 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
|
* - 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?
|
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
|
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
|
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||||
|
|
||||||
interface RoomCryptoService {
|
interface RoomCryptoService {
|
||||||
|
@ -30,6 +29,5 @@ interface RoomCryptoService {
|
||||||
/**
|
/**
|
||||||
* Enable encryption of the room
|
* Enable encryption of the room
|
||||||
*/
|
*/
|
||||||
fun enableEncryption(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM,
|
suspend fun enableEncryption(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM)
|
||||||
callback: MatrixCallback<Unit>)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.Failure
|
||||||
import org.matrix.android.sdk.api.failure.MatrixError
|
import org.matrix.android.sdk.api.failure.MatrixError
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
|
||||||
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
||||||
object CreatedWithTimeout : CreateRoomFailure()
|
object CreatedWithTimeout : CreateRoomFailure()
|
||||||
data class CreatedWithFederationFailure(val matrixError: MatrixError) : 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
|
* 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)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomAliasesContent(
|
data class RoomAliasesContent(
|
||||||
|
|
|
@ -24,5 +24,14 @@ import com.squareup.moshi.JsonClass
|
||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomCanonicalAliasContent(
|
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.
|
* The server will clobber the following keys: creator.
|
||||||
* Future versions of the specification may allow the server to clobber other keys.
|
* 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
|
* The power level content to override in the default power level event
|
||||||
|
@ -120,4 +135,8 @@ class CreateRoomParams {
|
||||||
fun enableEncryption() {
|
fun enableEncryption() {
|
||||||
algorithm = MXCRYPTO_ALGORITHM_MEGOLM
|
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
|
package org.matrix.android.sdk.api.session.room.notification
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
interface RoomPushRuleService {
|
interface RoomPushRuleService {
|
||||||
|
|
||||||
fun getLiveRoomNotificationState(): LiveData<RoomNotificationState>
|
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
|
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.
|
* This interface defines methods to report content of an event.
|
||||||
*/
|
*/
|
||||||
|
@ -28,5 +25,5 @@ interface ReportingService {
|
||||||
* Report content
|
* Report content
|
||||||
* Ref: https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-rooms-roomid-report-eventid
|
* 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
|
package org.matrix.android.sdk.api.session.room.send
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
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
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
|
||||||
interface DraftService {
|
interface DraftService {
|
||||||
|
@ -26,12 +24,12 @@ interface DraftService {
|
||||||
/**
|
/**
|
||||||
* Save or update a draft to the room
|
* 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
|
* 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
|
* 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.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.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.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.Cancelable
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
@ -38,21 +40,23 @@ interface StateService {
|
||||||
*/
|
*/
|
||||||
fun updateName(name: String, callback: MatrixCallback<Unit>): Cancelable
|
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
|
* 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
|
* Update the history readability of the room
|
||||||
*/
|
*/
|
||||||
fun updateHistoryReadability(readability: RoomHistoryVisibility, callback: MatrixCallback<Unit>): Cancelable
|
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
|
* Update the avatar of the room
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.session.room.tags
|
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.
|
* 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
|
* 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
|
* 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
|
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.
|
* 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 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
|
* @param since token to get next page, or null to get the first page
|
||||||
*/
|
*/
|
||||||
fun getUploads(numberOfEvents: Int,
|
suspend fun getUploads(numberOfEvents: Int, since: String?): GetUploadsResult
|
||||||
since: String?,
|
|
||||||
callback: MatrixCallback<GetUploadsResult>): Cancelable
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.session.search
|
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.
|
* 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 beforeLimit how many events before the result are returned.
|
||||||
* @param afterLimit how many events after 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 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,
|
suspend fun search(searchTerm: String,
|
||||||
roomId: String,
|
roomId: String,
|
||||||
nextBatch: String?,
|
nextBatch: String?,
|
||||||
orderByRecent: Boolean,
|
orderByRecent: Boolean,
|
||||||
limit: Int,
|
limit: Int,
|
||||||
beforeLimit: Int,
|
beforeLimit: Int,
|
||||||
afterLimit: Int,
|
afterLimit: Int,
|
||||||
includeProfile: Boolean,
|
includeProfile: Boolean): SearchResult
|
||||||
callback: MatrixCallback<SearchResult>): Cancelable
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,22 +16,16 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.session.terms
|
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 {
|
interface TermsService {
|
||||||
enum class ServiceType {
|
enum class ServiceType {
|
||||||
IntegrationManager,
|
IntegrationManager,
|
||||||
IdentityService
|
IdentityService
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTerms(serviceType: ServiceType,
|
suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse
|
||||||
baseUrl: String,
|
|
||||||
callback: MatrixCallback<GetTermsResponse>): Cancelable
|
|
||||||
|
|
||||||
fun agreeToTerms(serviceType: ServiceType,
|
suspend fun agreeToTerms(serviceType: ServiceType,
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
agreedUrls: List<String>,
|
agreedUrls: List<String>,
|
||||||
token: String?,
|
token: String?)
|
||||||
callback: MatrixCallback<Unit>): Cancelable
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,11 @@ interface UserService {
|
||||||
*/
|
*/
|
||||||
fun getUser(userId: String): User?
|
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.
|
* Search list of users on server directory.
|
||||||
* @param search the searched term
|
* @param search the searched term
|
||||||
|
|
|
@ -767,9 +767,9 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
*/
|
*/
|
||||||
private fun onRoomKeyEvent(event: Event) {
|
private fun onRoomKeyEvent(event: Event) {
|
||||||
val roomKeyContent = event.getClearContent().toModel<RoomKeyContent>() ?: return
|
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()) {
|
if (roomKeyContent.roomId.isNullOrEmpty() || roomKeyContent.algorithm.isNullOrEmpty()) {
|
||||||
Timber.e("## CRYPTO | GOSSIP onRoomKeyEvent() : missing fields")
|
Timber.e("## CRYPTO | onRoomKeyEvent() : missing fields")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(roomKeyContent.roomId, roomKeyContent.algorithm)
|
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(roomKeyContent.roomId, roomKeyContent.algorithm)
|
||||||
|
@ -782,20 +782,20 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
|
|
||||||
private fun onKeyWithHeldReceived(event: Event) {
|
private fun onKeyWithHeldReceived(event: Event) {
|
||||||
val withHeldContent = event.getClearContent().toModel<RoomKeyWithHeldContent>() ?: return Unit.also {
|
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)
|
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(withHeldContent.roomId, withHeldContent.algorithm)
|
||||||
if (alg is IMXWithHeldExtension) {
|
if (alg is IMXWithHeldExtension) {
|
||||||
alg.onRoomKeyWithHeldEvent(withHeldContent)
|
alg.onRoomKeyWithHeldEvent(withHeldContent)
|
||||||
} else {
|
} 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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onSecretSendReceived(event: Event) {
|
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()) {
|
if (!event.isEncrypted()) {
|
||||||
// secret send messages must be encrypted
|
// secret send messages must be encrypted
|
||||||
Timber.e("## CRYPTO | GOSSIP onSecretSend() :Received unencrypted secret send event")
|
Timber.e("## CRYPTO | GOSSIP onSecretSend() :Received unencrypted secret send event")
|
||||||
|
|
|
@ -119,7 +119,7 @@ internal class EventDecryptor @Inject constructor(
|
||||||
markOlmSessionForUnwedging(event.senderId ?: "", it)
|
markOlmSessionForUnwedging(event.senderId ?: "", it)
|
||||||
}
|
}
|
||||||
?: run {
|
?: 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 lastForcedDate = lastNewSessionForcedDates.getObject(senderId, deviceKey) ?: 0
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (now - lastForcedDate < DefaultCryptoService.CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.d("## CRYPTO | markOlmSessionForUnwedging from $senderId:${deviceInfo.deviceId}")
|
Timber.i("## CRYPTO | markOlmSessionForUnwedging from $senderId:${deviceInfo.deviceId}")
|
||||||
lastNewSessionForcedDates.setObject(senderId, deviceKey, now)
|
lastNewSessionForcedDates.setObject(senderId, deviceKey, now)
|
||||||
|
|
||||||
// offload this from crypto thread (?)
|
// offload this from crypto thread (?)
|
||||||
cryptoCoroutineScope.launch(coroutineDispatchers.computation) {
|
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.
|
// 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)
|
// (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 encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo))
|
||||||
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
||||||
sendToDeviceMap.setObject(senderId, deviceInfo.deviceId, encodedPayload)
|
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) {
|
withContext(coroutineDispatchers.io) {
|
||||||
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
|
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
|
||||||
|
try {
|
||||||
sendToDeviceTask.execute(sendToDeviceParams)
|
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 cryptoCoroutineScope: CoroutineScope) {
|
||||||
|
|
||||||
private val executor = Executors.newSingleThreadExecutor()
|
private val executor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
// list of IncomingRoomKeyRequests/IncomingRoomKeyRequestCancellations
|
// list of IncomingRoomKeyRequests/IncomingRoomKeyRequestCancellations
|
||||||
// we received in the current sync.
|
// we received in the current sync.
|
||||||
private val receivedGossipingRequests = ArrayList<IncomingShareRequestCommon>()
|
private val receivedGossipingRequests = ArrayList<IncomingShareRequestCommon>()
|
||||||
|
@ -103,8 +104,8 @@ internal class IncomingGossipingRequestManager @Inject constructor(
|
||||||
* @param event the announcement event.
|
* @param event the announcement event.
|
||||||
*/
|
*/
|
||||||
fun onGossipingRequestEvent(event: Event) {
|
fun onGossipingRequestEvent(event: Event) {
|
||||||
Timber.v("## CRYPTO | GOSSIP onGossipingRequestEvent type ${event.type} from user ${event.senderId}")
|
|
||||||
val roomKeyShare = event.getClearContent().toModel<GossipingDefaultContent>()
|
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 }
|
// val ageLocalTs = event.unsignedData?.age?.let { System.currentTimeMillis() - it }
|
||||||
when (roomKeyShare?.action) {
|
when (roomKeyShare?.action) {
|
||||||
GossipingToDeviceObject.ACTION_SHARE_REQUEST -> {
|
GossipingToDeviceObject.ACTION_SHARE_REQUEST -> {
|
||||||
|
|
|
@ -760,7 +760,7 @@ internal class MXOlmDevice @Inject constructor(
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
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,
|
requestId = params.requestId,
|
||||||
state = GossipingRequestState.FAILED_TO_ACCEPTED
|
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.
|
// 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 claimParams = ClaimOneTimeKeysForUsersDeviceTask.Params(usersDevicesToClaim)
|
||||||
val oneTimeKeys = oneTimeKeysForUsersDeviceTask.execute(claimParams)
|
val oneTimeKeys = oneTimeKeysForUsersDeviceTask.execute(claimParams)
|
||||||
|
@ -90,7 +90,7 @@ internal class EnsureOlmSessionsForDevicesAction @Inject constructor(
|
||||||
oneTimeKey = key
|
oneTimeKey = key
|
||||||
}
|
}
|
||||||
if (oneTimeKey == null) {
|
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)
|
+ " for device " + userId + " : " + deviceId)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,8 +243,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
|
if (event.getClearType() == EventType.FORWARDED_ROOM_KEY) {
|
||||||
Timber.v("## CRYPTO | onRoomKeyEvent(), forward adding key : roomId ${roomKeyContent.roomId}" +
|
Timber.i("## CRYPTO | onRoomKeyEvent(), forward adding key : ${roomKeyContent.roomId}|${roomKeyContent.sessionId}")
|
||||||
" sessionId ${roomKeyContent.sessionId} sessionKey ${roomKeyContent.sessionKey}")
|
|
||||||
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>()
|
val forwardedRoomKeyContent = event.getClearContent().toModel<ForwardedRoomKeyContent>()
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
|
@ -273,9 +272,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
||||||
|
|
||||||
keysClaimed["ed25519"] = forwardedRoomKeyContent.senderClaimedEd25519Key
|
keysClaimed["ed25519"] = forwardedRoomKeyContent.senderClaimedEd25519Key
|
||||||
} else {
|
} else {
|
||||||
Timber.v("## CRYPTO | onRoomKeyEvent(), Adding key : roomId " + roomKeyContent.roomId + " sessionId " + roomKeyContent.sessionId
|
Timber.i("## CRYPTO | onRoomKeyEvent(), Adding key : ${roomKeyContent.roomId}|${roomKeyContent.sessionId}")
|
||||||
+ " sessionKey " + roomKeyContent.sessionKey) // from " + event);
|
|
||||||
|
|
||||||
if (null == senderKey) {
|
if (null == senderKey) {
|
||||||
Timber.e("## onRoomKeyEvent() : key event has no sender key (not encrypted?)")
|
Timber.e("## onRoomKeyEvent() : key event has no sender key (not encrypted?)")
|
||||||
return
|
return
|
||||||
|
@ -285,7 +282,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
||||||
keysClaimed = event.getKeysClaimed().toMutableMap()
|
keysClaimed = event.getKeysClaimed().toMutableMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.e("## CRYPTO | onRoomKeyEvent addInboundGroupSession ${roomKeyContent.sessionId}")
|
Timber.i("## CRYPTO | onRoomKeyEvent addInboundGroupSession ${roomKeyContent.sessionId}")
|
||||||
val added = olmDevice.addInboundGroupSession(roomKeyContent.sessionId,
|
val added = olmDevice.addInboundGroupSession(roomKeyContent.sessionId,
|
||||||
roomKeyContent.sessionKey,
|
roomKeyContent.sessionKey,
|
||||||
roomKeyContent.roomId,
|
roomKeyContent.roomId,
|
||||||
|
@ -349,10 +346,10 @@ internal class MXMegolmDecryption(private val userId: String,
|
||||||
if (olmSessionResult?.sessionId == null) {
|
if (olmSessionResult?.sessionId == null) {
|
||||||
// no session with this device, probably because there
|
// no session with this device, probably because there
|
||||||
// were no one-time keys.
|
// were no one-time keys.
|
||||||
|
Timber.e("no session with this device $deviceId, probably because there were no one-time keys.")
|
||||||
return@mapCatching
|
return@mapCatching
|
||||||
}
|
}
|
||||||
Timber.v("## CRYPTO | shareKeysWithDevice() : sharing keys for session" +
|
Timber.i("## CRYPTO | shareKeysWithDevice() : sharing session ${body.sessionId} with device $userId:$deviceId")
|
||||||
" ${body.senderKey}|${body.sessionId} with device $userId:$deviceId")
|
|
||||||
|
|
||||||
val payloadJson = mutableMapOf<String, Any>("type" to EventType.FORWARDED_ROOM_KEY)
|
val payloadJson = mutableMapOf<String, Any>("type" to EventType.FORWARDED_ROOM_KEY)
|
||||||
runCatching { olmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId) }
|
runCatching { olmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId) }
|
||||||
|
@ -363,6 +360,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// TODO
|
// 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 encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo))
|
||||||
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
||||||
sendToDeviceMap.setObject(userId, deviceId, encodedPayload)
|
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)
|
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
|
||||||
|
try {
|
||||||
sendToDeviceTask.execute(sendToDeviceParams)
|
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")
|
Timber.v("## CRYPTO | shareUserDevicesKey() : starts")
|
||||||
|
|
||||||
val results = ensureOlmSessionsForDevicesAction.handle(devicesByUser)
|
val results = ensureOlmSessionsForDevicesAction.handle(devicesByUser)
|
||||||
Timber.v("## CRYPTO | shareUserDevicesKey() : ensureOlmSessionsForDevices succeeds after "
|
Timber.v(
|
||||||
+ (System.currentTimeMillis() - t0) + " ms")
|
"""## CRYPTO | shareUserDevicesKey(): ensureOlmSessionsForDevices succeeds after ${System.currentTimeMillis() - t0} ms"""
|
||||||
|
.trimMargin()
|
||||||
|
)
|
||||||
val contentMap = MXUsersDevicesMap<Any>()
|
val contentMap = MXUsersDevicesMap<Any>()
|
||||||
var haveTargets = false
|
var haveTargets = false
|
||||||
val userIds = results.userIds
|
val userIds = results.userIds
|
||||||
|
@ -242,7 +244,7 @@ internal class MXMegolmEncryption(
|
||||||
|
|
||||||
continue
|
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)))
|
contentMap.setObject(userId, deviceID, messageEncrypter.encryptMessage(payload, listOf(sessionResult.deviceInfo)))
|
||||||
haveTargets = true
|
haveTargets = true
|
||||||
}
|
}
|
||||||
|
@ -270,21 +272,22 @@ internal class MXMegolmEncryption(
|
||||||
|
|
||||||
if (haveTargets) {
|
if (haveTargets) {
|
||||||
t0 = System.currentTimeMillis()
|
t0 = System.currentTimeMillis()
|
||||||
Timber.v("## CRYPTO | shareUserDevicesKey() : has target")
|
Timber.i("## CRYPTO | shareUserDevicesKey() ${session.sessionId} : has target")
|
||||||
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap)
|
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, contentMap)
|
||||||
try {
|
try {
|
||||||
sendToDeviceTask.execute(sendToDeviceParams)
|
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) {
|
} catch (failure: Throwable) {
|
||||||
// What to do here...
|
// What to do here...
|
||||||
Timber.e("## CRYPTO | shareUserDevicesKey() : Failed to share session <${session.sessionId}> with $devicesByUser ")
|
Timber.e("## CRYPTO | shareUserDevicesKey() : Failed to share session <${session.sessionId}> with $devicesByUser ")
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
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(
|
val withHeldContent = RoomKeyWithHeldContent(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
senderKey = senderKey,
|
senderKey = senderKey,
|
||||||
|
@ -393,16 +396,16 @@ internal class MXMegolmEncryption(
|
||||||
userId: String,
|
userId: String,
|
||||||
deviceId: String,
|
deviceId: String,
|
||||||
senderKey: String): Boolean {
|
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
|
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
|
// Get the chain index of the key we previously sent this device
|
||||||
val chainIndex = outboundSession?.sharedWithHelper?.wasSharedWith(userId, deviceId) ?: return false
|
val chainIndex = outboundSession?.sharedWithHelper?.wasSharedWith(userId, deviceId) ?: return false
|
||||||
.also {
|
.also {
|
||||||
// Send a room key with held
|
// Send a room key with held
|
||||||
notifyKeyWithHeld(listOf(UserDevice(userId, deviceId)), sessionId, senderKey, WithHeldCode.UNAUTHORISED)
|
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))
|
val devicesByUser = mapOf(userId to listOf(deviceInfo))
|
||||||
|
@ -411,9 +414,11 @@ internal class MXMegolmEncryption(
|
||||||
olmSessionResult?.sessionId
|
olmSessionResult?.sessionId
|
||||||
?: // no session with this device, probably because there were no one-time keys.
|
?: // no session with this device, probably because there were no one-time keys.
|
||||||
// ensureOlmSessionsForDevicesAction has already done the logging, so just skip it.
|
// 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)
|
val payloadJson = mutableMapOf<String, Any>("type" to EventType.FORWARDED_ROOM_KEY)
|
||||||
|
|
||||||
|
@ -425,6 +430,7 @@ internal class MXMegolmEncryption(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// TODO
|
// 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 encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo))
|
||||||
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
val sendToDeviceMap = MXUsersDevicesMap<Any>()
|
||||||
sendToDeviceMap.setObject(userId, deviceId, encodedPayload)
|
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)
|
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
|
||||||
return try {
|
return try {
|
||||||
sendToDeviceTask.execute(sendToDeviceParams)
|
sendToDeviceTask.execute(sendToDeviceParams)
|
||||||
|
Timber.i("## CRYPTO reshareKey() : successfully send <$sessionId> to $userId:$deviceId")
|
||||||
true
|
true
|
||||||
} catch (failure: Throwable) {
|
} 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
|
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.task.configureWith
|
||||||
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
||||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||||
import org.matrix.android.sdk.internal.util.withoutPrefix
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||||
|
@ -444,7 +443,7 @@ internal class DefaultCrossSigningService @Inject constructor(
|
||||||
} else {
|
} else {
|
||||||
// Maybe it's signed by a locally trusted device?
|
// Maybe it's signed by a locally trusted device?
|
||||||
myMasterKey.signatures?.get(userId)?.forEach { (key, value) ->
|
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)
|
val potentialDevice = myDevices?.firstOrNull { it.deviceId == potentialDeviceId } // cryptoStore.getUserDevice(userId, potentialDeviceId)
|
||||||
if (potentialDevice != null && potentialDevice.isVerified) {
|
if (potentialDevice != null && potentialDevice.isVerified) {
|
||||||
// Check signature validity?
|
// Check signature validity?
|
||||||
|
|
|
@ -241,9 +241,9 @@ internal class UpdateTrustWorker(context: Context,
|
||||||
private fun computeRoomShield(activeMemberUserIds: List<String>, roomSummaryEntity: RoomSummaryEntity): RoomEncryptionTrustLevel {
|
private fun computeRoomShield(activeMemberUserIds: List<String>, roomSummaryEntity: RoomSummaryEntity): RoomEncryptionTrustLevel {
|
||||||
Timber.d("## CrossSigning - computeRoomShield ${roomSummaryEntity.roomId} -> $activeMemberUserIds")
|
Timber.d("## CrossSigning - computeRoomShield ${roomSummaryEntity.roomId} -> $activeMemberUserIds")
|
||||||
// The set of “all users” depends on the type of room:
|
// 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
|
// 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 }
|
activeMemberUserIds.filter { it != myUserId }
|
||||||
} else {
|
} else {
|
||||||
activeMemberUserIds
|
activeMemberUserIds
|
||||||
|
|
|
@ -1679,27 +1679,24 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
// Only keep one week history
|
// Only keep one week history
|
||||||
realm.where<IncomingGossipingRequestEntity>()
|
realm.where<IncomingGossipingRequestEntity>()
|
||||||
.lessThan(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, prevWeekTs)
|
.lessThan(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, prevWeekTs)
|
||||||
.findAll().let {
|
.findAll()
|
||||||
Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity")
|
.also { Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity") }
|
||||||
it.deleteAllFromRealm()
|
.deleteAllFromRealm()
|
||||||
}
|
|
||||||
|
|
||||||
// Clean the cancelled ones?
|
// Clean the cancelled ones?
|
||||||
realm.where<OutgoingGossipingRequestEntity>()
|
realm.where<OutgoingGossipingRequestEntity>()
|
||||||
.equalTo(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, OutgoingGossipingRequestState.CANCELLED.name)
|
.equalTo(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, OutgoingGossipingRequestState.CANCELLED.name)
|
||||||
.equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name)
|
.equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name)
|
||||||
.findAll().let {
|
.findAll()
|
||||||
Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity")
|
.also { Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity") }
|
||||||
it.deleteAllFromRealm()
|
.deleteAllFromRealm()
|
||||||
}
|
|
||||||
|
|
||||||
// Only keep one week history
|
// Only keep one week history
|
||||||
realm.where<GossipingEventEntity>()
|
realm.where<GossipingEventEntity>()
|
||||||
.lessThan(GossipingEventEntityFields.AGE_LOCAL_TS, prevWeekTs)
|
.lessThan(GossipingEventEntityFields.AGE_LOCAL_TS, prevWeekTs)
|
||||||
.findAll().let {
|
.findAll()
|
||||||
Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields")
|
.also { Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields") }
|
||||||
it.deleteAllFromRealm()
|
.deleteAllFromRealm()
|
||||||
}
|
|
||||||
|
|
||||||
// Can we do something for WithHeldSessionEntity?
|
// 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")
|
Timber.i("## Requesting verification to user: $otherUserId with device list $otherDevices")
|
||||||
|
|
||||||
val targetDevices = otherDevices ?: cryptoStore.getUserDevices(otherUserId)
|
val targetDevices = otherDevices ?: cryptoStore.getUserDevices(otherUserId)
|
||||||
?.values?.map { it.deviceId } ?: emptyList()
|
?.values?.map { it.deviceId }.orEmpty()
|
||||||
|
|
||||||
val requestsForUser = pendingRequests.getOrPut(otherUserId) { mutableListOf() }
|
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.actions.SetDeviceVerificationAction
|
||||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||||
import org.matrix.android.sdk.internal.extensions.toUnsignedInt
|
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.OlmSAS
|
||||||
import org.matrix.olm.OlmUtility
|
import org.matrix.olm.OlmUtility
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an ongoing short code interactive key verification between two devices.
|
* 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
|
// cannot be empty because it has been validated
|
||||||
theirMacSafe.mac.keys.forEach {
|
theirMacSafe.mac.keys.forEach {
|
||||||
val keyIDNoPrefix = it.withoutPrefix("ed25519:")
|
val keyIDNoPrefix = it.removePrefix("ed25519:")
|
||||||
val otherDeviceKey = otherUserKnownDevices?.get(keyIDNoPrefix)?.fingerprint()
|
val otherDeviceKey = otherUserKnownDevices?.get(keyIDNoPrefix)?.fingerprint()
|
||||||
if (otherDeviceKey == null) {
|
if (otherDeviceKey == null) {
|
||||||
Timber.w("## SAS Verification: Could not find device $keyIDNoPrefix to verify")
|
Timber.w("## SAS Verification: Could not find device $keyIDNoPrefix to verify")
|
||||||
|
@ -273,7 +273,7 @@ internal abstract class SASDefaultVerificationTransaction(
|
||||||
if (otherCrossSigningMasterKeyPublic != null) {
|
if (otherCrossSigningMasterKeyPublic != null) {
|
||||||
// Did the user signed his master key
|
// Did the user signed his master key
|
||||||
theirMacSafe.mac.keys.forEach {
|
theirMacSafe.mac.keys.forEach {
|
||||||
val keyIDNoPrefix = it.withoutPrefix("ed25519:")
|
val keyIDNoPrefix = it.removePrefix("ed25519:")
|
||||||
if (keyIDNoPrefix == otherCrossSigningMasterKeyPublic) {
|
if (keyIDNoPrefix == otherCrossSigningMasterKeyPublic) {
|
||||||
// Check the signature
|
// Check the signature
|
||||||
val mac = macUsingAgreedMethod(otherCrossSigningMasterKeyPublic, baseInfo + it)
|
val mac = macUsingAgreedMethod(otherCrossSigningMasterKeyPublic, baseInfo + it)
|
||||||
|
@ -345,7 +345,7 @@ internal abstract class SASDefaultVerificationTransaction(
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun hashUsingAgreedHashMethod(toHash: String): String? {
|
protected fun hashUsingAgreedHashMethod(toHash: String): String? {
|
||||||
if ("sha256".toLowerCase() == accepted?.hash?.toLowerCase()) {
|
if ("sha256" == accepted?.hash?.toLowerCase(Locale.ROOT)) {
|
||||||
val olmUtil = OlmUtility()
|
val olmUtil = OlmUtility()
|
||||||
val hashBytes = olmUtil.sha256(toHash)
|
val hashBytes = olmUtil.sha256(toHash)
|
||||||
olmUtil.releaseUtility()
|
olmUtil.releaseUtility()
|
||||||
|
@ -355,12 +355,11 @@ internal abstract class SASDefaultVerificationTransaction(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun macUsingAgreedMethod(message: String, info: String): String? {
|
private fun macUsingAgreedMethod(message: String, info: String): String? {
|
||||||
if (SAS_MAC_SHA256_LONGKDF.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
|
return when (accepted?.messageAuthenticationCode?.toLowerCase(Locale.ROOT)) {
|
||||||
return getSAS().calculateMacLongKdf(message, info)
|
SAS_MAC_SHA256_LONGKDF -> getSAS().calculateMacLongKdf(message, info)
|
||||||
} else if (SAS_MAC_SHA256.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
|
SAS_MAC_SHA256 -> getSAS().calculateMac(message, info)
|
||||||
return getSAS().calculateMac(message, info)
|
else -> null
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDecimalCodeRepresentation(): String {
|
override fun getDecimalCodeRepresentation(): String {
|
||||||
|
|
|
@ -52,5 +52,8 @@ internal class TimeOutInterceptor @Inject constructor() : Interceptor {
|
||||||
const val CONNECT_TIMEOUT = "CONNECT_TIMEOUT"
|
const val CONNECT_TIMEOUT = "CONNECT_TIMEOUT"
|
||||||
const val READ_TIMEOUT = "READ_TIMEOUT"
|
const val READ_TIMEOUT = "READ_TIMEOUT"
|
||||||
const val WRITE_TIMEOUT = "WRITE_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
|
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.RawCacheStrategy
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
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 java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultRawService @Inject constructor(
|
internal class DefaultRawService @Inject constructor(
|
||||||
private val taskExecutor: TaskExecutor,
|
|
||||||
private val getUrlTask: GetUrlTask,
|
private val getUrlTask: GetUrlTask,
|
||||||
private val cleanRawCacheTask: CleanRawCacheTask
|
private val cleanRawCacheTask: CleanRawCacheTask
|
||||||
) : RawService {
|
) : RawService {
|
||||||
override fun getUrl(url: String,
|
override suspend fun getUrl(url: String, rawCacheStrategy: RawCacheStrategy): String {
|
||||||
rawCacheStrategy: RawCacheStrategy,
|
return getUrlTask.execute(GetUrlTask.Params(url, rawCacheStrategy))
|
||||||
matrixCallback: MatrixCallback<String>): Cancelable {
|
|
||||||
return getUrlTask
|
|
||||||
.configureWith(GetUrlTask.Params(url, rawCacheStrategy)) {
|
|
||||||
callback = matrixCallback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getWellknown(userId: String,
|
override suspend fun getWellknown(userId: String): String {
|
||||||
matrixCallback: MatrixCallback<String>): Cancelable {
|
|
||||||
val homeServerDomain = userId.substringAfter(":")
|
val homeServerDomain = userId.substringAfter(":")
|
||||||
return getUrl(
|
return getUrl(
|
||||||
"https://$homeServerDomain/.well-known/matrix/client",
|
"https://$homeServerDomain/.well-known/matrix/client",
|
||||||
RawCacheStrategy.TtlCache(TimeUnit.HOURS.toMillis(8), false),
|
RawCacheStrategy.TtlCache(TimeUnit.HOURS.toMillis(8), false)
|
||||||
matrixCallback
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearCache(matrixCallback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun clearCache() {
|
||||||
return cleanRawCacheTask
|
cleanRawCacheTask.execute(Unit)
|
||||||
.configureWith(Unit) {
|
|
||||||
callback = matrixCallback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
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.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,
|
internal class DefaultGroup(override val groupId: String,
|
||||||
private val taskExecutor: TaskExecutor,
|
|
||||||
private val getGroupDataTask: GetGroupDataTask) : Group {
|
private val getGroupDataTask: GetGroupDataTask) : Group {
|
||||||
|
|
||||||
override fun fetchGroupData(callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun fetchGroupData() {
|
||||||
val params = GetGroupDataTask.Params.FetchWithIds(listOf(groupId))
|
val params = GetGroupDataTask.Params.FetchWithIds(listOf(groupId))
|
||||||
return getGroupDataTask.configureWith(params) {
|
getGroupDataTask.execute(params)
|
||||||
this.callback = callback
|
|
||||||
}.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.api.session.group.Group
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface GroupFactory {
|
internal interface GroupFactory {
|
||||||
|
@ -26,14 +25,12 @@ internal interface GroupFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal class DefaultGroupFactory @Inject constructor(private val getGroupDataTask: GetGroupDataTask,
|
internal class DefaultGroupFactory @Inject constructor(private val getGroupDataTask: GetGroupDataTask) :
|
||||||
private val taskExecutor: TaskExecutor) :
|
|
||||||
GroupFactory {
|
GroupFactory {
|
||||||
|
|
||||||
override fun create(groupId: String): Group {
|
override fun create(groupId: String): Group {
|
||||||
return DefaultGroup(
|
return DefaultGroup(
|
||||||
groupId = groupId,
|
groupId = groupId,
|
||||||
taskExecutor = taskExecutor,
|
|
||||||
getGroupDataTask = getGroupDataTask
|
getGroupDataTask = getGroupDataTask
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||||
import org.matrix.android.sdk.internal.util.ensureProtocol
|
import org.matrix.android.sdk.internal.util.ensureProtocol
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.net.ssl.HttpsURLConnection
|
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 {
|
override fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable {
|
||||||
|
if (!getUserConsent()) {
|
||||||
|
callback.onFailure(IdentityServiceError.UserConsentNotProvided)
|
||||||
|
return NoOpCancellable
|
||||||
|
}
|
||||||
|
|
||||||
if (threePids.isEmpty()) {
|
if (threePids.isEmpty()) {
|
||||||
callback.onSuccess(emptyList())
|
callback.onSuccess(emptyList())
|
||||||
return NoOpCancellable
|
return NoOpCancellable
|
||||||
|
@ -255,6 +269,9 @@ internal class DefaultIdentityService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getShareStatus(threePids: List<ThreePid>, callback: MatrixCallback<Map<ThreePid, SharedState>>): Cancelable {
|
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()) {
|
if (threePids.isEmpty()) {
|
||||||
callback.onSuccess(emptyMap())
|
callback.onSuccess(emptyMap())
|
||||||
return NoOpCancellable
|
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 org.matrix.android.sdk.internal.session.identity.db.RealmIdentityStore
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import org.matrix.android.sdk.internal.session.identity.db.RealmIdentityStoreMigration
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -59,6 +60,7 @@ internal abstract class IdentityModule {
|
||||||
@SessionScope
|
@SessionScope
|
||||||
fun providesIdentityRealmConfiguration(realmKeysUtils: RealmKeysUtils,
|
fun providesIdentityRealmConfiguration(realmKeysUtils: RealmKeysUtils,
|
||||||
@SessionFilesDirectory directory: File,
|
@SessionFilesDirectory directory: File,
|
||||||
|
migration: RealmIdentityStoreMigration,
|
||||||
@UserMd5 userMd5: String): RealmConfiguration {
|
@UserMd5 userMd5: String): RealmConfiguration {
|
||||||
return RealmConfiguration.Builder()
|
return RealmConfiguration.Builder()
|
||||||
.directory(directory)
|
.directory(directory)
|
||||||
|
@ -66,6 +68,8 @@ internal abstract class IdentityModule {
|
||||||
.apply {
|
.apply {
|
||||||
realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5))
|
realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5))
|
||||||
}
|
}
|
||||||
|
.schemaVersion(RealmIdentityStoreMigration.IDENTITY_STORE_SCHEMA_VERSION)
|
||||||
|
.migration(migration)
|
||||||
.allowWritesOnUiThread(true)
|
.allowWritesOnUiThread(true)
|
||||||
.modules(IdentityRealmModule())
|
.modules(IdentityRealmModule())
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -20,5 +20,6 @@ internal data class IdentityData(
|
||||||
val identityServerUrl: String?,
|
val identityServerUrl: String?,
|
||||||
val token: String?,
|
val token: String?,
|
||||||
val hashLookupPepper: 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 setToken(token: String?)
|
||||||
|
|
||||||
|
fun setUserConsent(consent: Boolean)
|
||||||
|
|
||||||
fun setHashDetails(hashDetailResponse: IdentityHashDetailResponse)
|
fun setHashDetails(hashDetailResponse: IdentityHashDetailResponse)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,7 +23,8 @@ internal open class IdentityDataEntity(
|
||||||
var identityServerUrl: String? = null,
|
var identityServerUrl: String? = null,
|
||||||
var token: String? = null,
|
var token: String? = null,
|
||||||
var hashLookupPepper: String? = null,
|
var hashLookupPepper: String? = null,
|
||||||
var hashLookupAlgorithm: RealmList<String> = RealmList()
|
var hashLookupAlgorithm: RealmList<String> = RealmList(),
|
||||||
|
var userConsent: Boolean = false
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
||||||
companion object
|
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,
|
internal fun IdentityDataEntity.Companion.setHashDetails(realm: Realm,
|
||||||
pepper: String,
|
pepper: String,
|
||||||
algorithms: List<String>) {
|
algorithms: List<String>) {
|
||||||
|
|
|
@ -26,7 +26,8 @@ internal object IdentityMapper {
|
||||||
identityServerUrl = entity.identityServerUrl,
|
identityServerUrl = entity.identityServerUrl,
|
||||||
token = entity.token,
|
token = entity.token,
|
||||||
hashLookupPepper = entity.hashLookupPepper,
|
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) {
|
override fun setHashDetails(hashDetailResponse: IdentityHashDetailResponse) {
|
||||||
Realm.getInstance(realmConfiguration).use {
|
Realm.getInstance(realmConfiguration).use {
|
||||||
it.executeTransaction { realm ->
|
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
|
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.IntegrationManagerConfig
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultIntegrationManagerService @Inject constructor(private val integrationManager: IntegrationManager) : IntegrationManagerService {
|
internal class DefaultIntegrationManagerService @Inject constructor(private val integrationManager: IntegrationManager) : IntegrationManagerService {
|
||||||
|
@ -44,20 +42,20 @@ internal class DefaultIntegrationManagerService @Inject constructor(private val
|
||||||
return integrationManager.isIntegrationEnabled()
|
return integrationManager.isIntegrationEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||||
return integrationManager.setIntegrationEnabled(enable, callback)
|
integrationManager.setIntegrationEnabled(enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean) {
|
||||||
return integrationManager.setWidgetAllowed(stateEventId, allowed, callback)
|
integrationManager.setWidgetAllowed(stateEventId, allowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isWidgetAllowed(stateEventId: String): Boolean {
|
override fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||||
return integrationManager.isWidgetAllowed(stateEventId)
|
return integrationManager.isWidgetAllowed(stateEventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean) {
|
||||||
return integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed, callback)
|
integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isNativeWidgetDomainAllowed(widgetType: String, domain: String): Boolean {
|
override fun isNativeWidgetDomainAllowed(widgetType: String, domain: String): Boolean {
|
||||||
|
|
|
@ -20,15 +20,12 @@ import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.LifecycleRegistry
|
import androidx.lifecycle.LifecycleRegistry
|
||||||
import com.zhuinden.monarchy.Monarchy
|
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.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
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.IntegrationManagerConfig
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
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.WidgetContent
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
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.database.model.WellknownIntegrationManagerConfigEntity
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.extensions.observeNotNull
|
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.WidgetFactory
|
||||||
import org.matrix.android.sdk.internal.session.widgets.helper.extractWidgetSequence
|
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.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -137,22 +133,17 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
||||||
return integrationProvisioningContent?.enabled ?: false
|
return integrationProvisioningContent?.enabled ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||||
val isIntegrationEnabled = isIntegrationEnabled()
|
val isIntegrationEnabled = isIntegrationEnabled()
|
||||||
if (enable == isIntegrationEnabled) {
|
if (enable == isIntegrationEnabled) {
|
||||||
callback.onSuccess(Unit)
|
return
|
||||||
return NoOpCancellable
|
|
||||||
}
|
}
|
||||||
val integrationProvisioningContent = IntegrationProvisioningContent(enabled = enable)
|
val integrationProvisioningContent = IntegrationProvisioningContent(enabled = enable)
|
||||||
val params = UpdateUserAccountDataTask.IntegrationProvisioning(integrationProvisioningContent = integrationProvisioningContent)
|
val params = UpdateUserAccountDataTask.IntegrationProvisioning(integrationProvisioningContent = integrationProvisioningContent)
|
||||||
return updateUserAccountDataTask
|
return updateUserAccountDataTask.execute(params)
|
||||||
.configureWith(params) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||||
val newContent = if (currentContent == null) {
|
val newContent = if (currentContent == null) {
|
||||||
|
@ -165,11 +156,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
||||||
currentContent.copy(widgets = allowedWidgets)
|
currentContent.copy(widgets = allowedWidgets)
|
||||||
}
|
}
|
||||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||||
return updateUserAccountDataTask
|
return updateUserAccountDataTask.execute(params)
|
||||||
.configureWith(params) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isWidgetAllowed(stateEventId: String): Boolean {
|
fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||||
|
@ -178,7 +165,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
||||||
return currentContent?.widgets?.get(stateEventId) ?: false
|
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 currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||||
val newContent = if (currentContent == null) {
|
val newContent = if (currentContent == null) {
|
||||||
|
@ -195,11 +182,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
||||||
currentContent.copy(native = nativeAllowedWidgets)
|
currentContent.copy(native = nativeAllowedWidgets)
|
||||||
}
|
}
|
||||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||||
return updateUserAccountDataTask
|
return updateUserAccountDataTask.execute(params)
|
||||||
.configureWith(params) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isNativeWidgetDomainAllowed(widgetType: String, domain: String?): Boolean {
|
fun isNativeWidgetDomainAllowed(widgetType: String, domain: String?): Boolean {
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package org.matrix.android.sdk.internal.session.notification
|
package org.matrix.android.sdk.internal.session.notification
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
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.PushRuleService
|
||||||
import org.matrix.android.sdk.api.pushrules.RuleKind
|
import org.matrix.android.sdk.api.pushrules.RuleKind
|
||||||
import org.matrix.android.sdk.api.pushrules.RuleSetKey
|
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.PushRule
|
||||||
import org.matrix.android.sdk.api.pushrules.rest.RuleSet
|
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.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.mapper.PushRulesMapper
|
||||||
import org.matrix.android.sdk.internal.database.model.PushRulesEntity
|
import org.matrix.android.sdk.internal.database.model.PushRulesEntity
|
||||||
import org.matrix.android.sdk.internal.database.query.where
|
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
|
// The rules will be updated, and will come back from the next sync response
|
||||||
return updatePushRuleEnableStatusTask
|
updatePushRuleEnableStatusTask.execute(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled))
|
||||||
.configureWith(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun addPushRule(kind: RuleKind, pushRule: PushRule) {
|
||||||
return addPushRuleTask
|
addPushRuleTask.execute(AddPushRuleTask.Params(kind, pushRule))
|
||||||
.configureWith(AddPushRuleTask.Params(kind, pushRule)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule) {
|
||||||
return updatePushRuleActionsTask
|
updatePushRuleActionsTask.execute(UpdatePushRuleActionsTask.Params(kind, oldPushRule, newPushRule))
|
||||||
.configureWith(UpdatePushRuleActionsTask.Params(kind, oldPushRule, newPushRule)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun removePushRule(kind: RuleKind, pushRule: PushRule) {
|
||||||
return removePushRuleTask
|
removePushRuleTask.execute(RemovePushRuleTask.Params(kind, pushRule))
|
||||||
.configureWith(RemovePushRuleTask.Params(kind, pushRule)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removePushRuleListener(listener: PushRuleService.PushRuleListener) {
|
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.database.model.UserThreePidEntity
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.session.content.FileUploader
|
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.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
import org.matrix.android.sdk.internal.task.configureWith
|
||||||
import org.matrix.android.sdk.internal.task.launchToCallback
|
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 finalizeAddingThreePidTask: FinalizeAddingThreePidTask,
|
||||||
private val deleteThreePidTask: DeleteThreePidTask,
|
private val deleteThreePidTask: DeleteThreePidTask,
|
||||||
private val pendingThreePidMapper: PendingThreePidMapper,
|
private val pendingThreePidMapper: PendingThreePidMapper,
|
||||||
|
private val userStore: UserStore,
|
||||||
private val fileUploader: FileUploader) : ProfileService {
|
private val fileUploader: FileUploader) : ProfileService {
|
||||||
|
|
||||||
override fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable {
|
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 {
|
override fun setDisplayName(userId: String, newDisplayName: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
|
||||||
return setDisplayNameTask
|
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.io, matrixCallback) {
|
||||||
.configureWith(SetDisplayNameTask.Params(userId = userId, newDisplayName = newDisplayName)) {
|
setDisplayNameTask.execute(SetDisplayNameTask.Params(userId = userId, newDisplayName = newDisplayName))
|
||||||
callback = matrixCallback
|
userStore.updateDisplayName(userId, newDisplayName)
|
||||||
}
|
}
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
|
override fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
|
||||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, matrixCallback) {
|
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, matrixCallback) {
|
||||||
val response = fileUploader.uploadFromUri(newAvatarUri, fileName, "image/jpeg")
|
val response = fileUploader.uploadFromUri(newAvatarUri, fileName, "image/jpeg")
|
||||||
setAvatarUrlTask.execute(SetAvatarUrlTask.Params(userId = userId, newAvatarUrl = response.contentUri))
|
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.crypto.CryptoService
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
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.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.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
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 roomCallService: RoomCallService,
|
||||||
private val readService: ReadService,
|
private val readService: ReadService,
|
||||||
private val typingService: TypingService,
|
private val typingService: TypingService,
|
||||||
|
private val aliasService: AliasService,
|
||||||
private val tagsService: TagsService,
|
private val tagsService: TagsService,
|
||||||
private val cryptoService: CryptoService,
|
private val cryptoService: CryptoService,
|
||||||
private val relationService: RelationService,
|
private val relationService: RelationService,
|
||||||
|
@ -76,6 +78,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
||||||
RoomCallService by roomCallService,
|
RoomCallService by roomCallService,
|
||||||
ReadService by readService,
|
ReadService by readService,
|
||||||
TypingService by typingService,
|
TypingService by typingService,
|
||||||
|
AliasService by aliasService,
|
||||||
TagsService by tagsService,
|
TagsService by tagsService,
|
||||||
RelationService by relationService,
|
RelationService by relationService,
|
||||||
MembershipService by roomMembersService,
|
MembershipService by roomMembersService,
|
||||||
|
@ -101,13 +104,13 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
||||||
return cryptoService.shouldEncryptForInvitedMembers(roomId)
|
return cryptoService.shouldEncryptForInvitedMembers(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun enableEncryption(algorithm: String, callback: MatrixCallback<Unit>) {
|
override suspend fun enableEncryption(algorithm: String) {
|
||||||
when {
|
when {
|
||||||
isEncrypted() -> {
|
isEncrypted() -> {
|
||||||
callback.onFailure(IllegalStateException("Encryption is already enabled for this room"))
|
throw IllegalStateException("Encryption is already enabled for this room")
|
||||||
}
|
}
|
||||||
algorithm != MXCRYPTO_ALGORITHM_MEGOLM -> {
|
algorithm != MXCRYPTO_ALGORITHM_MEGOLM -> {
|
||||||
callback.onFailure(InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported"))
|
throw InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val params = SendStateTask.Params(
|
val params = SendStateTask.Params(
|
||||||
|
@ -118,11 +121,7 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
||||||
"algorithm" to algorithm
|
"algorithm" to algorithm
|
||||||
))
|
))
|
||||||
|
|
||||||
sendStateTask
|
sendStateTask.execute(params)
|
||||||
.configureWith(params) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,24 @@ package org.matrix.android.sdk.internal.session.room
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.session.room.RoomDirectoryService
|
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.PublicRoomsParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
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.session.room.model.thirdparty.ThirdPartyProtocol
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
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.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.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.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
import org.matrix.android.sdk.internal.task.configureWith
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask,
|
internal class DefaultRoomDirectoryService @Inject constructor(
|
||||||
|
private val getPublicRoomTask: GetPublicRoomTask,
|
||||||
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
|
||||||
|
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
|
||||||
|
private val setRoomDirectoryVisibilityTask: SetRoomDirectoryVisibilityTask,
|
||||||
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
|
||||||
|
|
||||||
override fun getPublicRooms(server: String?,
|
override fun getPublicRooms(server: String?,
|
||||||
|
@ -49,4 +55,12 @@ internal class DefaultRoomDirectoryService @Inject constructor(private val getPu
|
||||||
}
|
}
|
||||||
.executeBy(taskExecutor)
|
.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
|
package org.matrix.android.sdk.internal.session.room
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
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.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
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.RoomService
|
||||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
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.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.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
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.Cancelable
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
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.alias.GetRoomIdByAliasTask
|
||||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
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.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.membership.joining.JoinRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
|
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.room.summary.RoomSummaryDataSource
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateBreadcrumbsTask
|
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.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
import org.matrix.android.sdk.internal.task.configureWith
|
||||||
|
import org.matrix.android.sdk.internal.util.fetchCopied
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultRoomService @Inject constructor(
|
internal class DefaultRoomService @Inject constructor(
|
||||||
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
private val createRoomTask: CreateRoomTask,
|
private val createRoomTask: CreateRoomTask,
|
||||||
private val joinRoomTask: JoinRoomTask,
|
private val joinRoomTask: JoinRoomTask,
|
||||||
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
|
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
|
||||||
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
||||||
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
||||||
|
private val deleteRoomAliasTask: DeleteRoomAliasTask,
|
||||||
private val roomGetter: RoomGetter,
|
private val roomGetter: RoomGetter,
|
||||||
private val roomSummaryDataSource: RoomSummaryDataSource,
|
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||||
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
||||||
|
@ -115,7 +127,31 @@ internal class DefaultRoomService @Inject constructor(
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteRoomAlias(roomAlias: String) {
|
||||||
|
deleteRoomAliasTask.execute(DeleteRoomAliasTask.Params(roomAlias))
|
||||||
|
}
|
||||||
|
|
||||||
override fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> {
|
override fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> {
|
||||||
return roomChangeMembershipStateDataSource.getLiveStates()
|
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