Merge remote-tracking branch 'upstream/develop' into spaces

Change-Id: I10235a7a808ae66f5b00ad2e58c2aedf395e8e25

Conflicts:
	matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/summary/RoomAggregateNotificationCount.kt
	sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
	matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt
	vector/build.gradle
	vector/src/main/java/im/vector/app/core/extensions/TimelineEvent.kt
	vector/src/main/java/im/vector/app/features/configuration/VectorConfiguration.kt
	vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
	vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt
	vector/src/main/java/im/vector/app/features/home/HomeDrawerFragment.kt
	vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt
	vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt
	vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt
	vector/src/main/java/im/vector/app/features/home/room/list/RoomListAction.kt
	vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt
	vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt
	vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModelFactory.kt
	vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt
	vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomController.kt
	vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
	vector/src/main/java/im/vector/app/features/ui/SharedPreferencesUiStateRepository.kt
This commit is contained in:
SpiritCroc 2021-05-02 12:12:52 +02:00
commit 39359f7d24
462 changed files with 21807 additions and 2008 deletions

View file

@ -1,3 +1,47 @@
Changes in Element 1.1.7 (2021-XX-XX)
===================================================
Features ✨:
- Spaces beta
Improvements 🙌:
- Add ability to install APK from directly from Element (#2381)
- Delete and react to stickers (#3250)
Bugfix 🐛:
- Message states cosmetic changes (#3007)
- Fix exception in rxSingle (#3180)
- Do not invite the current user when creating a room (#3123)
- Fix color issues when the system theme is changed (#2738)
- Fix issues on Android 11 (#3067)
- Fix issue when opening encrypted files (#3186)
- Fix wording issue (#3242)
- Fix missing sender information after edits (#3184)
Translations 🗣:
-
SDK API changes ⚠️:
- RegistrationWizard.createAccount() parameters are now all optional, following Matrix spec (#3205)
Build 🧱:
- Upgrade to gradle 7
Test:
-
Other changes:
- New store descriptions
- `master` branch has been renamed to `main`. To apply change to your dev environment, run:
```sh
git branch -m master main
git fetch origin
git branch -u origin/main main
# And optionally
git remote prune origin
```
- Allow cleartext (non-SSL) connections to Matrix servers on LAN hosts (#3166)
Changes in Element 1.1.6 (2021-04-16)
===================================================

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-rc01"
implementation "androidx.recyclerview:recyclerview:1.2.0"
implementation 'com.google.android.material:material:1.3.0'
}

View file

@ -16,8 +16,8 @@ buildscript {
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.3'
classpath "com.likethesalad.android:string-reference:1.2.1"
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.4'
classpath "com.likethesalad.android:string-reference:1.2.2"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@ -51,7 +51,7 @@ allprojects {
}
}
maven {
url "http://dl.bintray.com/piasy/maven"
url "https://dl.bintray.com/piasy/maven"
content {
includeGroupByRegex "com\\.github\\.piasy"
}
@ -59,7 +59,7 @@ allprojects {
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
// Jitsi repo
maven {
url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-3.1.0"
url "https://github.com/vector-im/jitsi_libre_maven/raw/main/android-sdk-3.1.0"
// Note: to test Jitsi release you can use a local file like this:
// url "file:///Users/bmarty/workspaces/jitsi_libre_maven/android-sdk-3.1.0"
}

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.2

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.3

View file

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

View file

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

View file

@ -1,30 +1,39 @@
Element is a new type of messenger and collaboration app that:
Element is both a secure messenger and a productivity team collaboration app that is ideal for group chats while remote working. This chat app uses end-to-end encryption to provide powerful video conferencing, file sharing and voice calls.
1. Puts you in control to preserve your privacy
2. Lets you communicate with anyone in the Matrix network, and even beyond by integrating with apps such as Slack
3. Protects you from advertising, datamining and walled gardens
4. Secures you through end-to-end encryption, with cross-signing to verify others
<b>Elements features include:</b>
- Advanced online communication tools
- Fully encrypted messages to allow safer corporate communication, even for remote workers
- Decentralized chat based on the Matrix open source framework
- File sharing securely with encrypted data while managing projects
- Video chats with Voice over IP and screen sharing
- Easy integration with your favourite online collaboration tools, project management tools, VoIP services and other team messaging apps
Element is completely different from other messaging and collaboration apps because it is decentralised and open source.
Element is completely different from other messaging and collaboration apps. It operates on Matrix, an open network for secure messaging and decentralized communication. It allows self-hosting to give users maximum ownership and control of their data and messages.
Element lets you self-host - or choose a host - so that you have privacy, ownership and control of your data and conversations. It gives you access to an open network; so youre not just stuck speaking to other Element users only. And it is very secure.
<b>Privacy and encrypted messaging</b>
Element protects you from unwanted ads, data mining and walled gardens. It also secures all your data, one-to-one video and voice communication through end-to-end encryption and cross-signed device verification.
Element is able to do all this because it operates on Matrix - the standard for open, decentralised communication.
Element gives you control over your privacy while allowing you to communicate securely with anyone on the Matrix network, or other business collaboration tools by integrating with apps such as Slack.
Element puts you in control by letting you choose who hosts your conversations. From the Element app, you can choose to host in different ways:
<b>Element can be self-hosted</b>
To allow more control of your sensitive data and conversations, Element can be self-hosted or you can choose any Matrix-based host - the standard for open source, decentralized communication. Element gives you privacy, security compliance and integration flexibility.
<b>Own your data</b>
You decide where to keep your data and messages. Without the risk of data mining or access from third parties.
Element puts you in control in different ways:
1. Get a free account on the matrix.org public server hosted by the Matrix developers, or choose from thousands of public servers hosted by volunteers
2. Self-host your account by running a server on your own hardware
2. Self-host your account by running a server on your own IT infrastructure
3. Sign up for an account on a custom server by simply subscribing to the Element Matrix Services hosting platform
<b>Why choose Element?</b>
<b>Open messaging and collaboration</b>
You can chat with anyone on the Matrix network, whether theyre using Element, another Matrix app or even if they are using a different messaging app.
<b>OWN YOUR DATA</b>: You decide where to keep your data and messages. You own it and control it, not some MEGACORP that mines your data or gives access to third parties.
<b>Super secure</b>
Real end-to-end encryption (only those in the conversation can decrypt messages), and cross-signed device verification.
<b>OPEN MESSAGING AND COLLABORATION</b>: You can chat with anyone else in the Matrix network, whether theyre using Element or another Matrix app, and even if they are using a different messaging system of the likes of Slack, IRC or XMPP.
<b>Complete communication and integration</b>
Messaging, voice and video calls, file sharing, screen sharing and a whole bunch of integrations, bots and widgets. Build rooms, communities, stay in touch and get things done.
<b>SUPER-SECURE</b>: Real end-to-end encryption (only those in the conversation can decrypt messages), and cross-signing to verify the devices of conversation participants.
<b>COMPLETE COMMUNICATION</b>: Messaging, voice and video calls, file sharing, screen sharing and a whole bunch of integrations, bots and widgets. Build rooms, communities, stay in touch and get things done.
<b>EVERYWHERE YOU ARE</b>: Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io.
<b>Pick up where you left off</b>
Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io

View file

@ -1 +1 @@
Secure decentralised chat & VoIP. Keep your data safe from third parties.
Group messenger - encrypted messaging, group chat and video calls

View file

@ -1 +1 @@
Element (previously Riot.im)
Element - Secure Messenger

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.2

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.3

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.2

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.3

View file

@ -1,30 +1,30 @@
Element est une nouvelle application de messagerie et de collaboration qui :
Element est une nouvelle application de messagerie et de collaboration qui :
1) Vous place aux commandes de votre vie privée
2) Vous permet de communiquer avec n'importe qui du réseau Matrix, et plus encore par des intégrations d'autres applications comme Slack ou Discord
3) Vous protège de la publicité et de la collecte de données
4) Vous sécurise grâce à du chiffrement bout-à-bout, avec de la signature croisée pour authentifier les autres utilisateurs
1. Vous permet de préserver votre vie privée
2. Vous permet de communiquer avec nimporte qui sur réseau Matrix, et plus encore grâce aux intégrations dautres applications telles que Slack ou Discord
3. Vous protège de la publicité et de la collecte de données
4. Vous protège grâce au chiffrement de bout-à-bout et à la signature croisée pour authentifier les autres utilisateurs
Element est complètement différent des autres applications de messagerie et de collaboration puisque l'application est décentralisée et open-source.
Element est complètement différente des autres applications de messagerie et de collaboration puisque lapplication est décentralisée et open-source.
Element vous permet d'héberger vous-même -ou de choisir un hôte- vous permettant d'assurer votre vie privée, la propriété et le contrôle de vos données et de vos conversations. Cela vous offre l'accès à un réseau ouvert, vous n'êtes donc pas condamné à parler à d'autres utilisateurs d'Element seulement. Et c'est très sécurisé.
Element vous permet dhéberger vous-même ou de choisir un hôte vous permettant dassurer votre vie privée, la propriété et le contrôle de vos données et de vos conversations. Cela vous donne accès à un réseau ouvert. Vous nêtes donc pas condamné à parler à dautres utilisateurs dElement seulement. Et c'est très sécurisé.
Element peut faire tout ça car il est basé sur Matrix, le protocole standard pour la communication ouverte et décentralisée.
Element peut faire tout ça car elle est basée sur Matrix, le protocole standard pour la communication ouverte et décentralisée.
Element vous donne le contrôle en vous laissant choisir qui héberge vos conversations. Depuis l'application Element, vous pouvez choisir votre hôte de différentes manières :
Element vous donne le contrôle en vous laissant choisir qui héberge vos conversations. Depuis l'application Element, vous pouvez choisir votre hôte de différentes manières :
1) Créer un compte gratuit sur le serveur public matrix.org hébergé par les développeurs de Matrix, ou choisir parler les milliers de serveurs public hébergés par des bénévoles
2) Héberger vous-même votre compte en installant un serveur sur votre propre machine
3) Créer un compte sur un serveur personnalisé en souscrivant sur la plateforme d'hébergement « Element Matrix Services » (EMS)
1. Créer un compte gratuit sur le serveur public matrix.org hébergé par les développeurs de Matrix, ou choisir parmi les milliers de serveurs public hébergés par des bénévoles
2. Héberger vous-même votre compte en installant un serveur sur votre propre machine
3. Créer un compte sur un serveur personnalisé en souscrivant sur la plateforme d'hébergement « Element Matrix Services » (EMS)
<b>Pourquoi choisir Element ?</b>
<b>POSSÉDEZ VOS DONNÉES</b> : Vous décidez où conserver vos données et vos messages. Vous les possédez et vous les contrôlez, et non une MEGACORP qui mine vos données ou les donnent à des tiers
<b>VOS DONNÉES VOUS APPARTIENNENT</b> : vous décidez où stocker vos données et messages. Ils vous appartiennent et vous les maîtrisez. Aucune multinationale ne viendra extraire vos données pour les envoyer au plus offrant.
<b>UNE MESSAGERIE OUVERTE ET COLLABORATIVE</b> : Vous pouvez discuter avec n'importe qui sur le réseau Matrix, qu'ils utilisent Element ou une autre application basée sur Matrix, et même s'ils utilisent un système de messagerie différent comment Slack, Discord, IRC ou XMPP.
<b>MESSAGERIE ET COLLABORATION OUVERTES</b> : vous pouvez discuter avec tout le réseau Matrix, quils utilisent Element ou une autre application Matrix, même sils utilisent une autre plateforme de messagerie telle que Slack, IRC ou XMPP.
<b>SUPER SÉCURISÉ</b> : Un réel chiffrement bout-à-bout (seulement ceux deux la conversation peuvent déchiffrer les messages), et une signature croisée pour vérifier les appareils des participants de la conversation.
<b>ULTRA SÉCURISÉ</b> : chiffrement de bout en bout (seuls les membres dune conversation peuvent déchiffrer les messages), et signature croisée pour vérifier les appareils de vos interlocuteurs.
<b>COMMUNICATION COMPLÈTE</b> : Messagerie, appels vocaux et vidéo, transfert de fichiers, partage d'écran et un tas d'intégrations, robots et widgets. Construisez des salons, des communautés, restez en contact et accomplissez de grandes choses.
<b>TOUTES VOS COMMUNICATIONS</b> : messagerie, appels audio et vidéo, partage de fichier, partage décran et un grand nombre dintégrations, robots et widgets. Participez à des salons, des communautés, restez en contact et faites avancer vos projets.
<b>PARTOUT OÙ VOUS ÊTES</b> : Restez connectés peu import où vous êtes avec la synchronisation complète de l'historique des messages sur tous vos appareils et sur le web sur https://app.element.io.
<b>PARTOUT AVEC VOUS</b> : votre historique reste synchronisé entre tous vos appareils et sur le web sur https://element.io/app.

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.2

View file

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

View file

@ -0,0 +1,2 @@
今回の新バージョンでは、主にバグの修正と改善が行われています。メッセージの送信がより速くなりました。
すべての変更履歴はこちら: https://github.com/vector-im/element-android/releases/tag/v1.0.10

View file

@ -0,0 +1,2 @@
今回の新バージョンでは、主にUIユーザーインターフェースとUXユーザーエクスペリエンスの向上が図られています。友達を招待したり、QRコードを読み取って素早くDMを作成できるようになりました。
すべての変更履歴はこちら: https://github.com/vector-im/element-android/releases/tag/v1.0.11

View file

@ -0,0 +1,2 @@
このバージョンの主な変更点: URLプレビュー、新しい絵文字、新しいルーム設定機能、それにクリスマスには雪が
すべての変更履歴はこちら: https://github.com/vector-im/element-android/releases/tag/v1.0.12

View file

@ -0,0 +1,2 @@
このバージョンの主な変更点: URLプレビュー、新しい絵文字、新しいルーム設定機能、それにクリスマスには雪が
すべての変更履歴はこちら: 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 and 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 @@
このバージョンの主な変更点: パフォーマンスの向上とバグの修正!
すべての変更履歴はこちら: https://github.com/vector-im/element-android/releases/tag/v1.1.2

View file

@ -0,0 +1,2 @@
このバージョンの主な変更点: パフォーマンスの向上とバグの修正!
すべての変更履歴はこちら: https://github.com/vector-im/element-android/releases/tag/v1.1.3

View file

@ -0,0 +1,30 @@
Elementはまったく新しいタイプのメッセンジャーアプリです。
1. あなた自身がプライバシーをコントロールすることを可能にします。
2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。
3. 広告、データ収集、バックドア、ユーザーの囲い込みから逃れることができます。
4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。
Elementは非中央集権型でオープンソースであるため、他のメッセンジャーアプリとは完全に異なっています。
Elementはあなた自身でサーバーをホストすることも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、あなたは他のElementユーザーと話せるだけでなくオープンネットワークへのアクセスも可能です。とてもセキュアです。
Elementは、オープンな分散型通信の標準規格であるMatrixで動作するため、これらすべてを実現することができています。
Elementではあなたの会話をどのサーバーでホストするか決めることができます。アプリでは、さまざまな方法で選択できます。
1. matrix.orgの公開サーバーで無料のアカウントを取得します。
2. あなた自身のハードウェアでサーバーを動かし、アカウントを管理します。
3. Element Matrix Servicesのホスティングプラットフォームに登録することで、カスタムサーバー上のアカウントを取得できます。
<b>なぜElementを選ぶべきなのか</b>
<b>データの所有権</b>: 自分でデータやメッセージを保管する場所を決めることができます。あなたが所有権を持ってコントロールすることで、第三者にあなたのデータを渡したり、ビッグデータを収集する巨大テック企業に依存する必要がなくなります。
<b>開かれたネットワークと共同作業</b>: Matrixネットワーク内の他の誰とでも、あるいはElementや他のMatrixアプリを使っているかどうかに関わらず、またSlack、IRC、XMPPのような他のメッセージングシステムを使っているかどうかに関わらず、チャットすることができます。
<b>はるかに安全</b>: 本物のエンドツーエンド暗号化(会話に参加している者のみがメッセージを読める)と会話参加者の真正性を確認するためクロス署名によって。
<b>完全なるコミュニケーションの訪れ</b>: テキスト、音声通話、ビデオ通話、ファイル共有、画面共有、連携機能、ボット、ウィジェットなどのコミュニケーションに必要な機能の全てが実装されています。ルームやコミュニティを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。
<b>いつでもどこでも!</b>: すべてのデバイスとウェブhttps://app.element.ioでメッセージの履歴が完全に同期されるため、どこにいても連絡を取ることができます。

View file

@ -0,0 +1 @@
安全な分散型チャットとVoIP。あなたの情報が第三者から守られます。

View file

@ -0,0 +1 @@
Elementエレメントメッセンジャー

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: URL-forhåndsvisning, nytt Emoji-tastatur, nye rominnstillingsmuligheter og snø til jul!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.12

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: URL-forhåndsvisning, nytt Emoji-tastatur, nye rominnstillingsmuligheter og snø til jul!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.13

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: Rediger romtillatelser, automatisk lys/mørkt tema og en haug med feilrettinger.
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.14

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: Sosial innloggingsstøtte.
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.15

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: Sosial innloggingsstøtte.
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.15 og https://github.com/vector-im/element-android/releases/tag/v1.0.16

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: Feilrettinger!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.17

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: forbedring av VoIP (lyd og videosamtaler i DM) og feilrettinger!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: forbedring av ytelsen og feilrettinger!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: forbedring av ytelsen og feilrettinger!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.2

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: forbedring av ytelsen og feilrettinger!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.3

View file

@ -0,0 +1,30 @@
Element er en ny type messenger og samarbeidsapp som:
1. Gir deg kontrollen for å bevare personvernet ditt
2. Lar deg kommunisere med hvem som helst i Matrix-nettverket, og til og med ved å integrere med apper som Slack
3. Beskytter deg mot reklame, datamining og inngjerdede hager
4. Sikrer deg gjennom end-to-end-kryptering, med kryssignering for å bekrefte andre
Element er helt forskjellig fra andre meldings- og samarbeidsapper fordi det er desentralisert og åpen kildekode.
Element lar deg selv være vert - eller velge en vert - slik at du har personvern, eierskap og kontroll over dataene og samtalene dine. Det gir deg tilgang til et åpent nettverk; slik at du ikke bare holder på å snakke med bare andre Element-brukere. Og det er veldig sikkert.
Element er i stand til å gjøre alt dette fordi det opererer på Matrix - standarden for åpen, desentralisert kommunikasjon.
Element setter deg i kontroll ved å la deg velge hvem som er vert for samtalene dine. Fra Element-appen kan du velge å være vert på forskjellige måter:
1. Få en gratis konto på matrix.org-serveren som er vert for Matrix-utviklerne, eller velg blant tusenvis av offentlige servere som er vert for frivillige
2. Vær vert for kontoen din ved å kjøre en server på din egen maskinvare
3. Registrer deg for en konto på en tilpasset server ved å bare abonnere på Hosting Matrix Services-vertsplattformen
<b> Hvorfor velge Element? </b>
<b> EGNE DATA DINE </b>: Du bestemmer hvor du vil oppbevare dataene og meldingene dine. Du eier den og kontrollerer den, ikke noe MEGACORP som utvinner dataene dine eller gir tilgang til tredjeparter.
<b> ÅPEN MELDING OG SAMARBEID </b>: Du kan chatte med alle andre i Matrix-nettverket, enten de bruker Element eller en annen Matrix-app, og selv om de bruker et annet meldingssystem som Slack, IRC eller XMPP.
<b> SUPER-SECURE </b>: Ekte end-to-end-kryptering (bare de i samtalen kan dekryptere meldinger), og kryssignering for å verifisere enhetene til samtaledeltakerne.
<b> KOMPLETT KOMMUNIKASJON </b>: Meldinger, tale- og videosamtaler, fildeling, skjermdeling og en hel haug med integrasjoner, bots og widgets. Bygg rom, lokalsamfunn, hold kontakten og få ting gjort.
<b> ALT DER DU ER </b>: Hold kontakten uansett hvor du er med fullt synkronisert meldingslogg på alle enhetene dine og på nettet på https://app.element.io.

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: Bugfikser!
Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.17

View file

@ -0,0 +1,2 @@
Hovedendringene i denne versjonen: Forbedringer i ytelse og bugfikser!
Full endringslogg: 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.2

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=9af5c8e7e2cd1a3b0f694a4ac262b9f38c75262e74a9e8b5101af302a6beadd7
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
distributionSha256Sum=81003f83b0056d20eedf48cddd4f52a9813163d4ba185bcf8abd34b8eeea4cbd
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View file

@ -1,2 +1 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.matrix.android.sdk.rx" />
<manifest package="org.matrix.android.sdk.rx" />

View file

@ -1,56 +0,0 @@
/*
* 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.rx
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.util.Cancelable
import io.reactivex.Completable
import io.reactivex.Single
fun <T> singleBuilder(builder: (MatrixCallback<T>) -> Cancelable): Single<T> = Single.create { emitter ->
val callback = object : MatrixCallback<T> {
override fun onSuccess(data: T) {
// 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) {
emitter.tryOnError(failure)
}
}
val cancelable = builder(callback)
emitter.setCancellable {
cancelable.cancel()
}
}
fun <T> completableBuilder(builder: (MatrixCallback<T>) -> Cancelable): Completable = Completable.create { emitter ->
val callback = object : MatrixCallback<T> {
override fun onSuccess(data: T) {
emitter.onComplete()
}
override fun onFailure(failure: Throwable) {
emitter.tryOnError(failure)
}
}
val cancelable = builder(callback)
emitter.setCancellable {
cancelable.cancel()
}
}

View file

@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
import org.matrix.android.sdk.api.session.sync.SyncState
import org.matrix.android.sdk.api.session.user.model.User
import org.matrix.android.sdk.api.session.widgets.model.Widget
@ -66,6 +67,13 @@ class RxSession(private val session: Session) {
}
}
fun liveSpaceSummaries(queryParams: SpaceSummaryQueryParams): Observable<List<RoomSummary>> {
return session.spaceService().getSpaceSummariesLive(queryParams).asObservable()
.startWithCallable {
session.spaceService().getSpaceSummaries(queryParams)
}
}
fun liveBreadcrumbs(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
return session.getBreadcrumbsLive(queryParams).asObservable()
.startWithCallable {
@ -124,8 +132,8 @@ class RxSession(private val session: Session) {
.startWithCallable { session.getPendingThreePids() }
}
fun createRoom(roomParams: CreateRoomParams): Single<String> = singleBuilder {
session.createRoom(roomParams, it)
fun createRoom(roomParams: CreateRoomParams): Single<String> = rxSingle {
session.createRoom(roomParams)
}
fun searchUsersDirectory(search: String,
@ -136,13 +144,13 @@ class RxSession(private val session: Session) {
fun joinRoom(roomIdOrAlias: String,
reason: String? = null,
viaServers: List<String> = emptyList()): Single<Unit> = singleBuilder {
session.joinRoom(roomIdOrAlias, reason, viaServers, it)
viaServers: List<String> = emptyList()): Single<Unit> = rxSingle {
session.joinRoom(roomIdOrAlias, reason, viaServers)
}
fun getRoomIdByAlias(roomAlias: String,
searchOnServer: Boolean): Single<Optional<RoomAliasDescription>> = singleBuilder {
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
searchOnServer: Boolean): Single<Optional<RoomAliasDescription>> = rxSingle {
session.getRoomIdByAlias(roomAlias, searchOnServer)
}
fun getProfileInfo(userId: String): Single<JsonDict> = rxSingle {

View file

@ -115,7 +115,7 @@ dependencies {
def lifecycle_version = '2.2.0'
def arch_version = '2.1.0'
def markwon_version = '3.1.0'
def daggerVersion = '2.33'
def daggerVersion = '2.35'
def work_version = '2.5.0'
def retrofit_version = '2.9.0'
@ -169,7 +169,7 @@ dependencies {
implementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.21'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.22'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.5.1'

View file

@ -66,8 +66,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
fun doE2ETestWithAliceInARoom(encryptedRoom: Boolean = true): CryptoTestData {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
val roomId = mTestHelper.doSync<String> {
aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" }, it)
val roomId = mTestHelper.runBlockingTest {
aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" })
}
if (encryptedRoom) {
@ -135,7 +135,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
bobRoomSummariesLive.observeForever(roomJoinedObserver)
}
mTestHelper.doSync<Unit> { bobSession.joinRoom(aliceRoomId, callback = it) }
mTestHelper.runBlockingTest { bobSession.joinRoom(aliceRoomId) }
mTestHelper.await(lock)
@ -176,8 +176,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
room.invite(samSession.myUserId, null)
}
mTestHelper.doSync<Unit> {
samSession.joinRoom(room.roomId, null, emptyList(), it)
mTestHelper.runBlockingTest {
samSession.joinRoom(room.roomId, null, emptyList())
}
return samSession
@ -256,8 +256,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
}
fun createDM(alice: Session, bob: Session): String {
val roomId = mTestHelper.doSync<String> {
alice.createDirectRoom(bob.myUserId, it)
val roomId = mTestHelper.runBlockingTest {
alice.createDirectRoom(bob.myUserId)
}
mTestHelper.waitWithLatch { latch ->
@ -300,7 +300,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
bobRoomSummariesLive.observeForever(newRoomObserver)
}
mTestHelper.doSync<Unit> { bob.joinRoom(roomId, callback = it) }
mTestHelper.runBlockingTest { bob.joinRoom(roomId) }
}
return roomId
@ -398,8 +398,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
val roomId = mTestHelper.doSync<String> {
aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" }, it)
val roomId = mTestHelper.runBlockingTest {
aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" })
}
val room = aliceSession.getRoom(roomId)!!
@ -412,7 +412,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
val session = mTestHelper.createAccount("User_$index", defaultSessionParams)
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) }
mTestHelper.runBlockingTest { session.joinRoom(room.roomId, null, emptyList()) }
println("TEST -> " + session.myUserId + " joined")
sessions.add(session)
}

View file

@ -71,13 +71,12 @@ class KeyShareTests : InstrumentedTest {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
// Create an encrypted room and add a message
val roomId = mTestHelper.doSync<String> {
val roomId = mTestHelper.runBlockingTest {
aliceSession.createRoom(
CreateRoomParams().apply {
visibility = RoomDirectoryVisibility.PRIVATE
enableEncryption()
},
it
}
)
}
val room = aliceSession.getRoom(roomId)
@ -332,13 +331,12 @@ class KeyShareTests : InstrumentedTest {
}
// Create an encrypted room and send a couple of messages
val roomId = mTestHelper.doSync<String> {
val roomId = mTestHelper.runBlockingTest {
aliceSession.createRoom(
CreateRoomParams().apply {
visibility = RoomDirectoryVisibility.PRIVATE
enableEncryption()
},
it
}
)
}
val roomAlicePov = aliceSession.getRoom(roomId)
@ -371,8 +369,8 @@ class KeyShareTests : InstrumentedTest {
roomAlicePov.invite(bobSession.myUserId, null)
}
mTestHelper.doSync<Unit> {
bobSession.joinRoom(roomAlicePov.roomId, null, emptyList(), it)
mTestHelper.runBlockingTest {
bobSession.joinRoom(roomAlicePov.roomId, null, emptyList())
}
// we want to discard alice outbound session

View file

@ -0,0 +1,194 @@
/*
* 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.session.space
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
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.query.QueryStringValue
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.SessionTestParams
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class SpaceCreationTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
@Test
fun createSimplePublicSpace() {
val session = commonTestHelper.createAccount("Hubble", SessionTestParams(true))
val roomName = "My Space"
val topic = "A public space for test"
val spaceId: String
runBlocking {
spaceId = session.spaceService().createSpace(roomName, topic, null, true)
// wait a bit to let the summary update it self :/
delay(400)
}
val syncedSpace = session.spaceService().getSpace(spaceId)
assertEquals(roomName, syncedSpace?.asRoom()?.roomSummary()?.name, "Room name should be set")
assertEquals(topic, syncedSpace?.asRoom()?.roomSummary()?.topic, "Room topic should be set")
// assertEquals(topic, syncedSpace.asRoom().roomSummary()?., "Room topic should be set")
assertNotNull(syncedSpace, "Space should be found by Id")
val creationEvent = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_CREATE)
val createContent = creationEvent?.content.toModel<RoomCreateContent>()
assertEquals(RoomType.SPACE, createContent?.type, "Room type should be space")
var powerLevelsContent: PowerLevelsContent? = null
commonTestHelper.waitWithLatch { latch ->
commonTestHelper.retryPeriodicallyWithLatch(latch) {
val toModel = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)?.content.toModel<PowerLevelsContent>()
powerLevelsContent = toModel
toModel != null
}
}
assertEquals(100, powerLevelsContent?.eventsDefault, "Space-rooms should be created with a power level for events_default of 100")
val guestAccess = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_GUEST_ACCESS)?.content
?.toModel<RoomGuestAccessContent>()?.guestAccess
assertEquals(GuestAccess.CanJoin, guestAccess, "Public space room should be peekable by guest")
val historyVisibility = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY)?.content
?.toModel<RoomHistoryVisibilityContent>()?.historyVisibility
assertEquals(RoomHistoryVisibility.WORLD_READABLE, historyVisibility, "Public space room should be world readable")
commonTestHelper.signOutAndClose(session)
}
@Test
fun testJoinSimplePublicSpace() {
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
val roomName = "My Space"
val topic = "A public space for test"
val spaceId: String
runBlocking {
spaceId = aliceSession.spaceService().createSpace(roomName, topic, null, true)
// wait a bit to let the summary update it self :/
delay(400)
}
// Try to join from bob, it's a public space no need to invite
val joinResult: JoinSpaceResult
runBlocking {
joinResult = bobSession.spaceService().joinSpace(spaceId)
}
assertEquals(JoinSpaceResult.Success, joinResult)
val spaceBobPov = bobSession.spaceService().getSpace(spaceId)
assertEquals(roomName, spaceBobPov?.asRoom()?.roomSummary()?.name, "Room name should be set")
assertEquals(topic, spaceBobPov?.asRoom()?.roomSummary()?.topic, "Room topic should be set")
commonTestHelper.signOutAndClose(aliceSession)
commonTestHelper.signOutAndClose(bobSession)
}
@Test
fun testSimplePublicSpaceWithChildren() {
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
val roomName = "My Space"
val topic = "A public space for test"
val spaceId: String = runBlocking { aliceSession.spaceService().createSpace(roomName, topic, null, true) }
val syncedSpace = aliceSession.spaceService().getSpace(spaceId)
// create a room
val firstChild: String = runBlocking {
aliceSession.createRoom(CreateRoomParams().apply {
this.name = "FirstRoom"
this.topic = "Description of first room"
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
})
}
runBlocking {
syncedSpace?.addChildren(firstChild, listOf(aliceSession.sessionParams.homeServerHost ?: ""), "a", true)
}
val secondChild: String = runBlocking {
aliceSession.createRoom(CreateRoomParams().apply {
this.name = "SecondRoom"
this.topic = "Description of second room"
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
})
}
runBlocking {
syncedSpace?.addChildren(secondChild, listOf(aliceSession.sessionParams.homeServerHost ?: ""), "b", false)
}
// Try to join from bob, it's a public space no need to invite
val joinResult = runBlocking {
bobSession.spaceService().joinSpace(spaceId)
}
assertEquals(JoinSpaceResult.Success, joinResult)
val spaceBobPov = bobSession.spaceService().getSpace(spaceId)
assertEquals(roomName, spaceBobPov?.asRoom()?.roomSummary()?.name, "Room name should be set")
assertEquals(topic, spaceBobPov?.asRoom()?.roomSummary()?.topic, "Room topic should be set")
// check if bob has joined automatically the first room
val bobMembershipFirstRoom = bobSession.getRoom(firstChild)?.roomSummary()?.membership
assertEquals(Membership.JOIN, bobMembershipFirstRoom, "Bob should have joined this room")
RoomSummaryQueryParams.Builder()
val spaceSummaryBobPov = bobSession.spaceService().getSpaceSummaries(roomSummaryQueryParams {
this.roomId = QueryStringValue.Equals(spaceId)
this.memberships = listOf(Membership.JOIN)
}).firstOrNull()
assertEquals(2, spaceSummaryBobPov?.spaceChildren?.size ?: -1, "Unexpected number of children")
commonTestHelper.signOutAndClose(aliceSession)
commonTestHelper.signOutAndClose(bobSession)
}
}

View file

@ -0,0 +1,414 @@
/*
* 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.session.space
import android.util.Log
import androidx.lifecycle.Observer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
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.session.Session
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.SessionTestParams
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class SpaceHierarchyTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
@Test
fun createCanonicalChildRelation() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceName = "My Space"
val topic = "A public space for test"
val spaceId: String
runBlocking {
spaceId = session.spaceService().createSpace(spaceName, topic, null, true)
// wait a bit to let the summary update it self :/
delay(400)
}
val syncedSpace = session.spaceService().getSpace(spaceId)
val roomId = runBlocking {
session.createRoom(CreateRoomParams().apply { name = "General" })
}
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
runBlocking {
syncedSpace!!.addChildren(roomId, viaServers, null, true)
}
runBlocking {
session.spaceService().setSpaceParent(roomId, spaceId, true, viaServers)
}
Thread.sleep(9000)
val parents = session.getRoom(roomId)?.roomSummary()?.spaceParents
val canonicalParents = session.getRoom(roomId)?.roomSummary()?.spaceParents?.filter { it.canonical == true }
parents?.forEach {
Log.d("## TEST", "parent : $it")
}
assertNotNull(parents)
assertEquals(1, parents.size)
assertEquals(spaceName, parents.first().roomSummary?.name)
assertNotNull(canonicalParents)
assertEquals(1, canonicalParents.size)
assertEquals(spaceName, canonicalParents.first().roomSummary?.name)
}
@Test
fun testCreateChildRelations() {
val session = commonTestHelper.createAccount("Jhon", SessionTestParams(true))
val spaceName = "My Space"
val topic = "A public space for test"
Log.d("## TEST", "Before")
val spaceId = runBlocking {
session.spaceService().createSpace(spaceName, topic, null, true)
}
Log.d("## TEST", "created space $spaceId ${Thread.currentThread()}")
val syncedSpace = session.spaceService().getSpace(spaceId)
val children = listOf("General" to true /*canonical*/, "Random" to false)
val roomIdList = children.map {
runBlocking {
session.createRoom(CreateRoomParams().apply { name = it.first })
} to it.second
}
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
runBlocking {
roomIdList.forEach { entry ->
syncedSpace!!.addChildren(entry.first, viaServers, null, true)
}
}
runBlocking {
roomIdList.forEach {
session.spaceService().setSpaceParent(it.first, spaceId, it.second, viaServers)
}
delay(400)
}
roomIdList.forEach {
val parents = session.getRoom(it.first)?.roomSummary()?.spaceParents
val canonicalParents = session.getRoom(it.first)?.roomSummary()?.spaceParents?.filter { it.canonical == true }
assertNotNull(parents)
assertEquals(1, parents.size, "Unexpected number of parent")
assertEquals(spaceName, parents.first().roomSummary?.name, "Unexpected parent name ")
assertEquals(if (it.second) 1 else 0, canonicalParents?.size ?: 0, "Parent of ${it.first} should be canonical ${it.second}")
}
}
@Test
fun testFilteringBySpace() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceAInfo = createPublicSpace(session, "SpaceA", listOf(
Triple("A1", true /*auto-join*/, true/*canonical*/),
Triple("A2", true, true)
))
val spaceBInfo = createPublicSpace(session, "SpaceB", listOf(
Triple("B1", true /*auto-join*/, true/*canonical*/),
Triple("B2", true, true),
Triple("B3", true, true)
))
val spaceCInfo = createPublicSpace(session, "SpaceC", listOf(
Triple("C1", true /*auto-join*/, true/*canonical*/),
Triple("C2", true, true)
))
// add C as a subspace of A
val spaceA = session.spaceService().getSpace(spaceAInfo.spaceId)
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
runBlocking {
spaceA!!.addChildren(spaceCInfo.spaceId, viaServers, null, true)
session.spaceService().setSpaceParent(spaceCInfo.spaceId, spaceAInfo.spaceId, true, viaServers)
}
// Create orphan rooms
val orphan1 = runBlocking {
session.createRoom(CreateRoomParams().apply { name = "O1" })
}
val orphan2 = runBlocking {
session.createRoom(CreateRoomParams().apply { name = "O2" })
}
val allRooms = session.getRoomSummaries(roomSummaryQueryParams { excludeType = listOf(RoomType.SPACE) })
assertEquals(9, allRooms.size, "Unexpected number of rooms")
val orphans = session.getFlattenRoomSummaryChildrenOf(null)
assertEquals(2, orphans.size, "Unexpected number of orphan rooms")
assertTrue(orphans.indexOfFirst { it.roomId == orphan1 } != -1, "O1 should be an orphan")
assertTrue(orphans.indexOfFirst { it.roomId == orphan2 } != -1, "O2 should be an orphan ${orphans.map { it.name }}")
val aChildren = session.getFlattenRoomSummaryChildrenOf(spaceAInfo.spaceId)
assertEquals(4, aChildren.size, "Unexpected number of flatten child rooms")
assertTrue(aChildren.indexOfFirst { it.name == "A1" } != -1, "A1 should be a child of A")
assertTrue(aChildren.indexOfFirst { it.name == "A2" } != -1, "A2 should be a child of A")
assertTrue(aChildren.indexOfFirst { it.name == "C1" } != -1, "CA should be a grand child of A")
assertTrue(aChildren.indexOfFirst { it.name == "C2" } != -1, "A1 should be a grand child of A")
// Add a non canonical child and check that it does not appear as orphan
val a3 = runBlocking {
session.createRoom(CreateRoomParams().apply { name = "A3" })
}
runBlocking {
spaceA!!.addChildren(a3, viaServers, null, false)
delay(400)
// here we do not set the parent!!
}
val orphansUpdate = session.getFlattenRoomSummaryChildrenOf(null)
assertEquals(2, orphansUpdate.size, "Unexpected number of orphan rooms ${orphansUpdate.map { it.name }}")
}
@Test
fun testBreakCycle() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceAInfo = createPublicSpace(session, "SpaceA", listOf(
Triple("A1", true /*auto-join*/, true/*canonical*/),
Triple("A2", true, true)
))
val spaceCInfo = createPublicSpace(session, "SpaceC", listOf(
Triple("C1", true /*auto-join*/, true/*canonical*/),
Triple("C2", true, true)
))
// add C as a subspace of A
val spaceA = session.spaceService().getSpace(spaceAInfo.spaceId)
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
runBlocking {
spaceA!!.addChildren(spaceCInfo.spaceId, viaServers, null, true)
session.spaceService().setSpaceParent(spaceCInfo.spaceId, spaceAInfo.spaceId, true, viaServers)
}
// add back A as subspace of C
runBlocking {
val spaceC = session.spaceService().getSpace(spaceCInfo.spaceId)
spaceC!!.addChildren(spaceAInfo.spaceId, viaServers, null, true)
}
Thread.sleep(1000)
// A -> C -> A
val aChildren = session.getFlattenRoomSummaryChildrenOf(spaceAInfo.spaceId)
assertEquals(4, aChildren.size, "Unexpected number of flatten child rooms ${aChildren.map { it.name }}")
assertTrue(aChildren.indexOfFirst { it.name == "A1" } != -1, "A1 should be a child of A")
assertTrue(aChildren.indexOfFirst { it.name == "A2" } != -1, "A2 should be a child of A")
assertTrue(aChildren.indexOfFirst { it.name == "C1" } != -1, "CA should be a grand child of A")
assertTrue(aChildren.indexOfFirst { it.name == "C2" } != -1, "A1 should be a grand child of A")
}
@Test
fun testLiveFlatChildren() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceAInfo = createPublicSpace(session, "SpaceA", listOf(
Triple("A1", true /*auto-join*/, true/*canonical*/),
Triple("A2", true, true)
))
val spaceBInfo = createPublicSpace(session, "SpaceB", listOf(
Triple("B1", true /*auto-join*/, true/*canonical*/),
Triple("B2", true, true),
Triple("B3", true, true)
))
// add B as a subspace of A
val spaceA = session.spaceService().getSpace(spaceAInfo.spaceId)
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
runBlocking {
spaceA!!.addChildren(spaceBInfo.spaceId, viaServers, null, true)
session.spaceService().setSpaceParent(spaceBInfo.spaceId, spaceAInfo.spaceId, true, viaServers)
}
val flatAChildren = runBlocking(Dispatchers.Main) {
session.getFlattenRoomSummaryChildrenOfLive(spaceAInfo.spaceId)
}
commonTestHelper.waitWithLatch { latch ->
val childObserver = object : Observer<List<RoomSummary>> {
override fun onChanged(children: List<RoomSummary>?) {
// Log.d("## TEST", "Space A flat children update : ${children?.map { it.name }}")
System.out.println("## TEST | Space A flat children update : ${children?.map { it.name }}")
if (children?.indexOfFirst { it.name == "C1" } != -1
&& children?.indexOfFirst { it.name == "C2" } != -1
) {
// B1 has been added live!
latch.countDown()
flatAChildren.removeObserver(this)
}
}
}
val spaceCInfo = createPublicSpace(session, "SpaceC", listOf(
Triple("C1", true /*auto-join*/, true/*canonical*/),
Triple("C2", true, true)
))
// add C as subspace of B
runBlocking {
val spaceB = session.spaceService().getSpace(spaceBInfo.spaceId)
spaceB!!.addChildren(spaceCInfo.spaceId, viaServers, null, true)
}
// C1 and C2 should be in flatten child of A now
GlobalScope.launch(Dispatchers.Main) { flatAChildren.observeForever(childObserver) }
}
// Test part one of the rooms
val bRoomId = spaceBInfo.roomIds.first()
val bRoom = session.getRoom(bRoomId)
commonTestHelper.waitWithLatch { latch ->
val childObserver = object : Observer<List<RoomSummary>> {
override fun onChanged(children: List<RoomSummary>?) {
System.out.println("## TEST | Space A flat children update : ${children?.map { it.name }}")
if (children?.any { it.roomId == bRoomId } == false) {
// B1 has been added live!
latch.countDown()
flatAChildren.removeObserver(this)
}
}
}
// part from b room
runBlocking {
bRoom!!.leave(null)
}
// The room should have disapear from flat children
GlobalScope.launch(Dispatchers.Main) { flatAChildren.observeForever(childObserver) }
}
}
data class TestSpaceCreationResult(
val spaceId: String,
val roomIds: List<String>
)
private fun createPublicSpace(session: Session,
spaceName: String,
childInfo: List<Triple<String, Boolean, Boolean?>>
/** Name, auto-join, canonical*/
): TestSpaceCreationResult {
val spaceId = runBlocking {
session.spaceService().createSpace(spaceName, "Test Topic", null, true)
}
val syncedSpace = session.spaceService().getSpace(spaceId)
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
val roomIds =
childInfo.map { entry ->
runBlocking {
session.createRoom(CreateRoomParams().apply { name = entry.first })
}
}
roomIds.forEachIndexed { index, roomId ->
runBlocking {
syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second)
val canonical = childInfo[index].third
if (canonical != null) {
session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers)
}
}
}
return TestSpaceCreationResult(spaceId, roomIds)
}
@Test
fun testRootSpaces() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceAInfo = createPublicSpace(session, "SpaceA", listOf(
Triple("A1", true /*auto-join*/, true/*canonical*/),
Triple("A2", true, true)
))
val spaceBInfo = createPublicSpace(session, "SpaceB", listOf(
Triple("B1", true /*auto-join*/, true/*canonical*/),
Triple("B2", true, true),
Triple("B3", true, true)
))
val spaceCInfo = createPublicSpace(session, "SpaceC", listOf(
Triple("C1", true /*auto-join*/, true/*canonical*/),
Triple("C2", true, true)
))
val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
// add C as subspace of B
runBlocking {
val spaceB = session.spaceService().getSpace(spaceBInfo.spaceId)
spaceB!!.addChildren(spaceCInfo.spaceId, viaServers, null, true)
}
Thread.sleep(2000)
// + A
// a1, a2
// + B
// b1, b2, b3
// + C
// + c1, c2
val rootSpaces = session.spaceService().getRootSpaceSummaries()
assertEquals(2, rootSpaces.size, "Unexpected number of root spaces ${rootSpaces.map { it.name }}")
}
}

View file

@ -16,12 +16,10 @@
package org.matrix.android.sdk.api.auth.data
sealed class LoginFlowResult {
data class Success(
val supportedLoginTypes: List<String>,
val ssoIdentityProviders: List<SsoIdentityProvider>?,
val isLoginAndRegistrationSupported: Boolean,
val homeServerUrl: String,
val isOutdatedHomeserver: Boolean
) : LoginFlowResult()
}
data class LoginFlowResult(
val supportedLoginTypes: List<String>,
val ssoIdentityProviders: List<SsoIdentityProvider>?,
val isLoginAndRegistrationSupported: Boolean,
val homeServerUrl: String,
val isOutdatedHomeserver: Boolean
)

View file

@ -20,7 +20,9 @@ interface RegistrationWizard {
suspend fun getRegistrationFlow(): RegistrationResult
suspend fun createAccount(userName: String, password: String, initialDeviceDisplayName: String?): RegistrationResult
suspend fun createAccount(userName: String?,
password: String?,
initialDeviceDisplayName: String?): RegistrationResult
suspend fun performReCaptcha(response: String): RegistrationResult

View file

@ -32,7 +32,6 @@ import java.io.IOException
*/
sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
data class Unknown(val throwable: Throwable? = null) : Failure(throwable)
data class Cancelled(val throwable: Throwable? = null) : Failure(throwable)
data class UnrecognizedCertificateFailure(val url: String, val fingerprint: Fingerprint) : Failure()
data class NetworkConnection(val ioException: IOException? = null) : Failure(ioException)
data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString()))

View file

@ -0,0 +1,23 @@
/*
* 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
sealed class ActiveSpaceFilter {
object None : ActiveSpaceFilter()
data class ActiveSpace(val currentSpaceId: String?) : ActiveSpaceFilter()
data class ExcludeSpace(val spaceId: String) : ActiveSpaceFilter()
}

View file

@ -48,6 +48,7 @@ import org.matrix.android.sdk.api.session.search.SearchService
import org.matrix.android.sdk.api.session.securestorage.SecureStorageService
import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
import org.matrix.android.sdk.api.session.signout.SignOutService
import org.matrix.android.sdk.api.session.space.SpaceService
import org.matrix.android.sdk.api.session.sync.FilterService
import org.matrix.android.sdk.api.session.sync.SyncState
import org.matrix.android.sdk.api.session.terms.TermsService
@ -227,6 +228,11 @@ interface Session :
*/
fun thirdPartyService(): ThirdPartyService
/**
* Returns the space service associated with the session
*/
fun spaceService(): SpaceService
/**
* Add a listener to the session.
* @param listener the listener to add.
@ -249,13 +255,13 @@ interface Session :
/**
* A global session listener to get notified for some events.
*/
interface Listener {
interface Listener : SessionLifecycleObserver {
/**
* Possible cases:
* - The access token is not valid anymore,
* - a M_CONSENT_NOT_GIVEN error has been received from the homeserver
*/
fun onGlobalError(globalError: GlobalError)
fun onGlobalError(session: Session, globalError: GlobalError)
}
val sharedSecretStorageService: SharedSecretStorageService

View file

@ -14,20 +14,19 @@
* limitations under the License.
*/
package org.matrix.android.sdk.internal.session
package org.matrix.android.sdk.api.session
import androidx.annotation.MainThread
/**
* This defines methods associated with some lifecycle events of a session.
* A list of SessionLifecycle will be injected into [DefaultSession]
*/
internal interface SessionLifecycleObserver {
interface SessionLifecycleObserver {
/*
Called when the session is opened
*/
@MainThread
fun onSessionStarted() {
fun onSessionStarted(session: Session) {
// noop
}
@ -35,7 +34,7 @@ internal interface SessionLifecycleObserver {
Called when the session is cleared
*/
@MainThread
fun onClearCache() {
fun onClearCache(session: Session) {
// noop
}
@ -43,7 +42,7 @@ internal interface SessionLifecycleObserver {
Called when the session is closed
*/
@MainThread
fun onSessionStopped() {
fun onSessionStopped(session: Session) {
// noop
}
}

View file

@ -53,6 +53,12 @@ object EventType {
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
// const val STATE_SPACE_CHILD = "m.space.child"
const val STATE_SPACE_CHILD = "org.matrix.msc1772.space.child"
// const val STATE_SPACE_PARENT = "m.space.parent"
const val STATE_SPACE_PARENT = "org.matrix.msc1772.space.parent"
/**
* Note that this Event has been deprecated, see
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
@ -75,6 +81,7 @@ object EventType {
const val CALL_NEGOTIATE = "m.call.negotiate"
const val CALL_REJECT = "m.call.reject"
const val CALL_HANGUP = "m.call.hangup"
// This type is not processed by the client, just sent to the server
const val CALL_REPLACES = "m.call.replaces"

View file

@ -29,14 +29,19 @@ import java.io.File
*/
interface FileService {
enum class FileState {
IN_CACHE,
DOWNLOADING,
UNKNOWN
sealed class FileState {
/**
* The original file is in cache, but the decrypted files can be deleted for security reason.
* To decrypt the file again, call [downloadFile], the encrypted file will not be downloaded again
* @param decryptedFileInCache true if the decrypted file is available. Always true for clear files.
*/
data class InCache(val decryptedFileInCache: Boolean) : FileState()
object Downloading : FileState()
object Unknown : FileState()
}
/**
* Download a file.
* Download a file if necessary and ensure that if the file is encrypted, the file is decrypted.
* Result will be a decrypted file, stored in the cache folder. url parameter will be used to create unique filename to avoid name collision.
*/
suspend fun downloadFile(fileName: String,

View file

@ -66,12 +66,13 @@ interface PushersService {
/**
* Directly ask the push gateway to send a push to this device
* If successful, 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 will be thrown. In this case it means that the pushkey is not valid.
*
* @param url the push gateway url (full path)
* @param appId the application id
* @param pushkey the FCM token
* @param eventId the eventId which will be sent in the Push message. Use a fake eventId.
* @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.
*/
suspend fun testPush(url: String,
appId: String,

View file

@ -34,6 +34,7 @@ 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.session.space.Space
import org.matrix.android.sdk.api.util.Optional
/**
@ -91,4 +92,9 @@ interface Room :
beforeLimit: Int,
afterLimit: Int,
includeProfile: Boolean): SearchResult
/**
* Use this room as a Space, if the type is correct.
*/
fun asSpace(): Space?
}

View file

@ -18,15 +18,14 @@ 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
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.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
@ -38,22 +37,19 @@ interface RoomService {
/**
* Create a room asynchronously
*/
fun createRoom(createRoomParams: CreateRoomParams,
callback: MatrixCallback<String>): Cancelable
suspend fun createRoom(createRoomParams: CreateRoomParams): String
/**
* Create a direct room asynchronously. This is a facility method to create a direct room with the necessary parameters
*/
fun createDirectRoom(otherUserId: String,
callback: MatrixCallback<String>): Cancelable {
suspend fun createDirectRoom(otherUserId: String): String {
return createRoom(
CreateRoomParams()
.apply {
invitedUserIds.add(otherUserId)
setDirectMessage()
enableEncryptionIfInvitedUsersSupportIt = true
},
callback
}
)
}
@ -63,10 +59,9 @@ interface RoomService {
* @param reason optional reason for joining the room
* @param viaServers the servers to attempt to join the room through. One of the servers must be participating in the room.
*/
fun joinRoom(roomIdOrAlias: String,
reason: String? = null,
viaServers: List<String> = emptyList(),
callback: MatrixCallback<Unit>): Cancelable
suspend fun joinRoom(roomIdOrAlias: String,
reason: String? = null,
viaServers: List<String> = emptyList())
/**
* Get a room from a roomId
@ -112,20 +107,18 @@ interface RoomService {
* Inform the Matrix SDK that a room is displayed.
* The SDK will update the breadcrumbs in the user account data
*/
fun onRoomDisplayed(roomId: String): Cancelable
suspend fun onRoomDisplayed(roomId: String)
/**
* Mark all rooms as read
*/
fun markAllAsRead(roomIds: List<String>,
callback: MatrixCallback<Unit>): Cancelable
suspend fun markAllAsRead(roomIds: List<String>)
/**
* Resolve a room alias to a room ID.
*/
fun getRoomIdByAlias(roomAlias: String,
searchOnServer: Boolean,
callback: MatrixCallback<Optional<RoomAliasDescription>>): Cancelable
suspend fun getRoomIdByAlias(roomAlias: String,
searchOnServer: Boolean): Optional<RoomAliasDescription>
/**
* Delete a room alias
@ -172,26 +165,28 @@ interface RoomService {
/**
* Get some state events about a room
*/
fun getRoomState(roomId: String, callback: MatrixCallback<List<Event>>)
suspend fun getRoomState(roomId: String): List<Event>
/**
* Use this if you want to get information from a room that you are not yet in (or invited)
* It might be possible to get some information on this room if it is public or if guest access is allowed
* 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>)
suspend fun peekRoom(roomIdOrAlias: String): PeekResult
/**
* TODO Doc
*/
fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,
pagedListConfig: PagedList.Config = defaultPagedListConfig): LiveData<PagedList<RoomSummary>>
pagedListConfig: PagedList.Config = defaultPagedListConfig,
sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData<PagedList<RoomSummary>>
/**
* TODO Doc
*/
fun getFilteredPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,
pagedListConfig: PagedList.Config = defaultPagedListConfig): UpdatableFilterLivePageResult
pagedListConfig: PagedList.Config = defaultPagedListConfig,
sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): UpdatableLivePageResult
/**
* TODO Doc
@ -205,4 +200,12 @@ interface RoomService {
.setEnablePlaceholders(false)
.setPrefetchDistance(10)
.build()
fun getFlattenRoomSummaryChildrenOf(spaceId: String?, memberships: List<Membership> = Membership.activeMemberships()) : List<RoomSummary>
/**
* Returns all the children of this space, as LiveData
*/
fun getFlattenRoomSummaryChildrenOfLive(spaceId: String?,
memberships: List<Membership> = Membership.activeMemberships()): LiveData<List<RoomSummary>>
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2019 New Vector Ltd
* 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.
@ -12,14 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package im.vector.app.features.grouplist
package org.matrix.android.sdk.api.session.room
import im.vector.app.core.platform.VectorViewModelAction
import org.matrix.android.sdk.api.session.group.model.GroupSummary
sealed class GroupListAction : VectorViewModelAction {
data class SelectGroup(val groupSummary: GroupSummary) : GroupListAction()
enum class RoomSortOrder {
NAME,
ACTIVITY,
NONE
}

View file

@ -16,15 +16,35 @@
package org.matrix.android.sdk.api.session.room
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
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
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
fun roomSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): RoomSummaryQueryParams {
return RoomSummaryQueryParams.Builder().apply(init).build()
}
fun spaceSummaryQueryParams(init: (RoomSummaryQueryParams.Builder.() -> Unit) = {}): SpaceSummaryQueryParams {
return RoomSummaryQueryParams.Builder()
.apply(init)
.apply {
includeType = listOf(RoomType.SPACE)
excludeType = null
roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
}
.build()
}
enum class RoomCategoryFilter {
ONLY_DM,
ONLY_ROOMS,
ALL
}
/**
* This class can be used to filter room summaries to use with:
* [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]
@ -35,7 +55,11 @@ data class RoomSummaryQueryParams(
val canonicalAlias: QueryStringValue,
val memberships: List<Membership>,
val roomCategoryFilter: RoomCategoryFilter?,
val roomTagQueryFilter: RoomTagQueryFilter?
val roomTagQueryFilter: RoomTagQueryFilter?,
val excludeType: List<String?>?,
val includeType: List<String?>?,
val activeSpaceId: ActiveSpaceFilter?,
var activeGroupId: String? = null
) {
class Builder {
@ -46,6 +70,10 @@ data class RoomSummaryQueryParams(
var memberships: List<Membership> = Membership.all()
var roomCategoryFilter: RoomCategoryFilter? = RoomCategoryFilter.ALL
var roomTagQueryFilter: RoomTagQueryFilter? = null
var excludeType: List<String?>? = listOf(RoomType.SPACE)
var includeType: List<String?>? = null
var activeSpaceId: ActiveSpaceFilter = ActiveSpaceFilter.None
var activeGroupId: String? = null
fun build() = RoomSummaryQueryParams(
roomId = roomId,
@ -53,7 +81,11 @@ data class RoomSummaryQueryParams(
canonicalAlias = canonicalAlias,
memberships = memberships,
roomCategoryFilter = roomCategoryFilter,
roomTagQueryFilter = roomTagQueryFilter
roomTagQueryFilter = roomTagQueryFilter,
excludeType = excludeType,
includeType = includeType,
activeSpaceId = activeSpaceId,
activeGroupId = activeGroupId
)
}
}

View file

@ -20,8 +20,16 @@ import androidx.lifecycle.LiveData
import androidx.paging.PagedList
import org.matrix.android.sdk.api.session.room.model.RoomSummary
interface UpdatableFilterLivePageResult {
interface UpdatableLivePageResult {
val livePagedList: LiveData<PagedList<RoomSummary>>
fun updateQuery(queryParams: RoomSummaryQueryParams)
fun updateQuery(builder: (RoomSummaryQueryParams) -> RoomSummaryQueryParams)
val liveBoundaries: LiveData<ResultBoundaries>
}
data class ResultBoundaries(
val frontLoaded: Boolean = false,
val endLoaded: Boolean = false,
val zeroItemLoaded: Boolean = false
)

View file

@ -17,7 +17,7 @@
package org.matrix.android.sdk.api.session.room.alias
sealed class RoomAliasError : Throwable() {
object AliasEmpty : RoomAliasError()
object AliasIsBlank : RoomAliasError()
object AliasNotAvailable : RoomAliasError()
object AliasInvalid : RoomAliasError()
}

View file

@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
sealed class CreateRoomFailure : Failure.FeatureFailure() {
object CreatedWithTimeout : CreateRoomFailure()
data class CreatedWithTimeout(val roomID: String) : CreateRoomFailure()
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
data class AliasError(val aliasError: RoomAliasError) : CreateRoomFailure()
}

View file

@ -28,43 +28,43 @@ data class PowerLevelsContent(
/**
* The level required to ban a user. Defaults to 50 if unspecified.
*/
@Json(name = "ban") val ban: Int = Role.Moderator.value,
@Json(name = "ban") val ban: Int? = null,
/**
* The level required to kick a user. Defaults to 50 if unspecified.
*/
@Json(name = "kick") val kick: Int = Role.Moderator.value,
@Json(name = "kick") val kick: Int? = null,
/**
* The level required to invite a user. Defaults to 50 if unspecified.
*/
@Json(name = "invite") val invite: Int = Role.Moderator.value,
@Json(name = "invite") val invite: Int? = null,
/**
* The level required to redact an event. Defaults to 50 if unspecified.
*/
@Json(name = "redact") val redact: Int = Role.Moderator.value,
@Json(name = "redact") val redact: Int? = null,
/**
* The default level required to send message events. Can be overridden by the events key. Defaults to 0 if unspecified.
*/
@Json(name = "events_default") val eventsDefault: Int = Role.Default.value,
@Json(name = "events_default") val eventsDefault: Int? = null,
/**
* The level required to send specific event types. This is a mapping from event type to power level required.
*/
@Json(name = "events") val events: Map<String, Int> = emptyMap(),
@Json(name = "events") val events: Map<String, Int>? = null,
/**
* The default power level for every user in the room, unless their user_id is mentioned in the users key. Defaults to 0 if unspecified.
*/
@Json(name = "users_default") val usersDefault: Int = Role.Default.value,
@Json(name = "users_default") val usersDefault: Int? = null,
/**
* The power levels for specific users. This is a mapping from user_id to power level for that user.
*/
@Json(name = "users") val users: Map<String, Int> = emptyMap(),
@Json(name = "users") val users: Map<String, Int>? = null,
/**
* The default level required to send state events. Can be overridden by the events key. Defaults to 50 if unspecified.
*/
@Json(name = "state_default") val stateDefault: Int = Role.Moderator.value,
@Json(name = "state_default") val stateDefault: Int? = null,
/**
* The power level requirements for specific notification types. This is a mapping from key to power level for that notifications key.
*/
@Json(name = "notifications") val notifications: Map<String, Any> = emptyMap()
@Json(name = "notifications") val notifications: Map<String, Any>? = null
) {
/**
* Return a copy of this content with a new power level for the specified user
@ -74,7 +74,7 @@ data class PowerLevelsContent(
*/
fun setUserPowerLevel(userId: String, powerLevel: Int?): PowerLevelsContent {
return copy(
users = users.toMutableMap().apply {
users = users.orEmpty().toMutableMap().apply {
if (powerLevel == null || powerLevel == usersDefault) {
remove(userId)
} else {
@ -91,7 +91,7 @@ data class PowerLevelsContent(
* @return the level, default to Moderator if the key is not found
*/
fun notificationLevel(key: String): Int {
return when (val value = notifications[key]) {
return when (val value = notifications.orEmpty()[key]) {
// the first implementation was a string value
is String -> value.toInt()
is Double -> value.toInt()
@ -107,3 +107,12 @@ data class PowerLevelsContent(
const val NOTIFICATIONS_ROOM_KEY = "room"
}
}
// Fallback to default value, defined in the Matrix specification
fun PowerLevelsContent.banOrDefault() = ban ?: Role.Moderator.value
fun PowerLevelsContent.kickOrDefault() = kick ?: Role.Moderator.value
fun PowerLevelsContent.inviteOrDefault() = invite ?: Role.Moderator.value
fun PowerLevelsContent.redactOrDefault() = redact ?: Role.Moderator.value
fun PowerLevelsContent.eventsDefaultOrDefault() = eventsDefault ?: Role.Default.value
fun PowerLevelsContent.usersDefaultOrDefault() = usersDefault ?: Role.Default.value
fun PowerLevelsContent.stateDefaultOrDefault() = stateDefault ?: Role.Moderator.value

View file

@ -40,7 +40,7 @@ data class RoomGuestAccessContent(
}
@JsonClass(generateAdapter = false)
enum class GuestAccess {
@Json(name = "can_join") CanJoin,
@Json(name = "forbidden") Forbidden
enum class GuestAccess(val value: String) {
@Json(name = "can_join") CanJoin("can_join"),
@Json(name = "forbidden") Forbidden("forbidden")
}

View file

@ -16,35 +16,31 @@
package org.matrix.android.sdk.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* Ref: https://matrix.org/docs/spec/client_server/latest#room-history-visibility
*/
@JsonClass(generateAdapter = false)
enum class RoomHistoryVisibility {
/**
* All events while this is the m.room.history_visibility value may be shared by any
* participating homeserver with anyone, regardless of whether they have ever joined the room.
*/
@Json(name = "world_readable") WORLD_READABLE,
WORLD_READABLE,
/**
* Previous events are always accessible to newly joined members. All events in the
* room are accessible, even those sent when the member was not a part of the room.
*/
@Json(name = "shared") SHARED,
SHARED,
/**
* Events are accessible to newly joined members from the point they were invited onwards.
* Events stop being accessible when the member's state changes to something other than invite or join.
*/
@Json(name = "invited") INVITED,
INVITED,
/**
* Events are accessible to newly joined members from the point they joined the room onwards.
* Events stop being accessible when the member's state changes to something other than join.
*/
@Json(name = "joined") JOINED
JOINED
}

View file

@ -24,9 +24,10 @@ 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 {
@Json(name = "public") PUBLIC,
@Json(name = "invite") INVITE,
@Json(name = "knock") KNOCK,
@Json(name = "private") PRIVATE
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"),
@Json(name = "restricted") RESTRICTED("restricted")
}

View file

@ -0,0 +1,33 @@
/*
* 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.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class RoomJoinRulesAllowEntry(
/**
* space: The room ID of the space to check the membership of.
*/
@Json(name = "space") val spaceID: String,
/**
* via: A list of servers which may be used to peek for membership of the space.
*/
@Json(name = "via") val via: List<String>
)

View file

@ -1,5 +1,6 @@
/*
* 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.
@ -26,14 +27,19 @@ import timber.log.Timber
*/
@JsonClass(generateAdapter = true)
data class RoomJoinRulesContent(
@Json(name = "join_rule") val _joinRules: String? = null
@Json(name = "join_rule") val _joinRules: String? = null,
/**
* If the allow key is an empty list (or not a list at all), then the room reverts to standard public join rules
*/
@Json(name = "allow") val allowList: List<RoomJoinRulesAllowEntry>? = null
) {
val joinRules: RoomJoinRules? = when (_joinRules) {
"public" -> RoomJoinRules.PUBLIC
"invite" -> RoomJoinRules.INVITE
"knock" -> RoomJoinRules.KNOCK
"public" -> RoomJoinRules.PUBLIC
"invite" -> RoomJoinRules.INVITE
"knock" -> RoomJoinRules.KNOCK
"private" -> RoomJoinRules.PRIVATE
else -> {
"restricted" -> RoomJoinRules.RESTRICTED
else -> {
Timber.w("Invalid value for RoomJoinRules: `$_joinRules`")
null
}

View file

@ -37,6 +37,7 @@ data class RoomSummary constructor(
val canonicalAlias: String? = null,
val aliases: List<String> = emptyList(),
val isDirect: Boolean = false,
val directUserId: String? = null,
val joinedMembersCount: Int? = 0,
val invitedMembersCount: Int? = 0,
val latestPreviewableEvent: TimelineEvent? = null,
@ -48,6 +49,7 @@ data class RoomSummary constructor(
val hasUnreadMessages: Boolean = false,
val hasUnreadContentMessages: Boolean = false,
val hasUnreadOriginalContentMessages: Boolean = false,
val unreadCount: Int? = 0,
val markedUnread: Boolean = false,
val tags: List<RoomTag> = emptyList(),
val membership: Membership = Membership.NONE,
@ -60,7 +62,11 @@ data class RoomSummary constructor(
val inviterId: String? = null,
val breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS,
val roomEncryptionTrustLevel: RoomEncryptionTrustLevel? = null,
val hasFailedSending: Boolean = false
val hasFailedSending: Boolean = false,
val roomType: String? = null,
val spaceParents: List<SpaceParentInfo>? = null,
val spaceChildren: List<SpaceChildInfo>? = null,
val flattenParentIds: List<String> = emptyList()
) {
val isVersioned: Boolean

View file

@ -47,7 +47,7 @@ data class RoomThirdPartyInviteContent(
/**
* Keys with which the token may be signed.
*/
@Json(name = "public_keys") val publicKeys: List<PublicKeys>? = emptyList()
@Json(name = "public_keys") val publicKeys: List<PublicKeys>?
)
@JsonClass(generateAdapter = true)

View file

@ -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.model
object RoomType {
const val SPACE = "org.matrix.msc1772.space" // "m.space"
// const val MESSAGING = "org.matrix.msc1840.messaging"
}

View file

@ -0,0 +1,33 @@
/*
* 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
data class SpaceChildInfo(
val childRoomId: String,
// We might not know this child at all,
// i.e we just know it exists but no info on type/name/etc..
val isKnown: Boolean,
val roomType: String?,
val name: String?,
val topic: String?,
val avatarUrl: String?,
val order: String?,
val activeMemberCount: Int?,
val autoJoin: Boolean,
val viaServers: List<String>,
val parentRoomId: String?
)

View file

@ -1,5 +1,5 @@
/*
* Copyright 2019 New Vector Ltd
* 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.
@ -14,14 +14,11 @@
* limitations under the License.
*/
package im.vector.app.features.grouplist
package org.matrix.android.sdk.api.session.room.model
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Uninitialized
import org.matrix.android.sdk.api.session.group.model.GroupSummary
data class GroupListViewState(
val asyncGroups: Async<List<GroupSummary>> = Uninitialized,
val selectedGroup: GroupSummary? = null
) : MvRxState
data class SpaceParentInfo(
val parentId: String?,
val roomSummary: RoomSummary?,
val canonical: Boolean?,
val viaServers: List<String>
)

View file

@ -18,13 +18,15 @@ package org.matrix.android.sdk.api.session.room.model.create
import android.net.Uri
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
// TODO Give a way to include other initial states
class CreateRoomParams {
open class CreateRoomParams {
/**
* A public visibility indicates that the room will be shown in the published room list.
* A private visibility will hide the room from the published room list.
@ -68,6 +70,11 @@ class CreateRoomParams {
*/
val invite3pids = mutableListOf<ThreePid>()
/**
* Initial Guest Access
*/
var guestAccess: GuestAccess? = null
/**
* If set to true, when the room will be created, if cross-signing is enabled and we can get keys for every invited users,
* the encryption will be enabled on the created room
@ -111,6 +118,17 @@ class CreateRoomParams {
}
}
var roomType: String? = null // RoomType.MESSAGING
set(value) {
field = value
if (value != null) {
creationContent[CREATION_CONTENT_KEY_ROOM_TYPE] = value
} else {
// This is the default value, we remove the field
creationContent.remove(CREATION_CONTENT_KEY_ROOM_TYPE)
}
}
/**
* The power level content to override in the default power level event
*/
@ -136,7 +154,12 @@ class CreateRoomParams {
algorithm = MXCRYPTO_ALGORITHM_MEGOLM
}
var roomVersion: String? = null
var joinRuleRestricted: List<RoomJoinRulesAllowEntry>? = null
companion object {
private const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate"
private const val CREATION_CONTENT_KEY_ROOM_TYPE = "org.matrix.msc1772.type"
}
}

View file

@ -26,5 +26,7 @@ import com.squareup.moshi.JsonClass
data class RoomCreateContent(
@Json(name = "creator") val creator: String? = null,
@Json(name = "room_version") val roomVersion: String? = null,
@Json(name = "predecessor") val predecessor: Predecessor? = null
@Json(name = "predecessor") val predecessor: Predecessor? = null,
// Defines the room type, see #RoomType (user extensible)
@Json(name = "org.matrix.msc1772.type") val type: String? = null
)

View file

@ -16,6 +16,8 @@
package org.matrix.android.sdk.api.session.room.peeking
import org.matrix.android.sdk.api.util.MatrixItem
sealed class PeekResult {
data class Success(
val roomId: String,
@ -24,7 +26,9 @@ sealed class PeekResult {
val topic: String?,
val avatarUrl: String?,
val numJoinedMembers: Int?,
val viaServers: List<String>
val roomType: String?,
val viaServers: List<String>,
val someMembers: List<MatrixItem.UserItem>?
) : PeekResult()
data class PeekingNotAllowed(
@ -34,4 +38,6 @@ sealed class PeekResult {
) : PeekResult()
object UnknownAlias : PeekResult()
fun isSuccess() = this is Success
}

View file

@ -18,6 +18,13 @@
package org.matrix.android.sdk.api.session.room.powerlevels
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.banOrDefault
import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault
import org.matrix.android.sdk.api.session.room.model.inviteOrDefault
import org.matrix.android.sdk.api.session.room.model.kickOrDefault
import org.matrix.android.sdk.api.session.room.model.redactOrDefault
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
/**
* This class is an helper around PowerLevelsContent.
@ -31,9 +38,9 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
* @return the power level
*/
fun getUserPowerLevelValue(userId: String): Int {
return powerLevelsContent.users.getOrElse(userId) {
powerLevelsContent.usersDefault
}
return powerLevelsContent.users
?.get(userId)
?: powerLevelsContent.usersDefaultOrDefault()
}
/**
@ -45,7 +52,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
fun getUserRole(userId: String): Role {
val value = getUserPowerLevelValue(userId)
// I think we should use powerLevelsContent.usersDefault, but Ganfra told me that it was like that on riot-Web
return Role.fromValue(value, powerLevelsContent.eventsDefault)
return Role.fromValue(value, powerLevelsContent.eventsDefaultOrDefault())
}
/**
@ -59,11 +66,11 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
fun isUserAllowedToSend(userId: String, isState: Boolean, eventType: String?): Boolean {
return if (userId.isNotEmpty()) {
val powerLevel = getUserPowerLevelValue(userId)
val minimumPowerLevel = powerLevelsContent.events[eventType]
val minimumPowerLevel = powerLevelsContent.events?.get(eventType)
?: if (isState) {
powerLevelsContent.stateDefault
powerLevelsContent.stateDefaultOrDefault()
} else {
powerLevelsContent.eventsDefault
powerLevelsContent.eventsDefaultOrDefault()
}
powerLevel >= minimumPowerLevel
} else false
@ -76,7 +83,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
*/
fun isUserAbleToInvite(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.invite
return powerLevel >= powerLevelsContent.inviteOrDefault()
}
/**
@ -86,7 +93,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
*/
fun isUserAbleToBan(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.ban
return powerLevel >= powerLevelsContent.banOrDefault()
}
/**
@ -96,7 +103,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
*/
fun isUserAbleToKick(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.kick
return powerLevel >= powerLevelsContent.kickOrDefault()
}
/**
@ -106,6 +113,6 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
*/
fun isUserAbleToRedact(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.redact
return powerLevel >= powerLevelsContent.redactOrDefault()
}
}

View file

@ -22,7 +22,7 @@ data class RoomAggregateNotificationCount(
val unreadCount: Int,
val markedUnreadCount: Int
) {
val totalCount = notificationCount + highlightCount + markedUnreadCount
val totalCount = notificationCount + markedUnreadCount
val isHighlight = highlightCount > 0
val markedUnread = markedUnreadCount > 0
}

View file

@ -0,0 +1,35 @@
/*
* 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.space
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
class CreateSpaceParams : CreateRoomParams() {
init {
// Space-rooms are distinguished from regular messaging rooms by the m.room.type of m.space
roomType = RoomType.SPACE
// Space-rooms should be created with a power level for events_default of 100,
// to prevent the rooms accidentally/maliciously clogging up with messages from random members of the space.
powerLevelContentOverride = PowerLevelsContent(
eventsDefault = 100
)
}
}

View file

@ -0,0 +1,27 @@
/*
* 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.session.space
sealed class JoinSpaceResult {
object Success : JoinSpaceResult()
data class Fail(val error: Throwable) : JoinSpaceResult()
/** Success fully joined the space, but failed to join all or some of it's rooms */
data class PartialSuccess(val failedRooms: Map<String, Throwable>) : JoinSpaceResult()
fun isSuccess() = this is Success || this is PartialSuccess
}

View file

@ -0,0 +1,50 @@
/*
* 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.space
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.model.RoomSummary
interface Space {
fun asRoom(): Room
val spaceId: String
suspend fun leave(reason: String? = null)
/**
* A current snapshot of [RoomSummary] associated with the space
*/
fun spaceSummary(): RoomSummary?
suspend fun addChildren(roomId: String,
viaServers: List<String>,
order: String?,
autoJoin: Boolean = false,
suggested: Boolean? = false)
suspend fun removeChildren(roomId: String)
@Throws
suspend fun setChildrenOrder(roomId: String, order: String?)
@Throws
suspend fun setChildrenAutoJoin(roomId: String, autoJoin: Boolean)
// fun getChildren() : List<IRoomSummary>
}

View file

@ -0,0 +1,87 @@
/*
* 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.space
import android.net.Uri
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult
typealias SpaceSummaryQueryParams = RoomSummaryQueryParams
interface SpaceService {
/**
* Create a space asynchronously
* @return the spaceId of the created space
*/
suspend fun createSpace(params: CreateSpaceParams): String
/**
* Just a shortcut for space creation for ease of use
*/
suspend fun createSpace(name: String, topic: String?, avatarUri: Uri?, isPublic: Boolean): String
/**
* Get a space from a roomId
* @param spaceId the roomId to look for.
* @return a space with spaceId or null if room type is not space
*/
fun getSpace(spaceId: String): Space?
/**
* Try to resolve (peek) rooms and subspace in this space.
* Use this call get preview of children of this space, particularly useful to get a
* preview of rooms that you did not join yet.
*/
suspend fun peekSpace(spaceId: String): SpacePeekResult
/**
* Get's information of a space by querying the server
*/
suspend fun querySpaceChildren(spaceId: String,
suggestedOnly: Boolean? = null,
autoJoinedOnly: Boolean? = null): Pair<RoomSummary, List<SpaceChildInfo>>
/**
* Get a live list of space summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[SpaceSummary]
*/
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>>
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary>
suspend fun joinSpace(spaceIdOrAlias: String,
reason: String? = null,
viaServers: List<String> = emptyList()): JoinSpaceResult
suspend fun rejectInvite(spaceId: String, reason: String?)
// fun getSpaceParentsOfRoom(roomId: String) : List<SpaceSummary>
/**
* Let this room declare that it has a parent.
* @param canonical true if it should be the main parent of this room
* In practice, well behaved rooms should only have one canonical parent, but given this is not enforced:
* if multiple are present the client should select the one with the lowest room ID, as determined via a lexicographic utf-8 ordering.
*/
suspend fun setSpaceParent(childRoomId: String, parentSpaceId: String, canonical: Boolean, viaServers: List<String>)
fun getRootSpaceSummaries(): List<RoomSummary>
}

View file

@ -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.api.session.space.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* "content": {
* "via": ["example.com"],
* "order": "abcd",
* "default": true
* }
*/
@JsonClass(generateAdapter = true)
data class SpaceChildContent(
/**
* Key which gives a list of candidate servers that can be used to join the room
* Children where via is not present are ignored.
*/
@Json(name = "via") val via: List<String>? = null,
/**
* The order key is a string which is used to provide a default ordering of siblings in the room list.
* (Rooms are sorted based on a lexicographic ordering of order values; rooms with no order come last.
* orders which are not strings, or do not consist solely of ascii characters in the range \x20 (space) to \x7F (~),
* or consist of more than 50 characters, are forbidden and should be ignored if received.)
*/
@Json(name = "order") val order: String? = null,
/**
* The auto_join flag on a child listing allows a space admin to list the sub-spaces and rooms in that space which should
* be automatically joined by members of that space.
* (This is not a force-join, which are descoped for a future MSC; the user can subsequently part these room if they desire.)
*/
@Json(name = "auto_join") val autoJoin: Boolean? = false,
/**
* If `suggested` is set to `true`, that indicates that the child should be advertised to
* members of the space by the client. This could be done by showing them eagerly
* in the room list. This is should be ignored if `auto_join` is set to `true`.
*/
@Json(name = "suggested") val suggested: Boolean? = false
) {
/**
* Orders which are not strings, or do not consist solely of ascii characters in the range \x20 (space) to \x7F (~),
* or consist of more than 50 characters, are forbidden and should be ignored if received.)
*/
fun validOrder(): String? {
return order
?.takeIf { it.length <= 50 }
?.takeIf { ORDER_VALID_CHAR_REGEX.matches(it) }
}
companion object {
private val ORDER_VALID_CHAR_REGEX = "[ -~]+".toRegex()
}
}

View file

@ -0,0 +1,48 @@
/*
* 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.space.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* Rooms can claim parents via the m.space.parent state event.
* {
* "type": "m.space.parent",
* "state_key": "!space:example.com",
* "content": {
* "via": ["example.com"],
* "canonical": true,
* }
* }
*/
@JsonClass(generateAdapter = true)
data class SpaceParentContent(
/**
* Key which gives a list of candidate servers that can be used to join the parent.
* Parents where via is not present are ignored.
*/
@Json(name = "via") val via: List<String>? = null,
/**
* Canonical determines whether this is the main parent for the space.
* When a user joins a room with a canonical parent, clients may switch to view the room
* in the context of that space, peeking into it in order to find other rooms and group them together.
* In practice, well behaved rooms should only have one canonical parent, but given this is not enforced:
* if multiple are present the client should select the one with the lowest room ID, as determined via a lexicographic utf-8 ordering.
*/
@Json(name = "canonical") val canonical: Boolean? = false
)

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