Merge branch 'release/1.1.4'

This commit is contained in:
Benoit Marty 2021-04-09 12:41:04 +02:00
commit 0a326015ef
483 changed files with 8972 additions and 5107 deletions

View file

@ -1,3 +1,43 @@
Changes in Element 1.1.4 (2021-04-09)
===================================================
Improvements 🙌:
- Split network request `/keys/query` into smaller requests (250 users max) (#2925)
- Crypto improvement | Bulk send NO_OLM withheld code
- Display the room shield in all room setting screens
- Improve message with Emoji only detection (#3017)
- Picture preview when replying. Also add the image preview in the message detail bottomsheet (#2916)
- Api interceptor to allow app developers peek responses (#2986)
- Update reactions to Unicode 13.1 (#2998)
- Be more robust when parsing some enums
- Improve timeline filtering (dissociate membership and profile events, display hidden events when highlighted, fix hidden item/read receipts behavior)
- Add better support for empty room name fallback (#3106)
- Room list improvements (paging)
- Fix quick click action (#3127)
- Get Event after a Push for a faster notification display in some conditions
- Always try to retry Http requests in case of 429 (#1300)
- registration availability endpoint added to matrix-sdk
Bugfix 🐛:
- Fix bad theme change for the MainActivity
- Handle encrypted reactions (#2509)
- Disable URL preview for some domains (#2995)
- Fix avatar rendering for DMs, after initial sync (#2693)
- Fix mandatory parameter in API (#3065)
- If signout request fails, do not start LoginActivity, but restart the app (#3099)
- Retain keyword order in emoji import script, and update the generated file (#3147)
SDK API changes ⚠️:
- Several Services have been migrated to coroutines (#2449)
- Removes filtering options on Timeline.
Build 🧱:
- Properly exclude gms dependencies in fdroid build flavour which were pulled in through the jitsi SDK (#3125)
Other changes:
- Add version details on the login screen, in debug or developer mode
- Migrate Retrofit interface to coroutine calls
Changes in Element 1.1.3 (2021-03-18)
===================================================

View file

@ -69,7 +69,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.recyclerview:recyclerview:1.2.0-beta02"
implementation "androidx.recyclerview:recyclerview:1.2.0-rc01"
implementation 'com.google.android.material:material:1.3.0'
}

View file

@ -2,7 +2,7 @@
buildscript {
// Ref: https://kotlinlang.org/releases.html
ext.kotlin_version = '1.4.31'
ext.kotlin_version = '1.4.32'
ext.kotlin_coroutines_version = "1.4.2"
repositories {
google()
@ -12,11 +12,11 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'com.android.tools.build:gradle:4.1.3'
classpath 'com.google.gms:google-services:4.3.5'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.1.1'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.3'
classpath "com.likethesalad.android:string-reference:1.2.1"
// NOTE: Do not place your application dependencies here; they belong

View file

@ -2,7 +2,7 @@ This document aims to describe how Element android displays notifications to the
# Table of Contents
1. [Prerequisites Knowledge](#prerequisites-knowledge)
* [How does a matrix client gets a message from a Home Server?](#how-does-a-matrix-client-gets-a-message-from-a-home-server)
* [How does a matrix client get a message from a Home Server?](#how-does-a-matrix-client-get-a-message-from-a-home-server)
* [How does a mobile app receives push notification?](#how-does-a-mobile-app-receives-push-notification)
* [Push VS Notification](#push-vs-notification)
* [Push in the matrix federated world](#push-in-the-matrix-federated-world)
@ -22,7 +22,7 @@ First let's start with some prerequisite knowledge
# Prerequisites Knowledge
## How does a matrix client gets a message from a Home Server?
## How does a matrix client get a message from a Home Server?
In order to get messages from a home server, a matrix client need to perform a ``sync`` operation.

View file

@ -0,0 +1,2 @@
التغييرات الرئيسة في هذه النسخة: تحسينات على الأداء وإصلاح للعلل!
اطّلع على سجل التغييرات الكامل هنا: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -1 +1 @@
Element (سابقاً Riot.im)
Element (Riot.im سابقًا)

View file

@ -0,0 +1,2 @@
Canvis principals d'aquesta versió: millora de rendiment i correcció d'errors!
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: vylepšení výkonnosti a opravy chyb!
Úplný záznam změn: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -1,2 +1,2 @@
Diese neue Version enthält hauptsächlich Verbesserungen der Benutzer*innenoberfläche und der Handhabung. Du kannst jetzt ganz schnell Freund*innen einladen und DMs erstellen, indem du schlicht einen QR-Code scannst.
Diese neue Version enthält hauptsächlich Verbesserungen der Benutzeroberfläche und der Handhabung. Du kannst jetzt ganz schnell Freund*innen einladen und DMs erstellen, indem du schlicht einen QR-Code scannst.
Vollständige Versionshinweise: https://github.com/vector-im/element-android/releases/tag/v1.0.11

View file

@ -0,0 +1,2 @@
Hauptänderungen in dieser Version: Leistungsverbesserungen und Fehlerbehebungen!
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -3,7 +3,7 @@ Element ist eine neuartige Messaging- und Kollaborationsapp:
1. Volle Kontrolle über deine Privatssphäre
2. Kommuniziere mit jedem aus dem Matrix-Netzwerk und mit der Integration von z.B. Slack sogar über Matrix hinaus
3. Schutz vor Werbung, Datamining und geschlossenen Platformen
4. Absicherung durch Ende-zu-Ende-Verschlüsselung, und Cross Signing um andere zu verifizieren
4. Absicherung durch Ende-zu-Ende-Verschlüsselung, und Cross-Signing um andere zu verifizieren
Element unterscheidet sich durch Dezentralität und Open Source deutlich von anderen Messaging- und Kollaborationsapps.
@ -11,11 +11,11 @@ Element ermöglicht es einen eigenen Server zu betreiben - oder einen beliebigen
Element ist zu all diesem in der Lage, weil es Matrix nutzt - einen Standard für offene, dezentrale Kommunikation.
Element gibt dir die Kontrolle, indem es dir die Wahl darüber lässt, wer deine Konversationen hostet. In der Element App kannst du zwischen verschiedenen Möglichkeiten auswählen:
Element gibt dir die Kontrolle, indem es dir die Wahl darüber lässt, wer deine Konversationen hostet. In der Element-App kannst du zwischen verschiedenen Möglichkeiten auswählen:
1. Kostenlos auf dem öffentlichen matrix.org Server registrieren, der von den Matrix-Entwicklern gehostet wird, oder wähle aus Tausenden von öffentlichen Servern, die von Freiwilligen gehostet werden
2. Einen Account auf einem eigenen Server auf eigener Hardware betreiben
3. Einen Account auf einem benutzerdefinierten Server erstellen, zum Beispiel durch ein Abonnment bei der Element Matrix Services Hosting-Platform
2. Einen Konto auf einem eigenen Server auf eigener Hardware betreiben
3. Einen Konto auf einem benutzerdefinierten Server erstellen, zum Beispiel durch ein Abonnement bei Element Matrix Services (kurz EMS)
<b>Wieso Element nutzen?</b>
@ -23,8 +23,8 @@ Element gibt dir die Kontrolle, indem es dir die Wahl darüber lässt, wer deine
<b>OFFENE KOMMUNIKATION UND KOLLABORATION</b>: Du kannst mit jedem im Matrix-Netzwerk schreiben, ob sie nun Element oder eine andere Matrix-App nutzen, oder gar ein anderes Kommunikationssystem wie z.B. Slack, IRC oder XMPP.
<b>SUPER SICHER</b>: Echte Ende-zu-Ende-Verschlüsselung (nur Personen in der Konversation können die Nachrichten entschlüsseln), und Cross Signing um die Geräte der anderen Personen zu verifizieren.
<b>SUPER SICHER</b>: Echte Ende-zu-Ende-Verschlüsselung (nur Personen in der Konversation können die Nachrichten entschlüsseln), und Cross-Signing um die Geräte der anderen Personen zu verifizieren.
<b>VOLLSTÄNDIGE KOMMUNIKATION</b>: Nachrichten, Telefonate und Videoanrufe, Teilen von Dateien oder dem eigenen Bildschirm und viele andere Integrationen, Bots und Widgets. Erstelle Räume, Communities, bleib in Kontakt und sei produktiv.
<b>ÜBERALL WO DU BIST</b>: Bleib in Kontakt wo auch immer du bist - mit einem vollständig synchronisierten Nachrichtenverlauf über alle Geräte und im Web auf https://app.element.io.
<b>ÜBERALL WO DU BIST</b>: Bleib in Kontakt wo auch immer du bist - mit einem vollständig synchronisierten Nachrichtenverlauf über alle Geräte und im Netz auf https://app.element.io.

View file

@ -1 +1 @@
Sicherer dezentraler Chat & Telefonie. Schütze deine Daten vor Dritten.
Sicherer dezentraler Chat und Telefonie. Schütze deine Daten vor Dritten.

View file

@ -0,0 +1,2 @@
Main changes in this version: performance improvement and bug fixes!
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.1.4

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: jõudluse parandused ja pisikohendused.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: پیش‌نمایش نشانی، صفحه‌کلید اموجی جدید، تنظیم‌های اتاق جدید و برف برای کریسمس!
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.12

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: پیش‌نمایش نشانی، صفحه‌کلید اموجی جدید، تنظیم‌های اتاق جدید و برف برای کریسمس!
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.13

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: ویرایش اجازه‌های اتاق، زمینهٔ تاریک/روشن خودکار و رفع دسته‌ای از مشکل‌ها.
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.14

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: پشتیبانی از ورود اجتماعی.
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.15

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: پشتیبانی از ورود اجتماعی.
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.15 و https://github.com/vector-im/element-android/releases/tag/v1.0.16

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: رفع مشکل‌ها!
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.17

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: بهبود ویپ (تماس‌های صوتی و تصویری در پیام‌های مستقیم) و رفع مشکل‌ها!
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: بهبود عملکرد و رفع مشکل‌ها!
گزارش تغییر کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1,2 @@
Suurimmat muutokset tässä versiossa: VoIP-parannuksia ja korjauksia (ääni- ja videopuhelut yksityiskeskusteluissa)
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Suurimmat muutokset tässä versiossa: suorituskykyparannuksia ja bugikorjauksia!
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -1,2 +1,2 @@
Principaux changements apportés par cette version : aperçu des URL, nouveau clavier Emoji, nouvelles options de configuration pour le salon et neige pour Noël.
Liste complète des changements : https://github.com/vector-im/element-android/releases/tag/v1.0.12
Liste complète des changements : https://github.com/vector-im/element-android/releases/tag/v1.0.13

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : modification des permissions dans les salons, thème lumineux/sombre automatique, et plein de corrections de bugs.
Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.0.14

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : prise en charge de lauthentification avec les réseaux sociaux.
Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.0.15

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : prise en charge de lauthentification avec les réseaux sociaux !
Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.0.15 et https://github.com/vector-im/element-android/releases/tag/v1.0.16

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : corrections de bugs !
Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1..017

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : améliorations de la VoIP (appels audio et vidéo dans les conversations primées) et corrections de bugs !
Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : amélioration des performances et corrections de bugs !
Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1 @@
Element (Riot.im roimhe sin)

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: migliorato il VoIP (chiamate audio e video in MD) e correzione di errori!
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: prestazioni migliorate e correzione di errori!
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -1 +1 @@
Adiwenni aɣellsan ur nelli aslammas & VoIP. Ḥrez isefra-k•m seg tama tis tlata.
Adiwenni aɣellsan ur nelli d aslammas & VoIP. Ḥrez isefra-k•m seg wis tlata.

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Melhoria de VoIP (chamadas de áudio e vídeo em conversas) e correção de erros!
Registro de alterações completo: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: melhoria de desempenho e correção de erros!
Registro de alterações completo: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1,2 @@
Основные изменения в этой версии: VoIP (аудио и видео звонки в ЛС) Улучшение и исправления ошибок!
Полный список изменений: https://github.com/vector-im/element-android/release/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Основные изменения в этой версии: улучшение производительности и исправления ошибок!
Полный список изменений: https://github.com/vector-im/element-android/release/tag/v1.1.1

View file

@ -0,0 +1,2 @@
Huvudsakliga ändringar i den här versionen: Förbättringar och buggfixar!
Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1,2 @@
Bu sürümdeki başlıca değişiklikler: Oda izinlerini düzenleme, otomatik koyu/açık tema ve bir avuç hata düzeltmeleri.
Değişim günlüğünün tamamı: https://github.com/vector-im/element-android/releases/tag/v1.0.14

View file

@ -0,0 +1,2 @@
Bu sürümdeki başlıca değişiklikler: Hata düzeltmeleri!
değişim günlüğünün tamamı: https://github.com/vector-im/element-android/releases/tag/v1.0.17

View file

@ -0,0 +1,2 @@
Bu sürümdeki ana değişiklikler: VoIP (DM'de sesli ve görüntülü aramalar) geliştirmeleri ve hata düzeltmeleri!
Değişim günlüğünün tamamı: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Bu sürümdeki ana değişiklikler: performans iyileştirme ve hata düzeltmeleri!
Değişim günlüğünün tamamı: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: поліпшення продуктивності та виправлення помилок!
Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -1,2 +1,2 @@
此新版本主要包含错误修复和改进。现在,发送消息要快得多
此新版本主要包含错误修复和改进。现在,发送消息比以前快多了
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.0.10

View file

@ -0,0 +1,2 @@
此版本的主要变化:链接预览,全新 Emoji 键盘,全新聊天室设置功能,以及圣诞节雪花!
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.0.12

View file

@ -0,0 +1,2 @@
此版本的主要变化:链接预览,全新 Emoji 键盘,全新聊天室设置功能,以及圣诞节雪花!
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.0.13

View file

@ -0,0 +1,2 @@
此版本的主要变化:支持编辑聊天室权限,自动切换浅色/深色主题,修复大量错误。
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.0.14

View file

@ -0,0 +1,2 @@
此版本的主要变化:支持通过社交网络登录。
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.0.15

View file

@ -0,0 +1,2 @@
此版本的主要变化:支持通过社交网络登录。
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.0.15 和 https://github.com/vector-im/element-android/releases/tag/v1.0.16

View file

@ -0,0 +1,2 @@
此版本的主要变化:修复错误!
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.0.17

View file

@ -0,0 +1,2 @@
此版本的主要变化:改进 VoIP私聊中的音频与视频通话以及修复错误
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
此版本的主要变化:改进性能以及修复错误!
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -1,30 +1,30 @@
Element 是一种新型消息和协作应用:
Element 是一种新型的通讯与协作应用:
1. 使您可以掌控您的隐私
2. 使您与 Matrix 网络中的任何人交流,甚至可以通过与其他应用如 Slack 集成
3. 保护您远离广告,数据挖掘和围墙花园
4. 通过端到端加密保护您,通过交叉签名验证其他人
2. 使您与 Matrix 网络中的任何人交流,甚至可以通过集成功能与如 Slack 之类的其他应用通讯
3. 保护您免受广告,大数据挖掘和封闭服务的侵害
4. 通过端到端加密保证安全,通过交叉签名验证其他人
Element 与其他消息和协作应用完全不同,因为它是去中心化且开源的。
Element 与其他通讯与协作应用完全不同,因为它是去中心化且开源的。
Element 使您可以自托管 - 或选择托管商 - 因此您拥有您的数据和会话的隐私权,所有权和控制权。它使您可以访问开放网络;因此您可以不仅仅与其他 Element 用户交流。并且它非常安全。
Element 允许您自托管——或者选择托管商——因此,您能拥有数据和会话的隐私权,所有权和控制权。它允许您访问开放网络;因此,您可以与 Element 用户以外的人交流。并且它非常安全。
Element 可以做到这些因为它在 Matrix 上运行 - 开放,去中心化通信标准。
Element 之所以可以做到这些,是因为它在 Matrix 上运行——开放,去中心化通讯的标准。
Element 通过让您选择谁来托管您的会话使您掌控一切。在 Element 应用中,您可以选择不同的托管方式:
通过让您选择由谁来托管您的会话Element 让您掌控一切。在 Element 应用中,您可以选择不同的托管方式:
1. 在由 Matrix 开发者托管的 matrix.org 公共服务器上获取免费帐户,或从志愿者托管的千个公共服务器中选择
2. 在您自己的硬件上运行服务器自托管您的会话
3. 通过简单地订阅 Element Matrix Services 托管平台在自定义服务器上注册账户
1. 在由 Matrix 开发者托管的 matrix.org 公共服务器上获取免费帐户,或从志愿者托管的千个公共服务器中选择
2. 在您自己的硬件上运行服务器自托管您的会话
3. 通过订阅 Element Matrix Services 托管平台,简单地在自定义服务器上注册账户
<b>为什么选择 Element</b>
<b>拥有您的数据</b>:您来决定存放您的数据和消息的位置。拥有并控制它的是您,而不是挖掘您的数据或与第三方分享的巨型企业。
<b>掌控您的数据</b>:您来决定存放您的数据和消息的位置。拥有并控制它的是您,而不是挖掘您的数据或与第三方分享的巨型企业。
<b>开放消息与协作</b>:您可以与 Matrix 网络中的任何人聊天,不论他们使用 Element 还是其他 Matrix 应用,甚至即使他们在使用不同的消息系统例如 SlackIRC 或 XMPP。
<b>开放通讯与协作</b>:您可以与 Matrix 网络中的任何人聊天,不论他们使用 Element 还是其他 Matrix 应用,甚至/即使他们在使用不同的通讯系统,例如 SlackIRC 或 XMPP。
<b>超级安全</b>:真正的端到端加密(仅有会话中的人可以解密消息),及用于验证会话参与方的设备的交叉签名。
<b>超级安全</b>支持真正的端到端加密(仅有会话中的人可以解密消息),还有能够验证会话参与方的设备的交叉签名。
<b>丰富的通信方式</b>:消息,语音和视频通话,文件分享,屏幕分享和大量集成,机器人和小部件。建立房间,社区,保持联系并做好工作。
<b>完善的通讯方式</b>:消息,语音和视频通话,文件共享,屏幕共享和大量集成功能,机器人和小挂件。建立房间与社区,保持联系并完成工作。
<b>随时随地</b>通过在您的全部设备和 https://app.element.io 网页上完全同步的消息历史,无论您在哪里都可以保持联系。
<b>随时随地</b>消息历史可在您的全部设备和 https://app.element.io 网页端之间完全同步,无论您在哪里,都可以保持联系。

View file

@ -1 +1 @@
安全去中心化的聊天和 VoIP。保护您的数据不受第三方的影响
安全、去中心化的聊天与 VoIP 通话。保护您的数据不被第三方窃取

View file

@ -0,0 +1,2 @@
此版本的主要變更:效能改進與錯誤修復!
完整變更紀錄https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -21,6 +21,7 @@ import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.Single
import kotlinx.coroutines.rx2.rxCompletable
import kotlinx.coroutines.rx2.rxSingle
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.identity.ThreePid
@ -90,13 +91,13 @@ class RxRoom(private val room: Room) {
return room.getMyReadReceiptLive().asObservable()
}
fun loadRoomMembersIfNeeded(): Single<Unit> = singleBuilder {
room.loadRoomMembersIfNeeded(it)
fun loadRoomMembersIfNeeded(): Single<Unit> = rxSingle {
room.loadRoomMembersIfNeeded()
}
fun joinRoom(reason: String? = null,
viaServers: List<String> = emptyList()): Single<Unit> = singleBuilder {
room.join(reason, viaServers, it)
viaServers: List<String> = emptyList()): Single<Unit> = rxSingle {
room.join(reason, viaServers)
}
fun liveEventReadReceipts(eventId: String): Observable<List<ReadReceipt>> {
@ -114,12 +115,12 @@ class RxRoom(private val room: Room) {
return room.getLiveRoomNotificationState().asObservable()
}
fun invite(userId: String, reason: String? = null): Completable = completableBuilder<Unit> {
room.invite(userId, reason, it)
fun invite(userId: String, reason: String? = null): Completable = rxCompletable {
room.invite(userId, reason)
}
fun invite3pid(threePid: ThreePid): Completable = completableBuilder<Unit> {
room.invite3pid(threePid, it)
fun invite3pid(threePid: ThreePid): Completable = rxCompletable {
room.invite3pid(threePid)
}
fun updateTopic(topic: String): Completable = rxCompletable {

View file

@ -20,6 +20,7 @@ import androidx.paging.PagedList
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.functions.Function3
import kotlinx.coroutines.rx2.rxSingle
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
@ -129,8 +130,8 @@ class RxSession(private val session: Session) {
fun searchUsersDirectory(search: String,
limit: Int,
excludedUserIds: Set<String>): Single<List<User>> = singleBuilder {
session.searchUsersDirectory(search, limit, excludedUserIds, it)
excludedUserIds: Set<String>): Single<List<User>> = rxSingle {
session.searchUsersDirectory(search, limit, excludedUserIds)
}
fun joinRoom(roomIdOrAlias: String,
@ -144,8 +145,8 @@ class RxSession(private val session: Session) {
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
}
fun getProfileInfo(userId: String): Single<JsonDict> = singleBuilder {
session.getProfile(userId, it)
fun getProfileInfo(userId: String): Single<JsonDict> = rxSingle {
session.getProfile(userId)
}
fun liveUserCryptoDevices(userId: String): Observable<List<CryptoDeviceInfo>> {

View file

@ -6,10 +6,10 @@ apply plugin: 'realm-android'
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:10.3.1"
classpath "io.realm:realm-gradle-plugin:10.4.0"
}
}
@ -108,7 +108,7 @@ static def gitRevisionDate() {
dependencies {
def arrow_version = "0.8.2"
def moshi_version = '1.11.0'
def moshi_version = '1.12.0'
def lifecycle_version = '2.2.0'
def arch_version = '2.1.0'
def markwon_version = '3.1.0'
@ -163,16 +163,16 @@ dependencies {
// Logging
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1'
implementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.19'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.21'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.5.1'
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
testImplementation 'io.mockk:mockk:1.10.6'
testImplementation 'io.mockk:mockk:1.11.0'
testImplementation 'org.amshove.kluent:kluent-android:1.65'
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
// Plant Timber tree for test
@ -185,8 +185,7 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'org.amshove.kluent:kluent-android:1.61'
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
androidTestImplementation 'io.mockk:mockk-android:1.10.6'
androidTestImplementation 'io.mockk:mockk-android:1.11.0'
androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
// Plant Timber tree for test

View file

@ -20,7 +20,6 @@ import android.content.Context
import androidx.test.core.app.ApplicationProvider
import org.matrix.android.sdk.test.shared.createTimberTestRule
import org.junit.Rule
import java.io.File
interface InstrumentedTest {
@ -30,8 +29,4 @@ interface InstrumentedTest {
fun context(): Context {
return ApplicationProvider.getApplicationContext()
}
fun cacheDir(): File {
return context().cacheDir
}
}

View file

@ -27,9 +27,12 @@ import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.api.network.ApiInterceptorListener
import org.matrix.android.sdk.api.network.ApiPath
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.common.DaggerTestMatrixComponent
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.network.ApiInterceptor
import org.matrix.android.sdk.internal.network.UserAgentHolder
import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
import org.matrix.olm.OlmManager
@ -51,6 +54,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
@Inject internal lateinit var olmManager: OlmManager
@Inject internal lateinit var sessionManager: SessionManager
@Inject internal lateinit var homeServerHistoryService: HomeServerHistoryService
@Inject internal lateinit var apiInterceptor: ApiInterceptor
private val uiHandler = Handler(Looper.getMainLooper())
@ -79,6 +83,14 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
return legacySessionImporter
}
fun registerApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
apiInterceptor.addListener(path, listener)
}
fun unregisterApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
apiInterceptor.removeListener(path, listener)
}
companion object {
private lateinit var instance: Matrix

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021 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.network
import org.amshove.kluent.shouldBeEqualTo
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import timber.log.Timber
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class ApiInterceptorTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
@Test
fun apiInterceptorTest() {
val responses = mutableListOf<String>()
val listener = object : ApiInterceptorListener {
override fun onApiResponse(path: ApiPath, response: String) {
Timber.w("onApiResponse($path): $response")
responses.add(response)
}
}
commonTestHelper.matrix.registerApiInterceptorListener(ApiPath.REGISTER, listener)
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
commonTestHelper.signOutAndClose(session)
commonTestHelper.matrix.unregisterApiInterceptorListener(ApiPath.REGISTER, listener)
responses.size shouldBeEqualTo 2
}
}

View file

@ -112,8 +112,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
bobRoomSummariesLive.observeForever(newRoomObserver)
}
mTestHelper.doSync<Unit> {
aliceRoom.invite(bobSession.myUserId, callback = it)
mTestHelper.runBlockingTest {
aliceRoom.invite(bobSession.myUserId)
}
mTestHelper.await(lock1)
@ -172,8 +172,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
fun createSamAccountAndInviteToTheRoom(room: Room): Session {
val samSession = mTestHelper.createAccount(TestConstants.USER_SAM, defaultSessionParams)
mTestHelper.doSync<Unit> {
room.invite(samSession.myUserId, null, it)
mTestHelper.runBlockingTest {
room.invite(samSession.myUserId, null)
}
mTestHelper.doSync<Unit> {
@ -337,8 +337,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
requestID,
roomId,
bob.myUserId,
bob.sessionParams.credentials.deviceId!!,
null)
bob.sessionParams.credentials.deviceId!!)
// we should reach SHOW SAS on both
var alicePovTx: OutgoingSasVerificationTransaction? = null
@ -411,7 +410,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
val sessions = mutableListOf(aliceSession)
for (index in 1 until numberOfMembers) {
val session = mTestHelper.createAccount("User_$index", defaultSessionParams)
mTestHelper.doSync<Unit>(timeout = 600_000) { room.invite(session.myUserId, null, it) }
mTestHelper.runBlockingTest(timeout = 600_000) { room.invite(session.myUserId, null) }
println("TEST -> " + session.myUserId + " invited")
mTestHelper.doSync<Unit> { session.joinRoom(room.roomId, null, emptyList(), it) }
println("TEST -> " + session.myUserId + " joined")

View file

@ -18,23 +18,26 @@ package org.matrix.android.sdk.common
import org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider
class TestRoomDisplayNameFallbackProvider() : RoomDisplayNameFallbackProvider {
class TestRoomDisplayNameFallbackProvider : RoomDisplayNameFallbackProvider {
override fun getNameForRoomInvite() =
"Room invite"
override fun getNameForEmptyRoom() =
override fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List<String>) =
"Empty room"
override fun getNameFor2members(name1: String?, name2: String?) =
override fun getNameFor1member(name: String) =
name
override fun getNameFor2members(name1: String, name2: String) =
"$name1 and $name2"
override fun getNameFor3members(name1: String?, name2: String?, name3: String?) =
override fun getNameFor3members(name1: String, name2: String, name3: String) =
"$name1, $name2 and $name3"
override fun getNameFor4members(name1: String?, name2: String?, name3: String?, name4: String?) =
override fun getNameFor4members(name1: String, name2: String, name3: String, name4: String) =
"$name1, $name2, $name3 and $name4"
override fun getNameFor4membersAndMore(name1: String?, name2: String?, name3: String?, remainingCount: Int) =
override fun getNameFor4membersAndMore(name1: String, name2: String, name3: String, remainingCount: Int) =
"$name1, $name2, $name3 and $remainingCount others"
}

View file

@ -367,8 +367,8 @@ class KeyShareTests : InstrumentedTest {
}
// Let alice invite bob
mTestHelper.doSync<Unit> {
roomAlicePov.invite(bobSession.myUserId, null, it)
mTestHelper.runBlockingTest {
roomAlicePov.invite(bobSession.myUserId, null)
}
mTestHelper.doSync<Unit> {

View file

@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.crypto.ssss
import androidx.lifecycle.Observer
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
import org.matrix.android.sdk.api.session.securestorage.KeySigner
@ -31,7 +30,6 @@ import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.common.TestMatrixCallback
import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
@ -40,7 +38,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.amshove.kluent.shouldBe
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
@ -70,8 +67,8 @@ class QuadSTests : InstrumentedTest {
val TEST_KEY_ID = "my.test.Key"
mTestHelper.doSync<SsssKeyCreationInfo> {
quadS.generateKey(TEST_KEY_ID, null, "Test Key", emptyKeySigner, it)
mTestHelper.runBlockingTest {
quadS.generateKey(TEST_KEY_ID, null, "Test Key", emptyKeySigner)
}
// Assert Account data is updated
@ -99,7 +96,9 @@ class QuadSTests : InstrumentedTest {
assertNull("Key was not generated from passphrase", parsed.passphrase)
// Set as default key
quadS.setDefaultKey(TEST_KEY_ID, object : MatrixCallback<Unit> {})
GlobalScope.launch {
quadS.setDefaultKey(TEST_KEY_ID)
}
var defaultKeyAccountData: UserAccountDataEvent? = null
val defaultDataLock = CountDownLatch(1)
@ -133,12 +132,11 @@ class QuadSTests : InstrumentedTest {
// Store a secret
val clearSecret = "42".toByteArray().toBase64NoPadding()
mTestHelper.doSync<Unit> {
mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.storeSecret(
"secret.of.life",
clearSecret,
listOf(SharedSecretStorageService.KeyRef(null, keySpec)), // default key
it
listOf(SharedSecretStorageService.KeyRef(null, keySpec)) // default key
)
}
@ -155,12 +153,11 @@ class QuadSTests : InstrumentedTest {
// Try to decrypt??
val decryptedSecret = mTestHelper.doSync<String> {
val decryptedSecret = mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.getSecret(
"secret.of.life",
null, // default key
keySpec!!,
it
keySpec!!
)
}
@ -176,13 +173,13 @@ class QuadSTests : InstrumentedTest {
val TEST_KEY_ID = "my.test.Key"
mTestHelper.doSync<SsssKeyCreationInfo> {
quadS.generateKey(TEST_KEY_ID, null, "Test Key", emptyKeySigner, it)
mTestHelper.runBlockingTest {
quadS.generateKey(TEST_KEY_ID, null, "Test Key", emptyKeySigner)
}
// Test that we don't need to wait for an account data sync to access directly the keyid from DB
mTestHelper.doSync<Unit> {
quadS.setDefaultKey(TEST_KEY_ID, it)
mTestHelper.runBlockingTest {
quadS.setDefaultKey(TEST_KEY_ID)
}
mTestHelper.signOutAndClose(aliceSession)
@ -198,15 +195,14 @@ class QuadSTests : InstrumentedTest {
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
mTestHelper.doSync<Unit> {
mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.storeSecret(
"my.secret",
mySecretText.toByteArray().toBase64NoPadding(),
listOf(
SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)),
SharedSecretStorageService.KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey))
),
it
)
)
}
@ -219,19 +215,17 @@ class QuadSTests : InstrumentedTest {
assertNotNull(encryptedContent?.get(keyId2))
// Assert that can decrypt with both keys
mTestHelper.doSync<String> {
mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)!!,
it
RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)!!
)
}
mTestHelper.doSync<String> {
mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId2,
RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!!,
it
RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!!
)
}
@ -247,50 +241,34 @@ class QuadSTests : InstrumentedTest {
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
mTestHelper.doSync<Unit> {
mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.storeSecret(
"my.secret",
mySecretText.toByteArray().toBase64NoPadding(),
listOf(SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey))),
it
listOf(SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)))
)
}
val decryptCountDownLatch = CountDownLatch(1)
var error = false
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromPassphrase(
"A bad passphrase",
key1Info.content?.passphrase?.salt ?: "",
key1Info.content?.passphrase?.iterations ?: 0,
null),
object : MatrixCallback<String> {
override fun onSuccess(data: String) {
decryptCountDownLatch.countDown()
}
override fun onFailure(failure: Throwable) {
error = true
decryptCountDownLatch.countDown()
}
}
)
mTestHelper.await(decryptCountDownLatch)
error shouldBe true
mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromPassphrase(
"A bad passphrase",
key1Info.content?.passphrase?.salt ?: "",
key1Info.content?.passphrase?.iterations ?: 0,
null)
)
}
// Now try with correct key
mTestHelper.doSync<String> {
mTestHelper.runBlockingTest {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromPassphrase(
passphrase,
key1Info.content?.passphrase?.salt ?: "",
key1Info.content?.passphrase?.iterations ?: 0,
null),
it
null)
)
}
@ -321,15 +299,15 @@ class QuadSTests : InstrumentedTest {
private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService
val creationInfo = mTestHelper.doSync<SsssKeyCreationInfo> {
quadS.generateKey(keyId, null, keyId, emptyKeySigner, it)
val creationInfo = mTestHelper.runBlockingTest {
quadS.generateKey(keyId, null, keyId, emptyKeySigner)
}
assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
if (asDefault) {
mTestHelper.doSync<Unit> {
quadS.setDefaultKey(keyId, it)
mTestHelper.runBlockingTest {
quadS.setDefaultKey(keyId)
}
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
@ -340,21 +318,20 @@ class QuadSTests : InstrumentedTest {
private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService
val creationInfo = mTestHelper.doSync<SsssKeyCreationInfo> {
val creationInfo = mTestHelper.runBlockingTest {
quadS.generateKeyWithPassphrase(
keyId,
keyId,
passphrase,
emptyKeySigner,
null,
it)
null)
}
assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
if (asDefault) {
val setDefaultLatch = CountDownLatch(1)
quadS.setDefaultKey(keyId, TestMatrixCallback(setDefaultLatch))
mTestHelper.await(setDefaultLatch)
mTestHelper.runBlockingTest {
quadS.setDefaultKey(keyId)
}
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}

View file

@ -593,16 +593,14 @@ class SASTest : InstrumentedTest {
requestID!!,
cryptoTestData.roomId,
bobSession.myUserId,
bobSession.sessionParams.deviceId!!,
null)
bobSession.sessionParams.deviceId!!)
bobVerificationService.beginKeyVerificationInDMs(
VerificationMethod.SAS,
requestID!!,
cryptoTestData.roomId,
aliceSession.myUserId,
aliceSession.sessionParams.deviceId!!,
null)
aliceSession.sessionParams.deviceId!!)
// we should reach SHOW SAS on both
var alicePovTx: SasVerificationTransaction?

View file

@ -17,115 +17,38 @@
package org.matrix.android.sdk.session.search
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.api.session.search.SearchResult
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestData
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.TestConstants
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class SearchMessagesTest : InstrumentedTest {
private val MESSAGE = "Lorem ipsum dolor sit amet"
companion object {
private const val MESSAGE = "Lorem ipsum dolor sit amet"
}
private val commonTestHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
@Test
fun sendTextMessageAndSearchPartOfItUsingSession() {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(10))
aliceTimeline.start()
commonTestHelper.sendTextMessage(
roomFromAlicePOV,
MESSAGE,
2)
run {
val lock = CountDownLatch(1)
val eventListener = commonTestHelper.createEventListener(lock) { snapshot ->
snapshot.count { it.root.content.toModel<MessageContent>()?.body?.startsWith(MESSAGE).orFalse() } == 2
}
aliceTimeline.addListener(eventListener)
commonTestHelper.await(lock)
val data = commonTestHelper.runBlockingTest {
aliceSession
.searchService()
.search(
searchTerm = "lore",
limit = 10,
includeProfile = true,
afterLimit = 0,
beforeLimit = 10,
orderByRecent = true,
nextBatch = null,
roomId = aliceRoomId
)
}
assertTrue(data.results?.size == 2)
assertTrue(
data.results
?.all {
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
}.orFalse()
)
aliceTimeline.removeAllListeners()
cryptoTestData.cleanUp(commonTestHelper)
}
aliceSession.startSync(true)
}
@Test
fun sendTextMessageAndSearchPartOfItUsingRoom() {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(10))
aliceTimeline.start()
commonTestHelper.sendTextMessage(
roomFromAlicePOV,
MESSAGE,
2)
run {
var lock = CountDownLatch(1)
val eventListener = commonTestHelper.createEventListener(lock) { snapshot ->
snapshot.count { it.root.content.toModel<MessageContent>()?.body?.startsWith(MESSAGE).orFalse() } == 2
}
aliceTimeline.addListener(eventListener)
commonTestHelper.await(lock)
lock = CountDownLatch(1)
roomFromAlicePOV
doTest { cryptoTestData ->
cryptoTestData.firstSession
.searchService()
.search(
searchTerm = "lore",
limit = 10,
@ -134,32 +57,64 @@ class SearchMessagesTest : InstrumentedTest {
beforeLimit = 10,
orderByRecent = true,
nextBatch = null,
callback = object : MatrixCallback<SearchResult> {
override fun onSuccess(data: SearchResult) {
super.onSuccess(data)
assertTrue(data.results?.size == 2)
assertTrue(
data.results
?.all {
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
}.orFalse()
)
lock.countDown()
}
override fun onFailure(failure: Throwable) {
super.onFailure(failure)
fail(failure.localizedMessage)
lock.countDown()
}
}
roomId = cryptoTestData.roomId
)
lock.await(TestConstants.timeOutMillis, TimeUnit.MILLISECONDS)
}
}
aliceTimeline.removeAllListeners()
cryptoTestData.cleanUp(commonTestHelper)
@Test
fun sendTextMessageAndSearchPartOfItUsingRoom() {
doTest { cryptoTestData ->
cryptoTestData.firstSession
.getRoom(cryptoTestData.roomId)!!
.search(
searchTerm = "lore",
limit = 10,
includeProfile = true,
afterLimit = 0,
beforeLimit = 10,
orderByRecent = true,
nextBatch = null
)
}
}
private fun doTest(block: suspend (CryptoTestData) -> SearchResult) {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(10))
aliceTimeline.start()
val lock = CountDownLatch(1)
val eventListener = commonTestHelper.createEventListener(lock) { snapshot ->
snapshot.count { it.root.content.toModel<MessageContent>()?.body?.startsWith(MESSAGE).orFalse() } == 2
}
aliceSession.startSync(true)
aliceTimeline.addListener(eventListener)
commonTestHelper.sendTextMessage(
roomFromAlicePOV,
MESSAGE,
2)
commonTestHelper.await(lock)
val data = commonTestHelper.runBlockingTest {
block.invoke(cryptoTestData)
}
assertTrue(data.results?.size == 2)
assertTrue(
data.results
?.all {
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
}.orFalse()
)
aliceTimeline.removeAllListeners()
cryptoTestData.cleanUp(commonTestHelper)
}
}

View file

@ -25,9 +25,12 @@ import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.api.network.ApiInterceptorListener
import org.matrix.android.sdk.api.network.ApiPath
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.di.DaggerMatrixComponent
import org.matrix.android.sdk.internal.network.ApiInterceptor
import org.matrix.android.sdk.internal.network.UserAgentHolder
import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
import org.matrix.olm.OlmManager
@ -49,6 +52,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
@Inject internal lateinit var olmManager: OlmManager
@Inject internal lateinit var sessionManager: SessionManager
@Inject internal lateinit var homeServerHistoryService: HomeServerHistoryService
@Inject internal lateinit var apiInterceptor: ApiInterceptor
init {
Monarchy.init(context)
@ -73,6 +77,14 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
return legacySessionImporter
}
fun registerApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
apiInterceptor.addListener(path, listener)
}
fun unregisterApiInterceptorListener(path: ApiPath, listener: ApiInterceptorListener) {
apiInterceptor.removeListener(path, listener)
}
companion object {
private lateinit var instance: Matrix

View file

@ -18,9 +18,10 @@ package org.matrix.android.sdk.api
interface RoomDisplayNameFallbackProvider {
fun getNameForRoomInvite(): String
fun getNameForEmptyRoom(): String
fun getNameFor2members(name1: String?, name2: String?): String
fun getNameFor3members(name1: String?, name2: String?, name3: String?): String
fun getNameFor4members(name1: String?, name2: String?, name3: String?, name4: String?): String
fun getNameFor4membersAndMore(name1: String?, name2: String?, name3: String?, remainingCount: Int): String
fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List<String>): String
fun getNameFor1member(name: String): String
fun getNameFor2members(name1: String, name2: String): String
fun getNameFor3members(name1: String, name2: String, name3: String): String
fun getNameFor4members(name1: String, name2: String, name3: String, name4: String): String
fun getNameFor4membersAndMore(name1: String, name2: String, name3: String, remainingCount: Int): String
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
* Copyright 2021 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.
@ -14,11 +14,11 @@
* limitations under the License.
*/
package org.matrix.android.sdk.api.util
package org.matrix.android.sdk.api.auth.registration
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.failure.Failure
/**
* Simple MatrixCallback implementation which delegate its calls to another callback
*/
open class MatrixCallbackDelegate<T>(private val callback: MatrixCallback<T>) : MatrixCallback<T> by callback
sealed class RegistrationAvailability {
object Available : RegistrationAvailability()
data class NotAvailable(val failure: Failure.ServerError) : RegistrationAvailability()
}

View file

@ -36,6 +36,8 @@ interface RegistrationWizard {
suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult
suspend fun registrationAvailable(userName: String): RegistrationAvailability
val currentThreePid: String?
// True when login and password has been sent with success to the homeserver

View file

@ -37,6 +37,18 @@ fun Throwable.shouldBeRetried(): Boolean {
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
}
/**
* Get the retry delay in case of rate limit exceeded error, adding 100 ms, of defaultValue otherwise
*/
fun Throwable.getRetryDelay(defaultValue: Long): Long {
return (this as? Failure.ServerError)
?.error
?.takeIf { it.code == MatrixError.M_LIMIT_EXCEEDED }
?.retryAfterMillis
?.plus(100L)
?: defaultValue
}
fun Throwable.isInvalidPassword(): Boolean {
return this is Failure.ServerError
&& error.code == MatrixError.M_FORBIDDEN
@ -53,13 +65,16 @@ fun Throwable.isInvalidUIAAuth(): Boolean {
* Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible
*/
fun Throwable.toRegistrationFlowResponse(): RegistrationFlowResponse? {
return if (this is Failure.OtherServerError && httpCode == 401) {
return if (this is Failure.OtherServerError
&& httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED /* 401 */) {
tryOrNull {
MoshiProvider.providesMoshi()
.adapter(RegistrationFlowResponse::class.java)
.fromJson(errorBody)
}
} else if (this is Failure.ServerError && httpCode == 401 && error.code == MatrixError.M_FORBIDDEN) {
} else if (this is Failure.ServerError
&& httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED /* 401 */
&& error.code == MatrixError.M_FORBIDDEN) {
// This happens when the submission for this stage was bad (like bad password)
if (error.session != null && error.flows != null) {
RegistrationFlowResponse(
@ -75,3 +90,11 @@ fun Throwable.toRegistrationFlowResponse(): RegistrationFlowResponse? {
null
}
}
fun Throwable.isRegistrationAvailabilityError(): Boolean {
return this is Failure.ServerError
&& httpCode == HttpsURLConnection.HTTP_BAD_REQUEST /* 400 */
&& (error.code == MatrixError.M_USER_IN_USE
|| error.code == MatrixError.M_INVALID_USERNAME
|| error.code == MatrixError.M_EXCLUSIVE)
}

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2021 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.network
interface ApiInterceptorListener {
fun onApiResponse(path: ApiPath, response: String)
}

View file

@ -0,0 +1,183 @@
/*
* Copyright (c) 2021 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.network
import org.matrix.android.sdk.internal.network.NetworkConstants
enum class ApiPath(val path: String, val method: String) {
// AuthApi
VERSIONS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "versions", "GET"),
REGISTER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register", "POST"),
ADD_3PID(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register/{threePid}/requestToken", "POST"),
LOGIN_FLOWS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login", "GET"),
LOGIN(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login", "POST"),
RESET_PASSWORD(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/password/email/requestToken", "POST"),
RESET_PASSWORD_MAIL_CONFIRMED(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/password", "POST"),
// DirectoryApi
ROOM_ID_BY_ALIAS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}", "GET"),
ROOM_DIRECTORY_VISIBILITY(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}", "GET"),
SET_ROOM_DIRECTORY_VISIBILITY(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/list/room/{roomId}", "PUT"),
ADD_ROOM_ALIAS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}", "PUT"),
DELETE_ROOM_ALIAS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}", "DELETE"),
// CryptoApi
GET_DEVICES(NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices", "GET"),
GET_DEVICE_INFO(NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices/{deviceId}", "GET"),
UPLOAD_KEYS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/upload", "POST"),
DOWNLOAD_KEYS_FOR_USERS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/query", "POST"),
UPLOAD_SIGNING_KEYS(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "keys/device_signing/upload", "POST"),
UPLOAD_SIGNATURES(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "keys/signatures/upload", "POST"),
CLAIM_ONE_TIME_KEYS_FOR_USERS_DEVICES(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/claim", "POST"),
SEND_TO_DEVICE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "sendToDevice/{eventType}/{txnId}", "PUT"),
DELETE_DEVICE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices/{device_id}", "DELETE"),
UPDATE_DEVICE_INFO(NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices/{device_id}", "PUT"),
GET_KEY_CHANGES(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/changes", "GET"),
// RoomKeysApi
CREATE_KEYS_BACKUP_VERSION(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version", "POST"),
GET_KEYS_BACKUP_LAST_VERSION(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version", "GET"),
GET_KEYS_BACKUP_VERSION(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version/{version}", "GET"),
UPDATE_KEYS_BACKUP_VERSION(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version/{version}", "PUT"),
STORE_ROOM_SESSION_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}", "PUT"),
STORE_ROOM_SESSIONS_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}", "PUT"),
STORE_SESSIONS_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys", "PUT"),
GET_ROOM_SESSION_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}", "GET"),
GET_ROOM_SESSIONS_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}", "GET"),
GET_SESSIONS_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys", "GET"),
DELETE_ROOM_SESSION_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}", "DELETE"),
DELETE_ROOM_SESSIONS_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}", "DELETE"),
DELETE_SESSIONS_DATA(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys", "DELETE"),
DELETE_BACKUP(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version/{version}", "DELETE"),
// AccountApi
CHANGE_PASSWORD(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/password", "POST"),
DEACTIVATE_ACCOUNT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/deactivate", "POST"),
// SearchApi
SEARCH(NetworkConstants.URI_API_PREFIX_PATH_R0 + "search", "POST"),
// FederationApi
GET_FEDERATION_VERSION(NetworkConstants.URI_FEDERATION_PATH + "version", "GET"),
// VoipApi
GET_TURN_SERVER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "voip/turnServer", "GET"),
// PushGatewayApi
NOTIFY_PUSH_GATEWAY(NetworkConstants.URI_PUSH_GATEWAY_PREFIX_PATH + "notify", "POST"),
// GroupApi
GET_GROUP_SUMMARY(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/summary", "GET"),
GET_GROUP_ROOMS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/rooms", "GET"),
GET_GROUP_USERS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/users", "GET"),
// CapabilitiesApi
GET_CAPABILITIES(NetworkConstants.URI_API_PREFIX_PATH_R0 + "capabilities", "GET"),
GET_VERSIONS(NetworkConstants.URI_API_PREFIX_PATH_ + "versions", "GET"),
PING(NetworkConstants.URI_API_PREFIX_PATH_ + "versions", "GET"),
// IdentityApi
GET_ACCOUNT(NetworkConstants.URI_IDENTITY_PATH_V2 + "account", "GET"),
LOGOUT(NetworkConstants.URI_IDENTITY_PATH_V2 + "account/logout", "POST"),
IDENTITY_HAS_DETAILS(NetworkConstants.URI_IDENTITY_PATH_V2 + "hash_details", "GET"),
LOOKUP(NetworkConstants.URI_IDENTITY_PATH_V2 + "lookup", "POST"),
REQUEST_TOKEN_TO_BIND_EMAIL(NetworkConstants.URI_IDENTITY_PATH_V2 + "validate/email/requestToken", "POST"),
REQUEST_TOKEN_TO_BIND_MSISDN(NetworkConstants.URI_IDENTITY_PATH_V2 + "validate/msisdn/requestToken", "POST"),
SUBMIT_TOKEN(NetworkConstants.URI_IDENTITY_PATH_V2 + "validate/{medium}/submitToken", "POST"),
// FilterApi
UPLOAD_FILTER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/filter", "POST"),
GET_FILTER_BY_ID(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/filter/{filterId}", "GET"),
// IndentityAuthApi
IDENTITY_REGISTER(NetworkConstants.URI_IDENTITY_PATH_V2 + "account/register", "POST"),
// MediaApi
GET_MEDIA_CONFIG(NetworkConstants.URI_API_MEDIA_PREFIX_PATH_R0 + "config", "GET"),
GET_PREVIEW_URL_DATA(NetworkConstants.URI_API_MEDIA_PREFIX_PATH_R0 + "preview_url", "GET"),
// OpenIdApi
OPEN_ID_TOKEN(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/openid/request_token", "POST"),
// ProfileApi
GET_PROFILE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "profile/{userId}", "GET"),
GET_THREE_PIDS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid", "GET"),
SET_DISPLAY_NAME(NetworkConstants.URI_API_PREFIX_PATH_R0 + "profile/{userId}/displayname", "PUT"),
SET_AVATAR_URL(NetworkConstants.URI_API_PREFIX_PATH_R0 + "profile/{userId}/avatar_url", "PUT"),
BIND_THREE_PID(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "account/3pid/bind", "POST"),
UNBIND_THREE_PID(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "account/3pid/unbind", "POST"),
ADD_EMAIL(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/email/requestToken", "POST"),
ADD_MSISDN(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/msisdn/requestToken", "POST"),
FINALIZE_ADD_THREE_PID(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/add", "POST"),
DELETE_THREE_PID(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/delete", "POST"),
// PusherRulesApi
GET_ALL_PUSHER_RULES(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushrules/", "GET"),
UPDATE_ENABLE_PUSH_RULE_STATUS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushrules/global/{kind}/{ruleId}/enabled", "PUT"),
UPDATE_PUSH_RULE_ACTIONS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushrules/global/{kind}/{ruleId}/actions", "PUT"),
DELETE_PUSH_RULE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushrules/global/{kind}/{ruleId}", "DELETE"),
ADD_PUSH_RULE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushrules/global/{kind}/{ruleId}", "PUT"),
// PusherApi
GET_PUSHERS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushers", "GET"),
SET_PUSHER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "pushers/set", "POST"),
// SignOutApi
LOGIN_AGAIN(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login", "POST"),
SIGN_OUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "logout", "POST"),
// RoomApi
GET_PUBLIC_ROOMS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "publicRooms", "POST"),
CREATE_ROOM(NetworkConstants.URI_API_PREFIX_PATH_R0 + "createRoom", "POST"),
GET_ROOM_MESSAGES_FROM(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/messages", "GET"),
GET_MEMBERS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/members", "GET"),
SEND_EVENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/send/{eventType}/{txId}", "PUT"),
GET_CONTEXT_OF_EVENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/context/{eventId}", "GET"),
GET_EVENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/event/{eventId}", "GET"),
SEND_READ_MARKER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/read_markers", "POST"),
INVITE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite", "POST"),
INVITE_USING_THREE_PID(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite", "POST"),
SEND_STATE_EVENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state/{state_event_type}", "PUT"),
SEND_STATE_EVENT_WITH_STATE_KEY(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state/{state_event_type}/{state_key}", "PUT"),
GET_ROOM_STATE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state", "GET"),
SEND_RELATION(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/send_relation/{parent_id}/{relation_type}/{event_type}", "POST"),
GET_RELATIONS(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "rooms/{roomId}/relations/{eventId}/{relationType}/{eventType}", "GET"),
JOIN_ROOM(NetworkConstants.URI_API_PREFIX_PATH_R0 + "join/{roomIdOrAlias}", "POST"),
LEAVE_ROOM(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/leave", "POST"),
BAN_USER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/ban", "POST"),
UNBAN_USER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/unban", "POST"),
KICK_USER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/kick", "POST"),
REDACT_EVENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/redact/{eventId}/{txnId}", "PUT"),
REPORT_CONTENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/report/{eventId}", "POST"),
GET_ALIASES(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "org.matrix.msc2432/rooms/{roomId}/aliases", "GET"),
SEND_TYPING_STATE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/typing/{userId}", "PUT"),
PUT_TAG(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/rooms/{roomId}/tags/{tag}", "PUT"),
DELETE_TAG(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/rooms/{roomId}/tags/{tag}", "DELETE"),
// SyncApi
SYNC(NetworkConstants.URI_API_PREFIX_PATH_R0 + "sync", "GET"),
// ThirdPartyApi
THIRD_PARTY_PROTOCOLS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "thirdparty/protocols", "GET"),
THIRD_PARTY_USER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "thirdparty/protocols/user/{protocol}", "GET"),
// SearchUserApi
SEARCH_USERS(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user_directory/search", "POST"),
// AccountDataApi
SET_ACCOUNT_DATA(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/account_data/{type}", "PUT")
}

View file

@ -39,6 +39,8 @@ interface PushRuleService {
fun removePushRuleListener(listener: PushRuleListener)
fun getActions(event: Event): List<Action>
// fun fulfilledBingRule(event: Event, rules: List<PushRule>): PushRule?
interface PushRuleListener {

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2021 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.query
enum class RoomCategoryFilter {
ONLY_DM,
ONLY_ROOMS,
ONLY_WITH_NOTIFICATIONS,
ALL
}

View file

@ -0,0 +1,23 @@
/*
* Copyright 2021 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.query
data class RoomTagQueryFilter(
val isFavorite: Boolean?,
val isLowPriority: Boolean?,
val isServerNotice: Boolean?
)

View file

@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.session.call.CallSignalingService
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.EventService
import org.matrix.android.sdk.api.session.file.ContentDownloadStateTracker
import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.group.GroupService
@ -68,6 +69,7 @@ interface Session :
SignOutService,
FilterService,
TermsService,
EventService,
ProfileService,
PushRuleService,
PushersService,

View file

@ -17,9 +17,7 @@
package org.matrix.android.sdk.api.session.accountdata
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.Optional
interface AccountDataService {
@ -48,5 +46,5 @@ interface AccountDataService {
/**
* Update the account data with the provided type and the provided account data content
*/
fun updateAccountData(type: String, content: Content, callback: MatrixCallback<Unit>? = null): Cancelable
suspend fun updateAccountData(type: String, content: Content)
}

View file

@ -16,7 +16,6 @@
package org.matrix.android.sdk.api.session.crypto.verification
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.LocalEcho
@ -79,8 +78,7 @@ interface VerificationService {
transactionId: String,
roomId: String,
otherUserId: String,
otherDeviceId: String,
callback: MatrixCallback<String>?): String?
otherDeviceId: String): String
/**
* Returns false if the request is unknown

View file

@ -1,5 +1,5 @@
/*
* Copyright 2020 The Matrix.org Foundation C.I.C.
* Copyright (c) 2021 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.
@ -14,21 +14,16 @@
* limitations under the License.
*/
package org.matrix.android.sdk.internal.crypto.model
package org.matrix.android.sdk.api.session.events
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event
class MXQueuedEncryption {
interface EventService {
/**
* The data to encrypt.
* Ask the homeserver for an event content. The SDK will try to decrypt it if it is possible
* The result will not be stored into cache
*/
var eventContent: Content? = null
var eventType: String? = null
/**
* the asynchronous callback
*/
var apiCallback: MatrixCallback<Content>? = null
suspend fun getEvent(roomId: String,
eventId: String): Event
}

View file

@ -289,3 +289,7 @@ fun Event.getRelationContent(): RelationDefaultContent? {
fun Event.isReply(): Boolean {
return getRelationContent()?.inReplyTo?.eventId != null
}
fun Event.isEdition(): Boolean {
return getRelationContent()?.takeIf { it.type == RelationType.REPLACE }?.eventId != null
}

View file

@ -17,11 +17,9 @@
package org.matrix.android.sdk.api.session.file
import android.net.Uri
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
import org.matrix.android.sdk.api.session.room.model.message.getFileName
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
import java.io.File
@ -41,20 +39,17 @@ interface FileService {
* Download a file.
* Result will be a decrypted file, stored in the cache folder. url parameter will be used to create unique filename to avoid name collision.
*/
fun downloadFile(fileName: String,
suspend fun downloadFile(fileName: String,
mimeType: String?,
url: String?,
elementToDecrypt: ElementToDecrypt?,
callback: MatrixCallback<File>): Cancelable
elementToDecrypt: ElementToDecrypt?): File
fun downloadFile(messageContent: MessageWithAttachmentContent,
callback: MatrixCallback<File>): Cancelable =
suspend fun downloadFile(messageContent: MessageWithAttachmentContent): File =
downloadFile(
fileName = messageContent.getFileName(),
mimeType = messageContent.mimeType,
url = messageContent.getFileUrl(),
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(),
callback = callback
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt()
)
fun isFileInCache(mxcUrl: String?,

View file

@ -16,9 +16,6 @@
package org.matrix.android.sdk.api.session.identity
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.util.Cancelable
/**
* Provides access to the identity server configuration and services identity server can provide
*/
@ -40,55 +37,55 @@ interface IdentityService {
* See https://matrix.org/docs/spec/identity_service/latest#status-check
* RiotX SDK only supports identity server API v2
*/
fun isValidIdentityServer(url: String, callback: MatrixCallback<Unit>): Cancelable
suspend fun isValidIdentityServer(url: String)
/**
* Update the identity server url.
* If successful, any previous identity server will be disconnected.
* In case of error, any previous identity server will remain configured.
* @param url the new url.
* @param callback will notify the user if change is successful. The String will be the final url of the identity server.
* @return The String will be the final url of the identity server.
* The SDK can prepend "https://" for instance.
*/
fun setNewIdentityServer(url: String, callback: MatrixCallback<String>): Cancelable
suspend fun setNewIdentityServer(url: String): String
/**
* Disconnect (logout) from the current identity server
*/
fun disconnect(callback: MatrixCallback<Unit>): Cancelable
suspend fun disconnect()
/**
* This will ask the identity server to send an email or an SMS to let the user confirm he owns the ThreePid
*/
fun startBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
suspend fun startBindThreePid(threePid: ThreePid)
/**
* This will cancel a pending binding of threePid.
*/
fun cancelBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
suspend fun cancelBindThreePid(threePid: ThreePid)
/**
* This will ask the identity server to send an new email or a new SMS to let the user confirm he owns the ThreePid
*/
fun sendAgainValidationCode(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
suspend fun sendAgainValidationCode(threePid: ThreePid)
/**
* Submit the code that the identity server has sent to the user (in email or SMS)
* Once successful, you will have to call [finalizeBindThreePid]
* @param code the code sent to the user
*/
fun submitValidationToken(threePid: ThreePid, code: String, callback: MatrixCallback<Unit>): Cancelable
suspend fun submitValidationToken(threePid: ThreePid, code: String)
/**
* This will perform the actual association of ThreePid and Matrix account
*/
fun finalizeBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
suspend fun finalizeBindThreePid(threePid: ThreePid)
/**
* Unbind a threePid
* The request will actually be done on the homeserver
*/
fun unbindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
suspend fun unbindThreePid(threePid: ThreePid)
/**
* Search MatrixId of users providing email and phone numbers
@ -96,7 +93,7 @@ interface IdentityService {
* 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
suspend fun lookUp(threePids: List<ThreePid>): List<FoundThreePid>
/**
* Return the current user consent for the current identity server, which has been stored using [setUserConsent].
@ -120,9 +117,9 @@ interface IdentityService {
* A lookup will be performed, but also pending binding state will be restored
*
* @param threePids the list of threePid the user owns (retrieved form the homeserver)
* @param callback onSuccess will be called with a map of ThreePid -> SharedState
* @return a map of ThreePid -> SharedState
*/
fun getShareStatus(threePids: List<ThreePid>, callback: MatrixCallback<Map<ThreePid, SharedState>>): Cancelable
suspend fun getShareStatus(threePids: List<ThreePid>): Map<ThreePid, SharedState>
fun addListener(listener: IdentityServiceListener)
fun removeListener(listener: IdentityServiceListener)

View file

@ -19,10 +19,8 @@ package org.matrix.android.sdk.api.session.profile
import android.net.Uri
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.api.util.Optional
@ -41,14 +39,14 @@ interface ProfileService {
* @param userId the userId param to look for
*
*/
fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable
suspend fun getDisplayName(userId: String): Optional<String>
/**
* Update the display name for this user
* @param userId the userId to update the display name of
* @param newDisplayName the new display name of the user
*/
fun setDisplayName(userId: String, newDisplayName: String, matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun setDisplayName(userId: String, newDisplayName: String)
/**
* Update the avatar for this user
@ -56,14 +54,14 @@ interface ProfileService {
* @param newAvatarUri the new avatar uri of the user
* @param fileName the fileName of selected image
*/
fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String, matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String)
/**
* Return the current avatarUrl for this user.
* @param userId the userId param to look for
*
*/
fun getAvatarUrl(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable
suspend fun getAvatarUrl(userId: String): Optional<String>
/**
* Get the combined profile information for this user.
@ -71,7 +69,7 @@ interface ProfileService {
* @param userId the userId param to look for
*
*/
fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable
suspend fun getProfile(userId: String): JsonDict
/**
* Get the current user 3Pids
@ -97,28 +95,26 @@ interface ProfileService {
/**
* Add a 3Pids. This is the first step to add a ThreePid to an account. Then the threePid will be added to the pending threePid list.
*/
fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun addThreePid(threePid: ThreePid)
/**
* Validate a code received by text message
*/
fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun submitSmsCode(threePid: ThreePid.Msisdn, code: String)
/**
* Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid
*/
fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor,
matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor)
/**
* Cancel adding a threepid. It will remove locally stored data about this ThreePid
*/
fun cancelAddingThreePid(threePid: ThreePid,
matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun cancelAddingThreePid(threePid: ThreePid)
/**
* Remove a 3Pid from the Matrix account.
*/
fun deleteThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun deleteThreePid(threePid: ThreePid)
}

View file

@ -16,8 +16,6 @@
package org.matrix.android.sdk.api.session.pushers
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.util.Cancelable
import java.util.UUID
interface PushersService {
@ -75,16 +73,15 @@ interface PushersService {
* @param callback callback to know if the push gateway has accepted the request. In this case, the app should receive a Push with the provided eventId.
* In case of error, PusherRejected failure can happen. In this case it means that the pushkey is not valid.
*/
fun testPush(url: String,
appId: String,
pushkey: String,
eventId: String,
callback: MatrixCallback<Unit>): Cancelable
suspend fun testPush(url: String,
appId: String,
pushkey: String,
eventId: String)
/**
* Remove the http pusher
*/
fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>): Cancelable
suspend fun removeHttpPusher(pushkey: String, appId: String)
/**
* Get the current pushers, as a LiveData

View file

@ -17,7 +17,6 @@
package org.matrix.android.sdk.api.session.room
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.room.alias.AliasService
import org.matrix.android.sdk.api.session.room.call.RoomCallService
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
@ -35,7 +34,6 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineService
import org.matrix.android.sdk.api.session.room.typing.TypingService
import org.matrix.android.sdk.api.session.room.uploads.UploadsService
import org.matrix.android.sdk.api.session.search.SearchResult
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.Optional
/**
@ -86,12 +84,11 @@ interface Room :
* @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,
nextBatch: String?,
orderByRecent: Boolean,
limit: Int,
beforeLimit: Int,
afterLimit: Int,
includeProfile: Boolean,
callback: MatrixCallback<SearchResult>): Cancelable
includeProfile: Boolean): SearchResult
}

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.api.session.room
import androidx.lifecycle.LiveData
import androidx.paging.PagedList
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
@ -24,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.peeking.PeekResult
import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
@ -178,4 +180,29 @@ interface RoomService {
* This call will try to gather some information on this room, but it could fail and get nothing more
*/
fun peekRoom(roomIdOrAlias: String, callback: MatrixCallback<PeekResult>)
/**
* TODO Doc
*/
fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,
pagedListConfig: PagedList.Config = defaultPagedListConfig): LiveData<PagedList<RoomSummary>>
/**
* TODO Doc
*/
fun getFilteredPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,
pagedListConfig: PagedList.Config = defaultPagedListConfig): UpdatableFilterLivePageResult
/**
* TODO Doc
*/
fun getNotificationCountForRooms(queryParams: RoomSummaryQueryParams): RoomAggregateNotificationCount
private val defaultPagedListConfig
get() = PagedList.Config.Builder()
.setPageSize(10)
.setInitialLoadSizeHint(20)
.setEnablePlaceholders(false)
.setPrefetchDistance(10)
.build()
}

View file

@ -17,6 +17,8 @@
package org.matrix.android.sdk.api.session.room
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.query.RoomCategoryFilter
import org.matrix.android.sdk.api.query.RoomTagQueryFilter
import org.matrix.android.sdk.api.session.room.model.Membership
fun roomSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): RoomSummaryQueryParams {
@ -31,7 +33,9 @@ data class RoomSummaryQueryParams(
val roomId: QueryStringValue,
val displayName: QueryStringValue,
val canonicalAlias: QueryStringValue,
val memberships: List<Membership>
val memberships: List<Membership>,
val roomCategoryFilter: RoomCategoryFilter?,
val roomTagQueryFilter: RoomTagQueryFilter?
) {
class Builder {
@ -40,12 +44,16 @@ data class RoomSummaryQueryParams(
var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
var canonicalAlias: QueryStringValue = QueryStringValue.NoCondition
var memberships: List<Membership> = Membership.all()
var roomCategoryFilter: RoomCategoryFilter? = RoomCategoryFilter.ALL
var roomTagQueryFilter: RoomTagQueryFilter? = null
fun build() = RoomSummaryQueryParams(
roomId = roomId,
displayName = displayName,
canonicalAlias = canonicalAlias,
memberships = memberships
memberships = memberships,
roomCategoryFilter = roomCategoryFilter,
roomTagQueryFilter = roomTagQueryFilter
)
}
}

View file

@ -1,11 +1,11 @@
/*
* Copyright 2019 New Vector Ltd
* Copyright (c) 2021 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
* 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,
@ -14,12 +14,14 @@
* limitations under the License.
*/
package im.vector.app.features.home
package org.matrix.android.sdk.api.session.room
import im.vector.app.core.utils.BehaviorDataSource
import androidx.lifecycle.LiveData
import androidx.paging.PagedList
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class HomeRoomListDataSource @Inject constructor() : BehaviorDataSource<List<RoomSummary>>()
interface UpdatableFilterLivePageResult {
val livePagedList: LiveData<PagedList<RoomSummary>>
fun updateQuery(queryParams: RoomSummaryQueryParams)
}

View file

@ -17,10 +17,8 @@
package org.matrix.android.sdk.api.session.room.members
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.api.util.Cancelable
/**
* This interface defines methods to handling membership. It's implemented at the room level.
@ -29,9 +27,8 @@ interface MembershipService {
/**
* This methods load all room members if it was done yet.
* @return a [Cancelable]
*/
fun loadRoomMembersIfNeeded(matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun loadRoomMembersIfNeeded()
/**
* Return the roomMember with userId or null.
@ -60,47 +57,35 @@ interface MembershipService {
/**
* Invite a user in the room
*/
fun invite(userId: String,
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
suspend fun invite(userId: String, reason: String? = null)
/**
* Invite a user with email or phone number in the room
*/
fun invite3pid(threePid: ThreePid,
callback: MatrixCallback<Unit>): Cancelable
suspend fun invite3pid(threePid: ThreePid)
/**
* Ban a user from the room
*/
fun ban(userId: String,
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
suspend fun ban(userId: String, reason: String? = null)
/**
* Unban a user from the room
*/
fun unban(userId: String,
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
suspend fun unban(userId: String, reason: String? = null)
/**
* Kick a user from the room
*/
fun kick(userId: String,
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
suspend fun kick(userId: String, reason: String? = null)
/**
* Join the room, or accept an invitation.
*/
fun join(reason: String? = null,
viaServers: List<String> = emptyList(),
callback: MatrixCallback<Unit>): Cancelable
suspend fun join(reason: String? = null, viaServers: List<String> = emptyList())
/**
* Leave the room, or reject an invitation.
*/
fun leave(reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
suspend fun leave(reason: String? = null)
}

View file

@ -23,24 +23,13 @@ import com.squareup.moshi.JsonClass
* Represents the membership of a user on a room
*/
@JsonClass(generateAdapter = false)
enum class Membership(val value: String) {
NONE("none"),
@Json(name = "invite")
INVITE("invite"),
@Json(name = "join")
JOIN("join"),
@Json(name = "knock")
KNOCK("knock"),
@Json(name = "leave")
LEAVE("leave"),
@Json(name = "ban")
BAN("ban");
enum class Membership {
NONE,
@Json(name = "invite") INVITE,
@Json(name = "join") JOIN,
@Json(name = "knock") KNOCK,
@Json(name = "leave") LEAVE,
@Json(name = "ban") BAN;
fun isLeft(): Boolean {
return this == KNOCK || this == LEAVE || this == BAN

View file

@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import timber.log.Timber
/**
* Class representing the EventType.STATE_ROOM_GUEST_ACCESS state event content
@ -26,14 +27,20 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class RoomGuestAccessContent(
// Required. Whether guests can join the room. One of: ["can_join", "forbidden"]
@Json(name = "guest_access") val guestAccess: GuestAccess? = null
)
@Json(name = "guest_access") val _guestAccess: String? = null
) {
val guestAccess: GuestAccess? = when (_guestAccess) {
"can_join" -> GuestAccess.CanJoin
"forbidden" -> GuestAccess.Forbidden
else -> {
Timber.w("Invalid value for GuestAccess: `$_guestAccess`")
null
}
}
}
@JsonClass(generateAdapter = false)
enum class GuestAccess(val value: String) {
@Json(name = "can_join")
CanJoin("can_join"),
@Json(name = "forbidden")
Forbidden("forbidden")
enum class GuestAccess {
@Json(name = "can_join") CanJoin,
@Json(name = "forbidden") Forbidden
}

View file

@ -18,8 +18,20 @@ package org.matrix.android.sdk.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import timber.log.Timber
@JsonClass(generateAdapter = true)
data class RoomHistoryVisibilityContent(
@Json(name = "history_visibility") val historyVisibility: RoomHistoryVisibility? = null
)
@Json(name = "history_visibility") val _historyVisibility: String? = null
) {
val historyVisibility: RoomHistoryVisibility? = when (_historyVisibility) {
"world_readable" -> RoomHistoryVisibility.WORLD_READABLE
"shared" -> RoomHistoryVisibility.SHARED
"invited" -> RoomHistoryVisibility.INVITED
"joined" -> RoomHistoryVisibility.JOINED
else -> {
Timber.w("Invalid value for RoomHistoryVisibility: `$_historyVisibility`")
null
}
}
}

View file

@ -24,17 +24,9 @@ import com.squareup.moshi.JsonClass
* Enum for [RoomJoinRulesContent] : https://matrix.org/docs/spec/client_server/r0.4.0#m-room-join-rules
*/
@JsonClass(generateAdapter = false)
enum class RoomJoinRules(val value: String) {
@Json(name = "public")
PUBLIC("public"),
@Json(name = "invite")
INVITE("invite"),
@Json(name = "knock")
KNOCK("knock"),
@Json(name = "private")
PRIVATE("private")
enum class RoomJoinRules {
@Json(name = "public") PUBLIC,
@Json(name = "invite") INVITE,
@Json(name = "knock") KNOCK,
@Json(name = "private") PRIVATE
}

View file

@ -19,11 +19,23 @@ package org.matrix.android.sdk.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import timber.log.Timber
/**
* Class representing the EventType.STATE_ROOM_JOIN_RULES state event content
*/
@JsonClass(generateAdapter = true)
data class RoomJoinRulesContent(
@Json(name = "join_rule") val joinRules: RoomJoinRules? = null
)
@Json(name = "join_rule") val _joinRules: String? = null
) {
val joinRules: RoomJoinRules? = when (_joinRules) {
"public" -> RoomJoinRules.PUBLIC
"invite" -> RoomJoinRules.INVITE
"knock" -> RoomJoinRules.KNOCK
"private" -> RoomJoinRules.PRIVATE
else -> {
Timber.w("Invalid value for RoomJoinRules: `$_joinRules`")
null
}
}
}

View file

@ -35,5 +35,5 @@ object MessageType {
const val MSGTYPE_STICKER_LOCAL = "org.matrix.android.sdk.sticker"
const val MSGTYPE_CONFETTI = "nic.custom.confetti"
const val MSGTYPE_SNOW = "nic.custom.snow"
const val MSGTYPE_SNOW = "io.element.effect.snowfall"
}

View file

@ -17,7 +17,6 @@
package org.matrix.android.sdk.api.session.room.read
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
import org.matrix.android.sdk.api.util.Optional
@ -35,17 +34,17 @@ interface ReadService {
/**
* Force the read marker to be set on the latest event.
*/
fun markAsRead(params: MarkAsReadParams = MarkAsReadParams.BOTH, callback: MatrixCallback<Unit>)
suspend fun markAsRead(params: MarkAsReadParams = MarkAsReadParams.BOTH)
/**
* Set the read receipt on the event with provided eventId.
*/
fun setReadReceipt(eventId: String, callback: MatrixCallback<Unit>)
suspend fun setReadReceipt(eventId: String)
/**
* Set the read marker on the event with provided eventId.
*/
fun setReadMarker(fullyReadEventId: String, callback: MatrixCallback<Unit>)
suspend fun setReadMarker(fullyReadEventId: String)
/**
* Check if an event is already read, ie. your read receipt is set on a more recent event.

Some files were not shown because too many files have changed in this diff Show more