Merge tag 'v1.3.7' into sc

Change-Id: Id73c834c10e11ccd46d7d2adc8328eb95d051941

Conflicts:
	matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
	matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt
	matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/VideoCompressor.kt
	vector/build.gradle
	vector/src/fdroid/AndroidManifest.xml
	vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt
	vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt
	vector/src/main/java/im/vector/app/VectorApplication.kt
	vector/src/main/java/im/vector/app/core/pushers/VectorMessagingReceiver.kt
	vector/src/main/java/im/vector/app/core/receiver/OnApplicationUpgradeOrRebootReceiver.kt
	vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
	vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt
	vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
	vector/src/main/java/im/vector/app/features/settings/VectorSettingsBaseFragment.kt
This commit is contained in:
SpiritCroc 2021-11-17 18:32:17 +01:00
commit c5f48fa4d2
427 changed files with 5008 additions and 3766 deletions

View File

@ -18,6 +18,5 @@ updates:
open-pull-requests-limit: 200 open-pull-requests-limit: 200
reviewers: reviewers:
- "bmarty" - "bmarty"
### ignore: ignore:
### - dependency-name: com.squareup.okhttp3:logging-interceptor - dependency-name: com.google.zxing:core
### versions: "> 3.12.10"

View File

@ -1,3 +1,39 @@
Changes in Element v1.3.7 (2021-11-04)
======================================
Features ✨
----------
- Adding the room name to the invitation notification (if the room summary is available) ([#582](https://github.com/vector-im/element-android/issues/582))
- Updating single sign on providers ordering to match priority/popularity ([#4277](https://github.com/vector-im/element-android/issues/4277))
Bugfixes 🐛
----------
- Stops showing a dedicated redacted event notification, the message notifications will update accordingly ([#1491](https://github.com/vector-im/element-android/issues/1491))
- Fixes marking individual notifications as read causing other notifications to be dismissed ([#3395](https://github.com/vector-im/element-android/issues/3395))
- Fixing missing send button in light mode dev tools - send * event ([#3674](https://github.com/vector-im/element-android/issues/3674))
- Fixing room search needing exact casing for non latin-1 character named rooms ([#3968](https://github.com/vector-im/element-android/issues/3968))
- Fixing call ringtones only playing once when the ringtone doesn't contain looping metadata (android 9.0 and above) ([#4047](https://github.com/vector-im/element-android/issues/4047))
- Tentatively fixing the doubled notifications by updating the group summary at specific points in the notification rendering cycle ([#4152](https://github.com/vector-im/element-android/issues/4152))
- Do not show shortcuts if a PIN code is set ([#4170](https://github.com/vector-im/element-android/issues/4170))
- Fixes being unable to join rooms by name ([#4255](https://github.com/vector-im/element-android/issues/4255))
- Fixing missing F-Droid notifications when in background due to background syncs not triggering ([#4298](https://github.com/vector-im/element-android/issues/4298))
- Fix video compression before upload ([#4353](https://github.com/vector-im/element-android/issues/4353))
- Fixing QR code crashes caused by a known issue in the zxing library for older versions of android by downgrading to 3.3.3 ([#4361](https://github.com/vector-im/element-android/issues/4361))
- Fixing timeline crash when rotating with the emoji window open ([#4365](https://github.com/vector-im/element-android/issues/4365))
- Fix handling of links coming from web instance reported as malformed by mistake ([#4369](https://github.com/vector-im/element-android/issues/4369))
SDK API changes ⚠️
------------------
- Add API `LoginWizard.loginCustom(data: JsonDict): Session` to be able to login to a homeserver using arbitrary request content ([#4266](https://github.com/vector-im/element-android/issues/4266))
- Add optional deviceId to the login API ([#4334](https://github.com/vector-im/element-android/issues/4334))
Other changes
-------------
- Migrate app DI framework to Hilt ([#3888](https://github.com/vector-im/element-android/issues/3888))
- Limit supported TLS versions and cipher suites ([#4192](https://github.com/vector-im/element-android/issues/4192))
- Fixed capitalisation of text on initial sync screen ([#4292](https://github.com/vector-im/element-android/issues/4292))
Changes in Element v1.3.6 (2021-10-26) Changes in Element v1.3.6 (2021-10-26)
====================================== ======================================

View File

@ -17,6 +17,7 @@ buildscript {
// https://developer.android.com/studio/releases/gradle-plugin // https://developer.android.com/studio/releases/gradle-plugin
classpath libs.gradle.gradlePlugin classpath libs.gradle.gradlePlugin
classpath libs.gradle.kotlinPlugin classpath libs.gradle.kotlinPlugin
classpath libs.gradle.hiltPlugin
classpath 'com.google.gms:google-services:4.3.10' classpath 'com.google.gms:google-services:4.3.10'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.4' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.4'

View File

@ -11,7 +11,7 @@ def gradle = "7.0.3"
// Ref: https://kotlinlang.org/releases.html // Ref: https://kotlinlang.org/releases.html
def kotlin = "1.5.31" def kotlin = "1.5.31"
def kotlinCoroutines = "1.5.2" def kotlinCoroutines = "1.5.2"
def dagger = "2.39.1" def dagger = "2.40"
def retrofit = "2.9.0" def retrofit = "2.9.0"
def arrow = "0.8.2" def arrow = "0.8.2"
def markwon = "4.6.2" def markwon = "4.6.2"
@ -34,7 +34,9 @@ def androidxTest = "1.4.0"
ext.libs = [ ext.libs = [
gradle : [ gradle : [
'gradlePlugin' : "com.android.tools.build:gradle:$gradle", 'gradlePlugin' : "com.android.tools.build:gradle:$gradle",
'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin" 'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin",
'hiltPlugin' : "com.google.dagger:hilt-android-gradle-plugin:$dagger"
], ],
jetbrains : [ jetbrains : [
'kotlinReflect' : "org.jetbrains.kotlin:kotlin-reflect:$kotlin", 'kotlinReflect' : "org.jetbrains.kotlin:kotlin-reflect:$kotlin",
@ -73,7 +75,9 @@ ext.libs = [
], ],
dagger : [ dagger : [
'dagger' : "com.google.dagger:dagger:$dagger", 'dagger' : "com.google.dagger:dagger:$dagger",
'daggerCompiler' : "com.google.dagger:dagger-compiler:$dagger" 'daggerCompiler' : "com.google.dagger:dagger-compiler:$dagger",
'hilt' : "com.google.dagger:hilt-android:$dagger",
'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
], ],
squareup : [ squareup : [
'moshi' : "com.squareup.moshi:moshi-adapters:$moshi", 'moshi' : "com.squareup.moshi:moshi-adapters:$moshi",

33
docs/hilt_migration.md Normal file
View File

@ -0,0 +1,33 @@
Useful links:
- https://dagger.dev/hilt/migration-guide
- https://dagger.dev/hilt/quick-start
Hilt is built on top of Dagger 2 and simplify usage by removing needs to create components manually.
When you create a new feature, you should have the following:
Annotate your Activity with @AndroidEntryPoint
If you have a BottomSheetFragment => Annotate it with @AndroidEntryPoint
Otherwise => Add your Fragment to the FragmentModule
Add your ViewModel.Factory to the MavericksViewModelModule
Makes sure your ViewModel as the following code:
```
@AssistedFactory
interface Factory: MavericksAssistedViewModelFactory<MyViewModel, MyViewState> {
override fun create(initialState: MyViewState): MyViewModel
}
companion object : MavericksViewModelFactory<MyViewModel, MyViewState> by hiltMavericksViewModelFactory()
```
## Some remarks
@MavericksViewModelScope dependencies can't be injected inside Fragments/Activities
You can only inject @Singleton, @MavericksViewModelScope or unscoped dependencies inside Maverick ViewModels
You can access some specific dependencies from Singleton component by using
```
context.singletonEntryPoint()
```
Be aware that only the app has been migrated to Hilt and not the SDK.

View File

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Přidání podpory přítomnosti pro místnost s přímými zprávami (poznámka: přítomnost je na matrix.org zakázána). Opět přidána podpora Android Auto.
Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Hauptänderungen: Organisiere deine Räume mit Spaces!
Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.0

View File

@ -0,0 +1,2 @@
Hauptänderungen: Organisiere deine Räume mit Spaces, Crash aus 1.3.0 gefixt.
Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.1

View File

@ -0,0 +1,2 @@
Hauptänderungen: Unterstützung für Android Auto, Viele Fehlerbehebungen
Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.2

View File

@ -0,0 +1,2 @@
Hauptänderungen: Bedingungen des Identitätsservers in Einstellungen anzeigen. Unterstützung für Android Auto temporär entfernt.
Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.3

View File

@ -0,0 +1,4 @@
Hauptänderungen:
- Anwesenheiten in Direktnachrichten anzeigen (Momentan auf Matrix.org deaktiviert)
- Android Auto wird wieder unterstützt
Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -37,3 +37,6 @@ Kurznachrichten, Sprach- und Videoanrufe, Dateifreigaben, Bildschirmübertragung
<b>Da Weitermachen, wo Sie aufgehört haben</b> <b>Da Weitermachen, wo Sie aufgehört haben</b>
Bleiben Sie in Kontakt, egal wo Sie sind, mit vollständig synchronisiertem Nachrichtenverlauf quer über all Ihre Geräte und im Netz auf https://app.element.io Bleiben Sie in Kontakt, egal wo Sie sind, mit vollständig synchronisiertem Nachrichtenverlauf quer über all Ihre Geräte und im Netz auf https://app.element.io
<b>Open source</b>
Element ist ein Open-Source-Projekt und wird auf GitHub gehostet. Solltest du Fehler in Element finden, melde diese bitte hier: https://github.com/vector-im/element-android

View File

@ -0,0 +1,2 @@
Main changes in this version: Bug fixes mainly regarding the notifications.
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.7

View File

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: Lisasime otsevestlustele kasutaja võrguolekute toe (matrix.org puhul on välja lülitatud) ja uuesti lisasime Android Auto toe.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
تغییرات اصلی در این نگارش: افزودن پشتیبانی حضور برای اتاق پیام خصوصی (توجه: حضور روی matrix.org از کار افتاده است). افزودن دوبارهٔ پشتیبانی اندروید خودرو.
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Principaux changements pour cette version : ajout du support pour les indicateurs de présence, dans les conversations privées (attention : les indicateurs de présence sont désactivés sur matrix.org). Réactivation de la prise en charge de Android Auto.
Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Fő változás ebben a verzióban: Állapot állítási lehetőség közvetlen beszélgetéseknél (megj.: a matrix.org-on az állapot jelzés ki van kapcsolva). Újra elérhető az Android Auto.
Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Perubahan utama di versi ini: Menambahkan dukungan presensi, untuk ruangan Pesan Langsung (diingat bahwa presensi dinonaktifkan di matrix.org). Menambahkan lagi dukungan Android Auto.
Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Modifiche principali in questa versione: aggiunto supporto alla presenza per messaggi diretti (nota: la presenza è disattivata su matrix.org). Aggiunto di nuovo il supporto ad Android Auto.
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Adicionar suporte a Presença, para sala de Mensagem Direta (nota: presença está desabilitada em matrix.org). Adicionar de novo suporte a Android Auto.
Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Основные изменения в этой версии: Добавлена поддержка присутствия, для комнат личных сообщений (примечание: присутствие отключено на matrix.org). Снова добавлена поддержка Android Auto.
Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Ndryshimet kryesore në këtë version: Shtim mbulimi për Prani, për dhomë Mesazh i Drejtpërdrejtë (shënim: në matrix.org prania është e çaktivizuar. Shtim sërish i mbulimit për Android Auto.
Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Huvudsakliga ändringar i den här versionen: Lägg till närvarostöd för direktmeddelanden (obs: närvaro är inaktiverat på matrix.org). Lägg till stöd för Android Auto igen.
Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Основні зміни в цій версії: Додано підтримку присутності для кімнати особистих повідомлень (примітка: присутність вимкнено на matrix.org. Знову додано підтримку Android Auto.
Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: xem trước URL, bàn phím Emoji mới, các khả năng cài đặt phòng mới và tuyết cho Giáng Sinh!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.12

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: xem trước URL, bàn phím Emoji mới, các khả năng cài đặt phòng mới và tuyết cho Giáng Sinh!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.13

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: chỉnh sửa quyền phòng, chủ đề Sáng/Tối tự động, và một loạt các bản sửa lỗi.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.14

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: hỗ trợ đăng nhập từ mạng xã hội.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.15

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: hỗ trợ đăng nhập từ mạng xã hội.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.15 và https://github.com/vector-im/element-android/releases/tag/v1.0.16

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Sửa lỗi!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.17

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cải tiến VoIP (các cuộc gọi thoại và video trong Tin nhắn Trực tiếp) và sửa lỗi!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.0

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.1

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.2

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.3

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.4

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: sửa lỗi nhanh cho 1.1.4
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.5

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: sửa lỗi nhanh cho 1.1.5
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.6

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: hỗ trợ beta cho Space. Nén video trước khi gửi.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.7

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Cải tiến cho Space.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.8

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: thêm hỗ trợ cho mạng gitter.im.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.9

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cập nhật chủ đề và phong cách và các tính năng mới cho Space.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.10

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cập nhật chủ đề và phong cách và các tính năng mới cho Space (sửa lỗi cho 1.1.1.0)
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.11

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: cập nhật chủ đề và phong cách và sửa lỗi sau khi gọi video
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.12

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: chủ yếu là sự ổn định và cập nhật sửa lỗi.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.13

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: sửa lỗi các tin nhắn mã hóa.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.14

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: triển khai tin nhắn thoại trong cài đặt thí nghiệm.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.15

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Sửa lỗi gửi tin nhắn mã hóa khi có ai đó trong phòng đăng xuất.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.16

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Tin nhắn Thoại được bật mặc định.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.2.0

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Nhiều cải tiến trong VoIP và Space (vẫn đang trong beta).
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.2.1

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Sắp xếp các phòng của bạn bằng Space!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.0

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Sắp xếp các phòng của bạn bằng Space! V1.3.1 khắc phục sự cố có thể xảy ra ở v1.3.0
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.1

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Thêm hỗ trợ Android Auto. Sửa rất nhiều lỗi!
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.2

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Hiển thị (các) chính sách máy chủ xác thực trong phần cài đặt. Tạm thời bỏ hỗ trợ Android Auto.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.3

View File

@ -0,0 +1,2 @@
Những thay đổi chính trong phiên bản này: Thêm hỗ trợ hiển thị, cho phòng Tin nhắn Trực tiếp (lưu ý: hiển thị bị vô hiệu hóa trên matrix.org. Thêm hỗ trợ Android Auto trở lại.
Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,42 @@
Element vừa là một ứng dụng nhắn tin an toàn vừa là một ứng dụng cộng tác nhóm năng suất, lý tưởng cho các cuộc trò chuyện nhóm trong khi làm việc từ xa. Ứng dụng trò chuyện này sử dụng mã hóa đầu cuối để cung cấp tính năng hội nghị truyền hình, chia sẻ tệp và cuộc gọi thoại mạnh mẽ.
<b> Các tính năng của Element bao gồm: </b>
- Các công cụ giao tiếp trực tuyến tiên tiến
- Các tin nhắn được mã hóa hoàn toàn để cho phép liên lạc doanh nghiệp an toàn hơn, ngay cả đối với những người làm việc từ xa
- Trò chuyện phi tập trung dựa trên khung mã nguồn mở Matrix
- Chia sẻ tệp một cách an toàn với dữ liệu được mã hóa trong khi quản lý dự án
- Trò chuyện video với VoIP và chia sẻ màn hình
- Tích hợp dễ dàng với các công cụ cộng tác trực tuyến yêu thích của bạn, công cụ quản lý dự án, dịch vụ VoIP và các ứng dụng nhắn tin nhóm khác
Element hoàn toàn khác với các ứng dụng nhắn tin và cộng tác khác. Nó hoạt động trên Matrix, một mạng mở để nhắn tin bảo mật và giao tiếp phi tập trung. Nó cho phép tự lưu trữ để cung cấp cho người dùng quyền sở hữu và kiểm soát tối đa dữ liệu và tin nhắn của họ.
<b> Nhắn tin mã hóa và riêng tư </b>
Element bảo vệ bạn khỏi các quảng cáo không mong muốn, khai thác dữ liệu và khu vườn có tường bao quanh. Nó cũng bảo mật tất cả dữ liệu của bạn, video 1-1 và giao tiếp thoại thông qua mã hóa đầu cuối và xác minh thiết bị có chữ ký chéo.
Element cung cấp cho bạn quyền kiểm soát quyền riêng tư của mình đồng thời cho phép bạn giao tiếp an toàn với bất kỳ ai trên mạng Ma trận hoặc các công cụ cộng tác kinh doanh khác bằng cách tích hợp với các ứng dụng như Slack.
<b> Phần tử có thể được tự lưu trữ </b>
Để cho phép kiểm soát nhiều hơn dữ liệu nhạy cảm và các cuộc trò chuyện của bạn, Element có thể được tự host hoặc bạn có thể chọn bất kỳ host Matrix nào - tiêu chuẩn cho giao tiếp phân tán, mã nguồn mở. Element cung cấp cho bạn quyền riêng tư, tuân thủ bảo mật và tính linh hoạt trong tích hợp.
<b> Sở hữu dữ liệu của bạn </b>
Bạn quyết định nơi lưu giữ dữ liệu và tin nhắn của mình. Không có rủi ro khai thác dữ liệu hoặc truy cập từ bên thứ ba.
Element giúp bạn kiểm soát theo những cách khác nhau:
1. Nhận một tài khoản miễn phí trên máy chủ công cộng matrix.org do các nhà phát triển Matrix host hoặc chọn từ hàng nghìn máy chủ công cộng do các tình nguyện viên lưu trữ
2. Tự host tài khoản của bạn bằng cách chạy một máy chủ trên cơ sở hạ tầng CNTT của riêng bạn
3. Đăng ký tài khoản trên máy chủ tùy chỉnh bằng cách chỉ cần đăng ký nền tảng Element Matrix Services hosting
<b> Mở tin nhắn và cộng tác </b>
Bạn có thể trò chuyện với bất kỳ ai trên mạng Matrix, cho dù họ đang sử dụng Element, một ứng dụng Matrix khác hay ngay cả khi họ đang sử dụng một ứng dụng nhắn tin khác.
<b> Siêu bảo mật </b>
Mã hóa đầu-cuối thực (chỉ những người trong cuộc trò chuyện mới có thể giải mã tin nhắn) và xác minh thiết bị xác thực chéo.
<b> Giao tiếp và tích hợp hoàn chỉnh </b>
Nhắn tin, cuộc gọi thoại và video, chia sẻ tệp, chia sẻ màn hình và một loạt các tích hợp, bot và widget. Xây dựng phòng, cộng đồng, giữ liên lạc và hoàn thành công việc.
<b> Tiếp tục nơi bạn đã dừng lại </b>
Giữ liên lạc mọi lúc mọi nơi với lịch sử tin nhắn được đồng bộ hóa hoàn toàn trên tất cả các thiết bị của bạn và trên web tại https://app.element.io
<b> Mã nguồn mở </b>
Element Android là một dự án mã nguồn mở, được host bởi GitHub. Vui lòng báo cáo lỗi và / hoặc đóng góp vào sự phát triển của nó tại https://github.com/vector-im/element-android

View File

@ -0,0 +1,2 @@
此版本主要变化:为 Direct Message 聊天室添加 Presence 支持 (注意Presence 在matrix.org 上是禁用的。再次添加 Android Auto 支持。
完整更新日志https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -0,0 +1,2 @@
此版本中的主要變動:為直接訊息聊天室新增 Presence 支援(請注意:此功能在 matrix.org 上停用)。加回 Android Auto 支援。
完整的變更紀錄https://github.com/vector-im/element-android/releases/tag/v1.3.4

View File

@ -31,7 +31,7 @@ android {
// that the app's state is completely cleared between tests. // that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true' testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "SDK_VERSION", "\"1.3.6\"" buildConfigField "String", "SDK_VERSION", "\"1.3.7\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
resValue "string", "git_sdk_revision", "\"${gitRevision()}\"" resValue "string", "git_sdk_revision", "\"${gitRevision()}\""
@ -156,7 +156,7 @@ dependencies {
implementation libs.apache.commonsImaging implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber // Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.35' implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.36'
testImplementation libs.tests.junit testImplementation libs.tests.junit
testImplementation 'org.robolectric:robolectric:4.6.1' testImplementation 'org.robolectric:robolectric:4.6.1'

View File

@ -16,6 +16,7 @@
package org.matrix.android.sdk.api package org.matrix.android.sdk.api
import okhttp3.ConnectionSpec
import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import java.net.Proxy import java.net.Proxy
@ -44,6 +45,10 @@ data class MatrixConfiguration(
* You can create one using for instance Proxy(proxyType, InetSocketAddress.createUnresolved(hostname, port). * You can create one using for instance Proxy(proxyType, InetSocketAddress.createUnresolved(hostname, port).
*/ */
val proxy: Proxy? = null, val proxy: Proxy? = null,
/**
* TLS versions and cipher suites limitation for unauthenticated requests
*/
val connectionSpec: ConnectionSpec = ConnectionSpec.RESTRICTED_TLS,
/** /**
* True to advertise support for call transfers to other parties on Matrix calls. * True to advertise support for call transfers to other parties on Matrix calls.
*/ */

View File

@ -105,9 +105,15 @@ interface AuthenticationService {
/** /**
* Authenticate with a matrixId and a password * Authenticate with a matrixId and a password
* Usually call this after a successful call to getWellKnownData() * Usually call this after a successful call to getWellKnownData()
* @param homeServerConnectionConfig the information about the homeserver and other configuration
* @param matrixId the matrixId of the user
* @param password the password of the account
* @param initialDeviceName the initial device name
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
*/ */
suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig, suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
matrixId: String, matrixId: String,
password: String, password: String,
initialDeviceName: String): Session initialDeviceName: String,
deviceId: String? = null): Session
} }

View File

@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.auth.data
import android.net.Uri import android.net.Uri
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import okhttp3.CipherSuite import okhttp3.CipherSuite
import okhttp3.ConnectionSpec
import okhttp3.TlsVersion import okhttp3.TlsVersion
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder
import org.matrix.android.sdk.internal.network.ssl.Fingerprint import org.matrix.android.sdk.internal.network.ssl.Fingerprint
@ -191,32 +192,25 @@ data class HomeServerConnectionConfig(
/** /**
* Convenient method to limit the TLS versions and cipher suites for this Builder * Convenient method to limit the TLS versions and cipher suites for this Builder
* Ref: * Ref:
* - https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf * - https://www.ssi.gouv.fr/uploads/2017/07/anssi-guide-recommandations_de_securite_relatives_a_tls-v1.2.pdf
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine * - https://developer.android.com/reference/javax/net/ssl/SSLEngine
* *
* @param tlsLimitations true to use Tls limitations * @param tlsLimitations true to use Tls limitations
* @param enableCompatibilityMode set to true for Android < 20 * @param enableCompatibilityMode set to true for Android < 20
* @return this builder * @return this builder
*/ */
@Deprecated("TLS versions and cipher suites are limited by default")
fun withTlsLimitations(tlsLimitations: Boolean, enableCompatibilityMode: Boolean): Builder { fun withTlsLimitations(tlsLimitations: Boolean, enableCompatibilityMode: Boolean): Builder {
if (tlsLimitations) { if (tlsLimitations) {
withShouldAcceptTlsExtensions(false) withShouldAcceptTlsExtensions(false)
// Tls versions // TlS versions
addAcceptedTlsVersion(TlsVersion.TLS_1_2) ConnectionSpec.RESTRICTED_TLS.tlsVersions?.let { this.tlsVersions.addAll(it) }
addAcceptedTlsVersion(TlsVersion.TLS_1_3)
forceUsageOfTlsVersions(enableCompatibilityMode) forceUsageOfTlsVersions(enableCompatibilityMode)
// Cipher suites // Cipher suites
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ConnectionSpec.RESTRICTED_TLS.cipherSuites?.let { this.tlsCipherSuites.addAll(it) }
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)
if (enableCompatibilityMode) { if (enableCompatibilityMode) {
// Adopt some preceding cipher suites for Android < 20 to be able to negotiate // Adopt some preceding cipher suites for Android < 20 to be able to negotiate

View File

@ -17,6 +17,7 @@
package org.matrix.android.sdk.api.auth.login package org.matrix.android.sdk.api.auth.login
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.util.JsonDict
/** /**
* Set of methods to be able to login to an existing account on a homeserver. * Set of methods to be able to login to an existing account on a homeserver.
@ -34,12 +35,14 @@ interface LoginWizard {
* *
* @param login the login field. Can be a user name, or a msisdn (email or phone number) associated to the account * @param login the login field. Can be a user name, or a msisdn (email or phone number) associated to the account
* @param password the password of the account * @param password the password of the account
* @param deviceName the initial device name * @param initialDeviceName the initial device name
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
* @return a [Session] if the login is successful * @return a [Session] if the login is successful
*/ */
suspend fun login(login: String, suspend fun login(login: String,
password: String, password: String,
deviceName: String): Session initialDeviceName: String,
deviceId: String? = null): Session
/** /**
* Exchange a login token to an access token. * Exchange a login token to an access token.
@ -49,6 +52,12 @@ interface LoginWizard {
*/ */
suspend fun loginWithToken(loginToken: String): Session suspend fun loginWithToken(loginToken: String): Session
/**
* Login to the homeserver by sending a custom JsonDict.
* The data should contain at least one entry "type" with a String value.
*/
suspend fun loginCustom(data: JsonDict): Session
/** /**
* Ask the homeserver to reset the user password. The password will not be reset until * Ask the homeserver to reset the user password. The password will not be reset until
* [resetPasswordMailConfirmed] is successfully called. * [resetPasswordMailConfirmed] is successfully called.

View File

@ -19,17 +19,41 @@ package org.matrix.android.sdk.api.query
/** /**
* Basic query language. All these cases are mutually exclusive. * Basic query language. All these cases are mutually exclusive.
*/ */
sealed class QueryStringValue { sealed interface QueryStringValue {
object NoCondition : QueryStringValue() sealed interface ContentQueryStringValue : QueryStringValue {
object IsNull : QueryStringValue() val string: String
object IsNotNull : QueryStringValue() val case: Case
object IsEmpty : QueryStringValue() }
object IsNotEmpty : QueryStringValue()
data class Equals(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue() object NoCondition : QueryStringValue
data class Contains(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue() object IsNull : QueryStringValue
object IsNotNull : QueryStringValue
object IsEmpty : QueryStringValue
object IsNotEmpty : QueryStringValue
data class Equals(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
data class Contains(override val string: String, override val case: Case = Case.SENSITIVE) : ContentQueryStringValue
enum class Case { enum class Case {
/**
* Match query sensitive to case
*/
SENSITIVE, SENSITIVE,
INSENSITIVE
/**
* Match query insensitive to case, this only works for Latin-1 character sets
*/
INSENSITIVE,
/**
* Match query with input normalized (case insensitive)
* Works around Realms inability to sort or filter by case for non Latin-1 character sets
* Expects the target field to contain normalized data
*
* @see org.matrix.android.sdk.internal.util.Normalizer.normalize
*/
NORMALIZED
} }
} }
internal fun QueryStringValue.isNormalized() = this is QueryStringValue.ContentQueryStringValue && case == QueryStringValue.Case.NORMALIZED

View File

@ -120,9 +120,11 @@ interface Session :
fun requireBackgroundSync() fun requireBackgroundSync()
/** /**
* Launches infinite periodic background syncs * Launches infinite self rescheduling background syncs via the WorkManager
* This does not work in doze mode :/ *
* If battery optimization is on it can work in app standby but that's all :/ * While dozing, syncs will only occur during maintenance windows
* For reliability it's recommended to also start a long running foreground service
* along with disabling battery optimizations
*/ */
fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long) fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long)

View File

@ -22,6 +22,8 @@ import org.json.JSONObject
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
@ -310,3 +312,6 @@ fun Event.isEdition(): Boolean {
fun Event.getPresenceContent(): PresenceContent? { fun Event.getPresenceContent(): PresenceContent? {
return content.toModel<PresenceContent>() return content.toModel<PresenceContent>()
} }
fun Event.isInvitation(): Boolean = type == EventType.STATE_ROOM_MEMBER &&
content?.toModel<RoomMemberContent>()?.membership == Membership.INVITE

View File

@ -94,13 +94,15 @@ interface RoomService {
* Get a snapshot list of room summaries. * Get a snapshot list of room summaries.
* @return the immutable list of [RoomSummary] * @return the immutable list of [RoomSummary]
*/ */
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary>
/** /**
* Get a live list of room summaries. This list is refreshed as soon as the data changes. * Get a live list of room summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[RoomSummary] * @return the [LiveData] of List[RoomSummary]
*/ */
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData<List<RoomSummary>>
/** /**
* Get a snapshot list of Breadcrumbs * Get a snapshot list of Breadcrumbs

View File

@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.session.space
import android.net.Uri import android.net.Uri
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult
@ -74,9 +75,11 @@ interface SpaceService {
* Get a live list of space summaries. This list is refreshed as soon as the data changes. * Get a live list of space summaries. This list is refreshed as soon as the data changes.
* @return the [LiveData] of List[SpaceSummary] * @return the [LiveData] of List[SpaceSummary]
*/ */
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>>
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary>
suspend fun joinSpace(spaceIdOrAlias: String, suspend fun joinSpace(spaceIdOrAlias: String,
reason: String? = null, reason: String? = null,

View File

@ -121,6 +121,10 @@ internal interface AuthAPI {
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login") @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
suspend fun login(@Body loginParams: TokenLoginParams): Credentials suspend fun login(@Body loginParams: TokenLoginParams): Credentials
@Headers("CONNECT_TIMEOUT:60000", "READ_TIMEOUT:60000", "WRITE_TIMEOUT:60000")
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
suspend fun login(@Body loginParams: JsonDict): Credentials
/** /**
* Ask the homeserver to reset the password associated with the provided email. * Ask the homeserver to reset the password associated with the provided email.
*/ */

View File

@ -388,8 +388,15 @@ internal class DefaultAuthenticationService @Inject constructor(
override suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig, override suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
matrixId: String, matrixId: String,
password: String, password: String,
initialDeviceName: String): Session { initialDeviceName: String,
return directLoginTask.execute(DirectLoginTask.Params(homeServerConnectionConfig, matrixId, password, initialDeviceName)) deviceId: String?): Session {
return directLoginTask.execute(DirectLoginTask.Params(
homeServerConnectionConfig = homeServerConnectionConfig,
userId = matrixId,
password = password,
deviceName = initialDeviceName,
deviceId = deviceId
))
} }
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI { private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {

View File

@ -49,51 +49,54 @@ internal data class PasswordLoginParams(
fun userIdentifier(user: String, fun userIdentifier(user: String,
password: String, password: String,
deviceDisplayName: String? = null, deviceDisplayName: String?,
deviceId: String? = null): PasswordLoginParams { deviceId: String?): PasswordLoginParams {
return PasswordLoginParams( return PasswordLoginParams(
mapOf( identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_USER, IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_USER,
IDENTIFIER_KEY_USER to user IDENTIFIER_KEY_USER to user
), ),
password, password = password,
LoginFlowTypes.PASSWORD, type = LoginFlowTypes.PASSWORD,
deviceDisplayName, deviceDisplayName = deviceDisplayName,
deviceId) deviceId = deviceId
)
} }
fun thirdPartyIdentifier(medium: String, fun thirdPartyIdentifier(medium: String,
address: String, address: String,
password: String, password: String,
deviceDisplayName: String? = null, deviceDisplayName: String?,
deviceId: String? = null): PasswordLoginParams { deviceId: String?): PasswordLoginParams {
return PasswordLoginParams( return PasswordLoginParams(
mapOf( identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_THIRD_PARTY, IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_THIRD_PARTY,
IDENTIFIER_KEY_MEDIUM to medium, IDENTIFIER_KEY_MEDIUM to medium,
IDENTIFIER_KEY_ADDRESS to address IDENTIFIER_KEY_ADDRESS to address
), ),
password, password = password,
LoginFlowTypes.PASSWORD, type = LoginFlowTypes.PASSWORD,
deviceDisplayName, deviceDisplayName = deviceDisplayName,
deviceId) deviceId = deviceId
)
} }
fun phoneIdentifier(country: String, fun phoneIdentifier(country: String,
phone: String, phone: String,
password: String, password: String,
deviceDisplayName: String? = null, deviceDisplayName: String?,
deviceId: String? = null): PasswordLoginParams { deviceId: String?): PasswordLoginParams {
return PasswordLoginParams( return PasswordLoginParams(
mapOf( identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_PHONE, IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_PHONE,
IDENTIFIER_KEY_COUNTRY to country, IDENTIFIER_KEY_COUNTRY to country,
IDENTIFIER_KEY_PHONE to phone IDENTIFIER_KEY_PHONE to phone
), ),
password, password = password,
LoginFlowTypes.PASSWORD, type = LoginFlowTypes.PASSWORD,
deviceDisplayName, deviceDisplayName = deviceDisplayName,
deviceId) deviceId = deviceId
)
} }
} }
} }

View File

@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.auth.login.LoginProfileInfo
import org.matrix.android.sdk.api.auth.login.LoginWizard import org.matrix.android.sdk.api.auth.login.LoginWizard
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.auth.AuthAPI import org.matrix.android.sdk.internal.auth.AuthAPI
import org.matrix.android.sdk.internal.auth.PendingSessionStore import org.matrix.android.sdk.internal.auth.PendingSessionStore
import org.matrix.android.sdk.internal.auth.SessionCreator import org.matrix.android.sdk.internal.auth.SessionCreator
@ -52,11 +53,23 @@ internal class DefaultLoginWizard(
override suspend fun login(login: String, override suspend fun login(login: String,
password: String, password: String,
deviceName: String): Session { initialDeviceName: String,
deviceId: String?): Session {
val loginParams = if (Patterns.EMAIL_ADDRESS.matcher(login).matches()) { val loginParams = if (Patterns.EMAIL_ADDRESS.matcher(login).matches()) {
PasswordLoginParams.thirdPartyIdentifier(ThreePidMedium.EMAIL, login, password, deviceName) PasswordLoginParams.thirdPartyIdentifier(
medium = ThreePidMedium.EMAIL,
address = login,
password = password,
deviceDisplayName = initialDeviceName,
deviceId = deviceId
)
} else { } else {
PasswordLoginParams.userIdentifier(login, password, deviceName) PasswordLoginParams.userIdentifier(
user = login,
password = password,
deviceDisplayName = initialDeviceName,
deviceId = deviceId
)
} }
val credentials = executeRequest(null) { val credentials = executeRequest(null) {
authAPI.login(loginParams) authAPI.login(loginParams)
@ -79,6 +92,14 @@ internal class DefaultLoginWizard(
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig) return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
} }
override suspend fun loginCustom(data: JsonDict): Session {
val credentials = executeRequest(null) {
authAPI.login(data)
}
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
}
override suspend fun resetPassword(email: String, newPassword: String) { override suspend fun resetPassword(email: String, newPassword: String) {
val param = RegisterAddThreePidTask.Params( val param = RegisterAddThreePidTask.Params(
RegisterThreePid.Email(email), RegisterThreePid.Email(email),

View File

@ -37,7 +37,8 @@ internal interface DirectLoginTask : Task<DirectLoginTask.Params, Session> {
val homeServerConnectionConfig: HomeServerConnectionConfig, val homeServerConnectionConfig: HomeServerConnectionConfig,
val userId: String, val userId: String,
val password: String, val password: String,
val deviceName: String val deviceName: String,
val deviceId: String?
) )
} }
@ -55,7 +56,12 @@ internal class DefaultDirectLoginTask @Inject constructor(
val authAPI = retrofitFactory.create(client, homeServerUrl) val authAPI = retrofitFactory.create(client, homeServerUrl)
.create(AuthAPI::class.java) .create(AuthAPI::class.java)
val loginParams = PasswordLoginParams.userIdentifier(params.userId, params.password, params.deviceName) val loginParams = PasswordLoginParams.userIdentifier(
user = params.userId,
password = params.password,
deviceDisplayName = params.deviceName,
deviceId = params.deviceId
)
val credentials = try { val credentials = try {
executeRequest(null) { executeRequest(null) {

View File

@ -34,7 +34,7 @@ internal interface SendEventTask : Task<SendEventTask.Params, String> {
internal class DefaultSendEventTask @Inject constructor( internal class DefaultSendEventTask @Inject constructor(
private val localEchoRepository: LocalEchoRepository, private val localEchoRepository: LocalEchoRepository,
private val encryptEventTask: DefaultEncryptEventTask, private val encryptEventTask: EncryptEventTask,
private val loadRoomMembersTask: LoadRoomMembersTask, private val loadRoomMembersTask: LoadRoomMembersTask,
private val roomAPI: RoomAPI, private val roomAPI: RoomAPI,
private val globalErrorReceiver: GlobalErrorReceiver) : SendEventTask { private val globalErrorReceiver: GlobalErrorReceiver) : SendEventTask {

View File

@ -34,7 +34,7 @@ internal interface SendVerificationMessageTask : Task<SendVerificationMessageTas
internal class DefaultSendVerificationMessageTask @Inject constructor( internal class DefaultSendVerificationMessageTask @Inject constructor(
private val localEchoRepository: LocalEchoRepository, private val localEchoRepository: LocalEchoRepository,
private val encryptEventTask: DefaultEncryptEventTask, private val encryptEventTask: EncryptEventTask,
private val roomAPI: RoomAPI, private val roomAPI: RoomAPI,
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
private val globalErrorReceiver: GlobalErrorReceiver) : SendVerificationMessageTask { private val globalErrorReceiver: GlobalErrorReceiver) : SendVerificationMessageTask {

View File

@ -45,17 +45,30 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.util.Normalizer
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
internal object RealmSessionStoreMigration : RealmMigration { internal class RealmSessionStoreMigration @Inject constructor(
private val normalizer: Normalizer
) : RealmMigration {
// SC-specific DB changes on top of Element companion object {
// 1: added markedUnread field // SC-specific DB changes on top of Element
const val SESSION_STORE_SCHEMA_SC_VERSION = 4L // 1: added markedUnread field
const val SESSION_STORE_SCHEMA_SC_VERSION_OFFSET = (1L shl 12) const val SESSION_STORE_SCHEMA_SC_VERSION = 4L
const val SESSION_STORE_SCHEMA_SC_VERSION_OFFSET = (1L shl 12)
const val SESSION_STORE_SCHEMA_VERSION = 18L + const val SESSION_STORE_SCHEMA_VERSION = 19L +
SESSION_STORE_SCHEMA_SC_VERSION * SESSION_STORE_SCHEMA_SC_VERSION_OFFSET SESSION_STORE_SCHEMA_SC_VERSION * SESSION_STORE_SCHEMA_SC_VERSION_OFFSET
}
/**
* Forces all RealmSessionStoreMigration instances to be equal
* Avoids Realm throwing when multiple instances of the migration are set
*/
override fun equals(other: Any?) = other is RealmSessionStoreMigration
override fun hashCode() = 1000
override fun migrate(realm: DynamicRealm, combinedOldVersion: Long, newVersion: Long) { override fun migrate(realm: DynamicRealm, combinedOldVersion: Long, newVersion: Long) {
@ -82,6 +95,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
if (oldVersion <= 15) migrateTo16(realm) if (oldVersion <= 15) migrateTo16(realm)
if (oldVersion <= 16) migrateTo17(realm) if (oldVersion <= 16) migrateTo17(realm)
if (oldVersion <= 17) migrateTo18(realm) if (oldVersion <= 17) migrateTo18(realm)
if (oldVersion <= 18) migrateTo19(realm)
if (oldScVersion <= 0) migrateToSc1(realm) if (oldScVersion <= 0) migrateToSc1(realm)
if (oldScVersion <= 1) migrateToSc2(realm) if (oldScVersion <= 1) migrateToSc2(realm)
@ -410,4 +424,16 @@ internal object RealmSessionStoreMigration : RealmMigration {
realm.schema.get("RoomMemberSummaryEntity") realm.schema.get("RoomMemberSummaryEntity")
?.addRealmObjectField(RoomMemberSummaryEntityFields.USER_PRESENCE_ENTITY.`$`, userPresenceEntity) ?.addRealmObjectField(RoomMemberSummaryEntityFields.USER_PRESENCE_ENTITY.`$`, userPresenceEntity)
} }
private fun migrateTo19(realm: DynamicRealm) {
Timber.d("Step 18 -> 19")
realm.schema.get("RoomSummaryEntity")
?.addField(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, String::class.java)
?.transform {
it.getString(RoomSummaryEntityFields.DISPLAY_NAME)?.let { displayName ->
val normalised = normalizer.normalize(displayName)
it.set(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, normalised)
}
}
}
} }

View File

@ -40,6 +40,7 @@ private const val REALM_NAME = "disk_store.realm"
*/ */
internal class SessionRealmConfigurationFactory @Inject constructor( internal class SessionRealmConfigurationFactory @Inject constructor(
private val realmKeysUtils: RealmKeysUtils, private val realmKeysUtils: RealmKeysUtils,
private val realmSessionStoreMigration: RealmSessionStoreMigration,
@SessionFilesDirectory val directory: File, @SessionFilesDirectory val directory: File,
@SessionId val sessionId: String, @SessionId val sessionId: String,
@UserMd5 val userMd5: String, @UserMd5 val userMd5: String,
@ -71,7 +72,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
.allowWritesOnUiThread(true) .allowWritesOnUiThread(true)
.modules(SessionRealmModule()) .modules(SessionRealmModule())
.schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION) .schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION)
.migration(RealmSessionStoreMigration) .migration(realmSessionStoreMigration)
.build() .build()
// Try creating a realm instance and if it succeeds we can clear the flag // Try creating a realm instance and if it succeeds we can clear the flag

View File

@ -21,13 +21,13 @@ 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.api.session.room.model.SpaceChildInfo
import org.matrix.android.sdk.api.session.room.model.SpaceParentInfo import org.matrix.android.sdk.api.session.room.model.SpaceParentInfo
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
import org.matrix.android.sdk.api.session.typing.TypingUsersTracker
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
import org.matrix.android.sdk.internal.database.model.presence.toUserPresence import org.matrix.android.sdk.internal.database.model.presence.toUserPresence
import org.matrix.android.sdk.internal.session.typing.DefaultTypingUsersTracker
import javax.inject.Inject import javax.inject.Inject
internal class RoomSummaryMapper @Inject constructor(private val timelineEventMapper: TimelineEventMapper, internal class RoomSummaryMapper @Inject constructor(private val timelineEventMapper: TimelineEventMapper,
private val typingUsersTracker: DefaultTypingUsersTracker) { private val typingUsersTracker: TypingUsersTracker) {
fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary { fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary {
val tags = roomSummaryEntity.tags().map { val tags = roomSummaryEntity.tags().map {
@ -48,7 +48,7 @@ internal class RoomSummaryMapper @Inject constructor(private val timelineEventMa
return RoomSummary( return RoomSummary(
roomId = roomSummaryEntity.roomId, roomId = roomSummaryEntity.roomId,
displayName = roomSummaryEntity.displayName ?: "", displayName = roomSummaryEntity.displayName() ?: "",
name = roomSummaryEntity.name ?: "", name = roomSummaryEntity.name ?: "",
topic = roomSummaryEntity.topic ?: "", topic = roomSummaryEntity.topic ?: "",
avatarUrl = roomSummaryEntity.avatarUrl ?: "", avatarUrl = roomSummaryEntity.avatarUrl ?: "",

View File

@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.session.room.model.VersioningState
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntity import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntity
import org.matrix.android.sdk.internal.session.room.membership.RoomName
import timber.log.Timber import timber.log.Timber
internal open class RoomSummaryEntity( internal open class RoomSummaryEntity(
@ -39,10 +40,24 @@ internal open class RoomSummaryEntity(
var children: RealmList<SpaceChildSummaryEntity> = RealmList() var children: RealmList<SpaceChildSummaryEntity> = RealmList()
) : RealmObject() { ) : RealmObject() {
var displayName: String? = "" private var displayName: String? = ""
set(value) {
if (value != field) field = value fun displayName() = displayName
fun setDisplayName(roomName: RoomName) {
if (roomName.name != displayName) {
displayName = roomName.name
normalizedDisplayName = roomName.normalizedName
} }
}
/**
* Workaround for Realm only supporting Latin-1 character sets when sorting
* or filtering by case
* See https://github.com/realm/realm-core/issues/777
*/
private var normalizedDisplayName: String? = ""
var avatarUrl: String? = "" var avatarUrl: String? = ""
set(value) { set(value) {
if (value != field) field = value if (value != field) field = value
@ -344,6 +359,7 @@ internal open class RoomSummaryEntity(
roomEncryptionTrustLevelStr = value?.name roomEncryptionTrustLevelStr = value?.name
} }
} }
companion object companion object

View File

@ -20,6 +20,7 @@ import com.facebook.stetho.okhttp3.StethoInterceptor
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import okhttp3.ConnectionSpec
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.BuildConfig
@ -29,6 +30,7 @@ import org.matrix.android.sdk.internal.network.TimeOutInterceptor
import org.matrix.android.sdk.internal.network.UserAgentInterceptor import org.matrix.android.sdk.internal.network.UserAgentInterceptor
import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor
import org.matrix.android.sdk.internal.network.interceptors.FormattedJsonHttpLogger import org.matrix.android.sdk.internal.network.interceptors.FormattedJsonHttpLogger
import java.util.Collections
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@Module @Module
@ -66,6 +68,8 @@ internal object NetworkModule {
httpLoggingInterceptor: HttpLoggingInterceptor, httpLoggingInterceptor: HttpLoggingInterceptor,
curlLoggingInterceptor: CurlLoggingInterceptor, curlLoggingInterceptor: CurlLoggingInterceptor,
apiInterceptor: ApiInterceptor): OkHttpClient { apiInterceptor: ApiInterceptor): OkHttpClient {
val spec = ConnectionSpec.Builder(matrixConfiguration.connectionSpec).build()
return OkHttpClient.Builder() return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS)
@ -87,6 +91,7 @@ internal object NetworkModule {
proxy(it) proxy(it)
} }
} }
.connectionSpecs(Collections.singletonList(spec))
.build() .build()
} }

View File

@ -177,15 +177,13 @@ internal object CertUtil {
val trustPinned = arrayOf<TrustManager>(PinnedTrustManagerProvider.provide(hsConfig.allowedFingerprints, defaultTrustManager)) val trustPinned = arrayOf<TrustManager>(PinnedTrustManagerProvider.provide(hsConfig.allowedFingerprints, defaultTrustManager))
val sslSocketFactory: SSLSocketFactory val sslSocketFactory = if (hsConfig.forceUsageTlsVersions && !hsConfig.tlsVersions.isNullOrEmpty()) {
if (hsConfig.forceUsageTlsVersions && hsConfig.tlsVersions != null) {
// Force usage of accepted Tls Versions for Android < 20 // Force usage of accepted Tls Versions for Android < 20
sslSocketFactory = TLSSocketFactory(trustPinned, hsConfig.tlsVersions) TLSSocketFactory(trustPinned, hsConfig.tlsVersions)
} else { } else {
val sslContext = SSLContext.getInstance("TLS") val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustPinned, java.security.SecureRandom()) sslContext.init(null, trustPinned, java.security.SecureRandom())
sslSocketFactory = sslContext.socketFactory sslContext.socketFactory
} }
return PinnedSSLSocketFactory(sslSocketFactory, defaultTrustManager!!) return PinnedSSLSocketFactory(sslSocketFactory, defaultTrustManager!!)
@ -237,14 +235,14 @@ internal object CertUtil {
* @return a list of accepted TLS specifications. * @return a list of accepted TLS specifications.
*/ */
fun newConnectionSpecs(hsConfig: HomeServerConnectionConfig): List<ConnectionSpec> { fun newConnectionSpecs(hsConfig: HomeServerConnectionConfig): List<ConnectionSpec> {
val builder = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) val builder = ConnectionSpec.Builder(ConnectionSpec.RESTRICTED_TLS)
val tlsVersions = hsConfig.tlsVersions val tlsVersions = hsConfig.tlsVersions
if (null != tlsVersions && tlsVersions.isNotEmpty()) { if (!tlsVersions.isNullOrEmpty()) {
builder.tlsVersions(*tlsVersions.toTypedArray()) builder.tlsVersions(*tlsVersions.toTypedArray())
} }
val tlsCipherSuites = hsConfig.tlsCipherSuites val tlsCipherSuites = hsConfig.tlsCipherSuites
if (null != tlsCipherSuites && tlsCipherSuites.isNotEmpty()) { if (!tlsCipherSuites.isNullOrEmpty()) {
builder.cipherSuites(*tlsCipherSuites.toTypedArray()) builder.cipherSuites(*tlsCipherSuites.toTypedArray())
} }

View File

@ -20,24 +20,41 @@ import io.realm.Case
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.RealmQuery import io.realm.RealmQuery
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStringValue
import timber.log.Timber import org.matrix.android.sdk.api.query.QueryStringValue.ContentQueryStringValue
import org.matrix.android.sdk.internal.util.Normalizer
import javax.inject.Inject
fun <T : RealmObject> RealmQuery<T>.process(field: String, queryStringValue: QueryStringValue): RealmQuery<T> { class QueryStringValueProcessor @Inject constructor(
when (queryStringValue) { private val normalizer: Normalizer
is QueryStringValue.NoCondition -> Timber.v("No condition to process") ) {
is QueryStringValue.IsNotNull -> isNotNull(field)
is QueryStringValue.IsNull -> isNull(field) fun <T : RealmObject> RealmQuery<T>.process(field: String, queryStringValue: QueryStringValue): RealmQuery<T> {
is QueryStringValue.IsEmpty -> isEmpty(field) return when (queryStringValue) {
is QueryStringValue.IsNotEmpty -> isNotEmpty(field) is QueryStringValue.NoCondition -> this
is QueryStringValue.Equals -> equalTo(field, queryStringValue.string, queryStringValue.case.toRealmCase()) is QueryStringValue.IsNotNull -> isNotNull(field)
is QueryStringValue.Contains -> contains(field, queryStringValue.string, queryStringValue.case.toRealmCase()) is QueryStringValue.IsNull -> isNull(field)
is QueryStringValue.IsEmpty -> isEmpty(field)
is QueryStringValue.IsNotEmpty -> isNotEmpty(field)
is ContentQueryStringValue -> when (queryStringValue) {
is QueryStringValue.Equals -> equalTo(field, queryStringValue.toRealmValue(), queryStringValue.case.toRealmCase())
is QueryStringValue.Contains -> contains(field, queryStringValue.toRealmValue(), queryStringValue.case.toRealmCase())
}
}
}
private fun ContentQueryStringValue.toRealmValue(): String {
return when (case) {
QueryStringValue.Case.NORMALIZED -> normalizer.normalize(string)
QueryStringValue.Case.SENSITIVE,
QueryStringValue.Case.INSENSITIVE -> string
}
} }
return this
} }
private fun QueryStringValue.Case.toRealmCase(): Case { private fun QueryStringValue.Case.toRealmCase(): Case {
return when (this) { return when (this) {
QueryStringValue.Case.INSENSITIVE -> Case.INSENSITIVE QueryStringValue.Case.INSENSITIVE -> Case.INSENSITIVE
QueryStringValue.Case.SENSITIVE -> Case.SENSITIVE QueryStringValue.Case.SENSITIVE,
QueryStringValue.Case.NORMALIZED -> Case.SENSITIVE
} }
} }

View File

@ -41,6 +41,7 @@ import org.matrix.android.sdk.api.session.file.ContentDownloadStateTracker
import org.matrix.android.sdk.api.session.file.FileService import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.group.GroupService import org.matrix.android.sdk.api.session.group.GroupService
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.api.session.identity.IdentityService
import org.matrix.android.sdk.api.session.initsync.SyncStatusService import org.matrix.android.sdk.api.session.initsync.SyncStatusService
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
import org.matrix.android.sdk.api.session.media.MediaService import org.matrix.android.sdk.api.session.media.MediaService
@ -72,7 +73,6 @@ import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.di.WorkManagerProvider
import org.matrix.android.sdk.internal.network.GlobalErrorHandler import org.matrix.android.sdk.internal.network.GlobalErrorHandler
import org.matrix.android.sdk.internal.session.identity.DefaultIdentityService
import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.session.sync.SyncTokenStore
import org.matrix.android.sdk.internal.session.sync.job.SyncThread import org.matrix.android.sdk.internal.session.sync.job.SyncThread
import org.matrix.android.sdk.internal.session.sync.job.SyncWorker import org.matrix.android.sdk.internal.session.sync.job.SyncWorker
@ -124,7 +124,7 @@ internal class DefaultSession @Inject constructor(
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>, private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
private val accountService: Lazy<AccountService>, private val accountService: Lazy<AccountService>,
private val eventService: Lazy<EventService>, private val eventService: Lazy<EventService>,
private val defaultIdentityService: DefaultIdentityService, private val identityService: IdentityService,
private val integrationManagerService: IntegrationManagerService, private val integrationManagerService: IntegrationManagerService,
private val thirdPartyService: Lazy<ThirdPartyService>, private val thirdPartyService: Lazy<ThirdPartyService>,
private val callSignalingService: Lazy<CallSignalingService>, private val callSignalingService: Lazy<CallSignalingService>,
@ -275,7 +275,7 @@ internal class DefaultSession @Inject constructor(
override fun cryptoService(): CryptoService = cryptoService.get() override fun cryptoService(): CryptoService = cryptoService.get()
override fun identityService() = defaultIdentityService override fun identityService() = identityService
override fun fileService(): FileService = defaultFileService.get() override fun fileService(): FileService = defaultFileService.get()

View File

@ -163,6 +163,7 @@ internal abstract class SessionModule {
@JvmStatic @JvmStatic
@Provides @Provides
@SessionFilesDirectory @SessionFilesDirectory
@SessionScope
fun providesFilesDir(@UserMd5 userMd5: String, fun providesFilesDir(@UserMd5 userMd5: String,
@SessionId sessionId: String, @SessionId sessionId: String,
context: Context): File { context: Context): File {

View File

@ -35,12 +35,12 @@ import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.content.ContentUrlResolver import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.internal.di.Authenticated import org.matrix.android.sdk.internal.di.Authenticated
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.ProgressRequestBody import org.matrix.android.sdk.internal.network.ProgressRequestBody
import org.matrix.android.sdk.internal.network.awaitResponse import org.matrix.android.sdk.internal.network.awaitResponse
import org.matrix.android.sdk.internal.network.toFailure import org.matrix.android.sdk.internal.network.toFailure
import org.matrix.android.sdk.internal.session.homeserver.DefaultHomeServerCapabilitiesService
import org.matrix.android.sdk.internal.util.TemporaryFileCreator import org.matrix.android.sdk.internal.util.TemporaryFileCreator
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
@ -50,7 +50,7 @@ import javax.inject.Inject
internal class FileUploader @Inject constructor( internal class FileUploader @Inject constructor(
@Authenticated private val okHttpClient: OkHttpClient, @Authenticated private val okHttpClient: OkHttpClient,
private val globalErrorReceiver: GlobalErrorReceiver, private val globalErrorReceiver: GlobalErrorReceiver,
private val homeServerCapabilitiesService: DefaultHomeServerCapabilitiesService, private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
private val context: Context, private val context: Context,
private val temporaryFileCreator: TemporaryFileCreator, private val temporaryFileCreator: TemporaryFileCreator,
contentUrlResolver: ContentUrlResolver, contentUrlResolver: ContentUrlResolver,

View File

@ -217,8 +217,11 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
.also { filesToDelete.add(it) } .also { filesToDelete.add(it) }
} }
VideoCompressionResult.CompressionNotNeeded, VideoCompressionResult.CompressionNotNeeded,
VideoCompressionResult.CompressionCancelled, VideoCompressionResult.CompressionCancelled -> {
workingFile
}
is VideoCompressionResult.CompressionFailed -> { is VideoCompressionResult.CompressionFailed -> {
Timber.e(videoCompressionResult.failure, "Video compression failed")
workingFile workingFile
} }
} }

View File

@ -44,7 +44,7 @@ internal class VideoCompressor @Inject constructor(
var result: Int = -1 var result: Int = -1
var failure: Throwable? = null var failure: Throwable? = null
Transcoder.into(destinationFile.path) Transcoder.into(destinationFile.path)
.addDataSource(object: FilePathDataSource(videoFile.path) { .addDataSource(object : FilePathDataSource(videoFile.path) {
// https://github.com/natario1/Transcoder/issues/154 // https://github.com/natario1/Transcoder/issues/154
@Suppress("SENSELESS_COMPARISON") // Source is annotated as @NonNull, but can actually be null... @Suppress("SENSELESS_COMPARISON") // Source is annotated as @NonNull, but can actually be null...
override fun isInitialized(): Boolean { override fun isInitialized(): Boolean {

View File

@ -30,12 +30,16 @@ import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity
import org.matrix.android.sdk.internal.database.model.GroupSummaryEntityFields import org.matrix.android.sdk.internal.database.model.GroupSummaryEntityFields
import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.util.fetchCopyMap import org.matrix.android.sdk.internal.util.fetchCopyMap
import javax.inject.Inject import javax.inject.Inject
internal class DefaultGroupService @Inject constructor(@SessionDatabase private val monarchy: Monarchy, internal class DefaultGroupService @Inject constructor(
private val groupFactory: GroupFactory) : GroupService { @SessionDatabase private val monarchy: Monarchy,
private val groupFactory: GroupFactory,
private val queryStringValueProcessor: QueryStringValueProcessor,
) : GroupService {
override fun getGroup(groupId: String): Group? { override fun getGroup(groupId: String): Group? {
return Realm.getInstance(monarchy.realmConfiguration).use { realm -> return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
@ -67,8 +71,10 @@ internal class DefaultGroupService @Inject constructor(@SessionDatabase private
} }
private fun groupSummariesQuery(realm: Realm, queryParams: GroupSummaryQueryParams): RealmQuery<GroupSummaryEntity> { private fun groupSummariesQuery(realm: Realm, queryParams: GroupSummaryQueryParams): RealmQuery<GroupSummaryEntity> {
return GroupSummaryEntity.where(realm) return with(queryStringValueProcessor) {
.process(GroupSummaryEntityFields.DISPLAY_NAME, queryParams.displayName) GroupSummaryEntity.where(realm)
.process(GroupSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships) .process(GroupSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.process(GroupSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
}
} }
} }

View File

@ -80,7 +80,7 @@ internal class DefaultIdentityService @Inject constructor(
private val identityApiProvider: IdentityApiProvider, private val identityApiProvider: IdentityApiProvider,
private val accountDataDataSource: UserAccountDataDataSource, private val accountDataDataSource: UserAccountDataDataSource,
private val homeServerCapabilitiesService: HomeServerCapabilitiesService, private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
private val sign3pidInvitationTask: DefaultSign3pidInvitationTask, private val sign3pidInvitationTask: Sign3pidInvitationTask,
private val sessionParams: SessionParams private val sessionParams: SessionParams
) : IdentityService, SessionLifecycleObserver { ) : IdentityService, SessionLifecycleObserver {

View File

@ -21,6 +21,7 @@ import dagger.Module
import dagger.Provides import dagger.Provides
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.session.identity.IdentityService
import org.matrix.android.sdk.internal.database.RealmKeysUtils import org.matrix.android.sdk.internal.database.RealmKeysUtils
import org.matrix.android.sdk.internal.di.AuthenticatedIdentity import org.matrix.android.sdk.internal.di.AuthenticatedIdentity
import org.matrix.android.sdk.internal.di.IdentityDatabase import org.matrix.android.sdk.internal.di.IdentityDatabase
@ -75,6 +76,9 @@ internal abstract class IdentityModule {
} }
} }
@Binds
abstract fun bindIdentityService(service: DefaultIdentityService): IdentityService
@Binds @Binds
@AuthenticatedIdentity @AuthenticatedIdentity
abstract fun bindAccessTokenProvider(provider: IdentityAccessTokenProvider): AccessTokenProvider abstract fun bindAccessTokenProvider(provider: IdentityAccessTokenProvider): AccessTokenProvider

View File

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.notification
import org.matrix.android.sdk.api.pushrules.rest.PushRule import org.matrix.android.sdk.api.pushrules.rest.PushRule
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.isInvitation
import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.task.Task
@ -48,14 +49,18 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
} }
val newJoinEvents = params.syncResponse.join val newJoinEvents = params.syncResponse.join
.mapNotNull { (key, value) -> .mapNotNull { (key, value) ->
value.timeline?.events?.map { it.copy(roomId = key) } value.timeline?.events?.mapNotNull {
it.takeIf { !it.isInvitation() }?.copy(roomId = key)
}
} }
.flatten() .flatten()
val inviteEvents = params.syncResponse.invite val inviteEvents = params.syncResponse.invite
.mapNotNull { (key, value) -> .mapNotNull { (key, value) ->
value.inviteState?.events?.map { it.copy(roomId = key) } value.inviteState?.events?.map { it.copy(roomId = key) }
} }
.flatten() .flatten()
val allEvents = (newJoinEvents + inviteEvents).filter { event -> val allEvents = (newJoinEvents + inviteEvents).filter { event ->
when (event.type) { when (event.type) {
EventType.MESSAGE, EventType.MESSAGE,

View File

@ -85,12 +85,14 @@ internal class DefaultRoomService @Inject constructor(
return roomSummaryDataSource.getRoomSummary(roomIdOrAlias) return roomSummaryDataSource.getRoomSummary(roomIdOrAlias)
} }
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> { override fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
return roomSummaryDataSource.getRoomSummaries(queryParams) sortOrder: RoomSortOrder): List<RoomSummary> {
return roomSummaryDataSource.getRoomSummaries(queryParams, sortOrder)
} }
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> { override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
return roomSummaryDataSource.getRoomSummariesLive(queryParams) sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getRoomSummariesLive(queryParams, sortOrder)
} }
override fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams, override fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,

View File

@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.session.room.membership.admin.MembershipAdminTask import org.matrix.android.sdk.internal.session.room.membership.admin.MembershipAdminTask
import org.matrix.android.sdk.internal.session.room.membership.joining.InviteTask import org.matrix.android.sdk.internal.session.room.membership.joining.InviteTask
@ -51,7 +52,8 @@ internal class DefaultMembershipService @AssistedInject constructor(
private val leaveRoomTask: LeaveRoomTask, private val leaveRoomTask: LeaveRoomTask,
private val membershipAdminTask: MembershipAdminTask, private val membershipAdminTask: MembershipAdminTask,
@UserId @UserId
private val userId: String private val userId: String,
private val queryStringValueProcessor: QueryStringValueProcessor
) : MembershipService { ) : MembershipService {
@AssistedFactory @AssistedFactory
@ -94,15 +96,17 @@ internal class DefaultMembershipService @AssistedInject constructor(
} }
private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberSummaryEntity> { private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberSummaryEntity> {
return RoomMemberHelper(realm, roomId).queryRoomMembersEvent() return with(queryStringValueProcessor) {
.process(RoomMemberSummaryEntityFields.USER_ID, queryParams.userId) RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
.process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships) .process(RoomMemberSummaryEntityFields.USER_ID, queryParams.userId)
.process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName) .process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
.apply { .process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
if (queryParams.excludeSelf) { .apply {
notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId) if (queryParams.excludeSelf) {
notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
}
} }
} }
} }
override fun getNumberOfJoinedMembers(): Int { override fun getNumberOfJoinedMembers(): Int {

View File

@ -34,6 +34,7 @@ import org.matrix.android.sdk.internal.database.query.getOrNull
import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.displayname.DisplayNameResolver import org.matrix.android.sdk.internal.session.displayname.DisplayNameResolver
import org.matrix.android.sdk.internal.util.Normalizer
import javax.inject.Inject import javax.inject.Inject
/** /**
@ -42,6 +43,7 @@ import javax.inject.Inject
internal class RoomDisplayNameResolver @Inject constructor( internal class RoomDisplayNameResolver @Inject constructor(
matrixConfiguration: MatrixConfiguration, matrixConfiguration: MatrixConfiguration,
private val displayNameResolver: DisplayNameResolver, private val displayNameResolver: DisplayNameResolver,
private val normalizer: Normalizer,
@UserId private val userId: String @UserId private val userId: String
) { ) {
@ -54,7 +56,7 @@ internal class RoomDisplayNameResolver @Inject constructor(
* @param roomId: the roomId to resolve the name of. * @param roomId: the roomId to resolve the name of.
* @return the room display name * @return the room display name
*/ */
fun resolve(realm: Realm, roomId: String): String { fun resolve(realm: Realm, roomId: String): RoomName {
// this algorithm is the one defined in // this algorithm is the one defined in
// https://github.com/matrix-org/matrix-js-sdk/blob/develop/lib/models/room.js#L617 // https://github.com/matrix-org/matrix-js-sdk/blob/develop/lib/models/room.js#L617
// calculateRoomName(room, userId) // calculateRoomName(room, userId)
@ -66,12 +68,12 @@ internal class RoomDisplayNameResolver @Inject constructor(
val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_NAME, stateKey = "")?.root val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_NAME, stateKey = "")?.root
name = ContentMapper.map(roomName?.content).toModel<RoomNameContent>()?.name name = ContentMapper.map(roomName?.content).toModel<RoomNameContent>()?.name
if (!name.isNullOrEmpty()) { if (!name.isNullOrEmpty()) {
return name return name.toRoomName()
} }
val canonicalAlias = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_CANONICAL_ALIAS, stateKey = "")?.root val canonicalAlias = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_CANONICAL_ALIAS, stateKey = "")?.root
name = ContentMapper.map(canonicalAlias?.content).toModel<RoomCanonicalAliasContent>()?.canonicalAlias name = ContentMapper.map(canonicalAlias?.content).toModel<RoomCanonicalAliasContent>()?.canonicalAlias
if (!name.isNullOrEmpty()) { if (!name.isNullOrEmpty()) {
return name return name.toRoomName()
} }
val roomMembers = RoomMemberHelper(realm, roomId) val roomMembers = RoomMemberHelper(realm, roomId)
@ -152,7 +154,7 @@ internal class RoomDisplayNameResolver @Inject constructor(
} }
} }
} }
return name ?: roomId return (name ?: roomId).toRoomName()
} }
/** See [org.matrix.android.sdk.api.session.room.sender.SenderInfo.disambiguatedDisplayName] */ /** See [org.matrix.android.sdk.api.session.room.sender.SenderInfo.disambiguatedDisplayName] */
@ -165,4 +167,8 @@ internal class RoomDisplayNameResolver @Inject constructor(
"${roomMemberSummary.displayName} (${roomMemberSummary.userId})" "${roomMemberSummary.displayName} (${roomMemberSummary.userId})"
} }
} }
private fun String.toRoomName() = RoomName(this, normalizedName = normalizer.normalize(this))
} }
internal data class RoomName(val name: String, val normalizedName: String)

View File

@ -31,11 +31,15 @@ import org.matrix.android.sdk.internal.database.mapper.asDomain
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.query.process
import javax.inject.Inject import javax.inject.Inject
internal class StateEventDataSource @Inject constructor(@SessionDatabase private val monarchy: Monarchy, internal class StateEventDataSource @Inject constructor(
private val realmSessionProvider: RealmSessionProvider) { @SessionDatabase private val monarchy: Monarchy,
private val realmSessionProvider: RealmSessionProvider,
private val queryStringValueProcessor: QueryStringValueProcessor
) {
fun getStateEvent(roomId: String, eventType: String, stateKey: QueryStringValue): Event? { fun getStateEvent(roomId: String, eventType: String, stateKey: QueryStringValue): Event? {
return realmSessionProvider.withRealm { realm -> return realmSessionProvider.withRealm { realm ->
@ -78,13 +82,15 @@ internal class StateEventDataSource @Inject constructor(@SessionDatabase private
eventTypes: Set<String>, eventTypes: Set<String>,
stateKey: QueryStringValue stateKey: QueryStringValue
): RealmQuery<CurrentStateEventEntity> { ): RealmQuery<CurrentStateEventEntity> {
return realm.where<CurrentStateEventEntity>() return with(queryStringValueProcessor) {
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId) realm.where<CurrentStateEventEntity>()
.apply { .equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
if (eventTypes.isNotEmpty()) { .apply {
`in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray()) if (eventTypes.isNotEmpty()) {
`in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray())
}
} }
} .process(CurrentStateEventEntityFields.STATE_KEY, stateKey)
.process(CurrentStateEventEntityFields.STATE_KEY, stateKey) }
} }
} }

View File

@ -26,10 +26,10 @@ import com.zhuinden.monarchy.Monarchy
import de.spiritcroc.matrixsdk.StaticScSdkHelper import de.spiritcroc.matrixsdk.StaticScSdkHelper
import io.realm.Realm import io.realm.Realm
import io.realm.RealmQuery import io.realm.RealmQuery
import io.realm.Sort
import io.realm.kotlin.where import io.realm.kotlin.where
import org.matrix.android.sdk.api.query.ActiveSpaceFilter import org.matrix.android.sdk.api.query.ActiveSpaceFilter
import org.matrix.android.sdk.api.query.RoomCategoryFilter import org.matrix.android.sdk.api.query.RoomCategoryFilter
import org.matrix.android.sdk.api.query.isNormalized
import org.matrix.android.sdk.api.session.room.ResultBoundaries import org.matrix.android.sdk.api.session.room.ResultBoundaries
import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
@ -49,13 +49,17 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
import org.matrix.android.sdk.internal.database.query.findByAlias import org.matrix.android.sdk.internal.database.query.findByAlias
import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.util.fetchCopyMap import org.matrix.android.sdk.internal.util.fetchCopyMap
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase private val monarchy: Monarchy, internal class RoomSummaryDataSource @Inject constructor(
private val roomSummaryMapper: RoomSummaryMapper) { @SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val queryStringValueProcessor: QueryStringValueProcessor
) {
fun getRoomSummary(roomIdOrAlias: String): RoomSummary? { fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {
return monarchy return monarchy
@ -82,25 +86,27 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
} }
} }
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> { fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary> {
return monarchy.fetchAllMappedSync( return monarchy.fetchAllMappedSync(
{ roomSummariesQuery(it, queryParams) }, { roomSummariesQuery(it, queryParams).process(sortOrder) },
{ roomSummaryMapper.map(it) } { roomSummaryMapper.map(it) }
) )
} }
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> { fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges( return monarchy.findAllMappedWithChanges(
{ {
roomSummariesQuery(it, queryParams) roomSummariesQuery(it, queryParams).process(sortOrder)
.sort(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Sort.DESCENDING)
}, },
{ roomSummaryMapper.map(it) } { roomSummaryMapper.map(it) }
) )
} }
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> { fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
return getRoomSummariesLive(queryParams) sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
return getRoomSummariesLive(queryParams, sortOrder)
} }
fun getSpaceSummary(roomIdOrAlias: String): RoomSummary? { fun getSpaceSummary(roomIdOrAlias: String): RoomSummary? {
@ -124,8 +130,9 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
} }
} }
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> { fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
return getRoomSummaries(spaceSummaryQueryParams) sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary> {
return getRoomSummaries(spaceSummaryQueryParams, sortOrder)
} }
fun getRootSpaceSummaries(): List<RoomSummary> { fun getRootSpaceSummaries(): List<RoomSummary> {
@ -269,12 +276,20 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
} }
private fun roomSummariesQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> { private fun roomSummariesQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
val query = RoomSummaryEntity.where(realm) val query = with(queryStringValueProcessor) {
query.process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId) RoomSummaryEntity.where(realm)
query.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName) .process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId)
query.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias) .let {
query.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships) if (queryParams.displayName.isNormalized()) {
query.equalTo(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, false) it.process(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, queryParams.displayName)
} else {
it.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
}
}
.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias)
.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
.equalTo(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, false)
}
queryParams.roomCategoryFilter?.let { queryParams.roomCategoryFilter?.let {
when (it) { when (it) {

View File

@ -66,6 +66,7 @@ import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataD
import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
import org.matrix.android.sdk.internal.session.room.relationship.RoomChildRelationInfo import org.matrix.android.sdk.internal.session.room.relationship.RoomChildRelationInfo
import org.matrix.android.sdk.internal.util.Normalizer
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.min import kotlin.math.min
@ -77,7 +78,8 @@ internal class RoomSummaryUpdater @Inject constructor(
private val roomAvatarResolver: RoomAvatarResolver, private val roomAvatarResolver: RoomAvatarResolver,
private val eventDecryptor: EventDecryptor, private val eventDecryptor: EventDecryptor,
private val crossSigningService: DefaultCrossSigningService, private val crossSigningService: DefaultCrossSigningService,
private val roomAccountDataDataSource: RoomAccountDataDataSource) { private val roomAccountDataDataSource: RoomAccountDataDataSource,
private val normalizer: Normalizer) {
fun update(realm: Realm, fun update(realm: Realm,
roomId: String, roomId: String,
@ -160,7 +162,7 @@ internal class RoomSummaryUpdater @Inject constructor(
(latestPreviewableOriginalContentEvent != null && (latestPreviewableOriginalContentEvent != null &&
!isEventRead(realm.configuration, userId, roomId, latestPreviewableOriginalContentEvent.eventId)) !isEventRead(realm.configuration, userId, roomId, latestPreviewableOriginalContentEvent.eventId))
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(realm, roomId) roomSummaryEntity.setDisplayName(roomDisplayNameResolver.resolve(realm, roomId))
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId) roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId)
roomSummaryEntity.name = ContentMapper.map(lastNameEvent?.content).toModel<RoomNameContent>()?.name roomSummaryEntity.name = ContentMapper.map(lastNameEvent?.content).toModel<RoomNameContent>()?.name
roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel<RoomTopicContent>()?.topic roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel<RoomTopicContent>()?.topic

View File

@ -42,11 +42,12 @@ internal class DefaultSignInAgainTask @Inject constructor(
signOutAPI.loginAgain( signOutAPI.loginAgain(
PasswordLoginParams.userIdentifier( PasswordLoginParams.userIdentifier(
// Reuse the same userId // Reuse the same userId
sessionParams.userId, user = sessionParams.userId,
params.password, password = params.password,
// The spec says the initial device name will be ignored // The spec says the initial device name will be ignored
// https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-login // https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-login
// but https://github.com/matrix-org/synapse/issues/6525 // but https://github.com/matrix-org/synapse/issues/6525
deviceDisplayName = null,
// Reuse the same deviceId // Reuse the same deviceId
deviceId = sessionParams.deviceId deviceId = sessionParams.deviceId
) )

View File

@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.model.GuestAccess 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.Membership
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
@ -94,12 +95,14 @@ internal class DefaultSpaceService @Inject constructor(
return spaceGetter.get(spaceId) return spaceGetter.get(spaceId)
} }
override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> { override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
return roomSummaryDataSource.getSpaceSummariesLive(queryParams) sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getSpaceSummariesLive(queryParams, sortOrder)
} }
override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> { override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams) sortOrder: RoomSortOrder): List<RoomSummary> {
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams, sortOrder)
} }
override fun getRootSpaceSummaries(): List<RoomSummary> { override fun getRootSpaceSummaries(): List<RoomSummary> {

View File

@ -39,8 +39,11 @@ internal class RoomSyncEphemeralTemporaryStoreFile @Inject constructor(
moshi: Moshi moshi: Moshi
) : RoomSyncEphemeralTemporaryStore { ) : RoomSyncEphemeralTemporaryStore {
private val workingDir = File(fileDirectory, "rr") private val workingDir: File by lazy {
.also { it.mkdirs() } File(fileDirectory, "rr").also {
it.mkdirs()
}
}
private val roomSyncEphemeralAdapter = moshi.adapter(RoomSyncEphemeral::class.java) private val roomSyncEphemeralAdapter = moshi.adapter(RoomSyncEphemeral::class.java)

View File

@ -166,7 +166,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
roomSummaryEntity.directUserId = userId roomSummaryEntity.directUserId = userId
// Also update the avatar and displayname, there is a specific treatment for DMs // Also update the avatar and displayname, there is a specific treatment for DMs
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId) roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId)
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(realm, roomId) roomSummaryEntity.setDisplayName(roomDisplayNameResolver.resolve(realm, roomId))
} }
} }
} }
@ -178,7 +178,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
it.directUserId = null it.directUserId = null
// Also update the avatar and displayname, there was a specific treatment for DMs // Also update the avatar and displayname, there was a specific treatment for DMs
it.avatarUrl = roomAvatarResolver.resolve(realm, it.roomId) it.avatarUrl = roomAvatarResolver.resolve(realm, it.roomId)
it.displayName = roomDisplayNameResolver.resolve(realm, it.roomId) it.setDisplayName(roomDisplayNameResolver.resolve(realm, it.roomId))
} }
} }

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