Merge 1.3.7

This commit is contained in:
Benoit Marty 2021-11-04 18:40:51 +01:00
commit ec4923fbc8
428 changed files with 4873 additions and 3826 deletions

View file

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

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)
======================================

View file

@ -17,6 +17,7 @@ buildscript {
// https://developer.android.com/studio/releases/gradle-plugin
classpath libs.gradle.gradlePlugin
classpath libs.gradle.kotlinPlugin
classpath libs.gradle.hiltPlugin
classpath 'com.google.gms:google-services:4.3.10'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
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
def kotlin = "1.5.31"
def kotlinCoroutines = "1.5.2"
def dagger = "2.39.1"
def dagger = "2.40"
def retrofit = "2.9.0"
def arrow = "0.8.2"
def markwon = "4.6.2"
@ -34,7 +34,9 @@ def androidxTest = "1.4.0"
ext.libs = [
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 : [
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
@ -72,7 +74,9 @@ ext.libs = [
],
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 : [
'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>
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.
testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "SDK_VERSION", "\"1.3.6\""
buildConfigField "String", "SDK_VERSION", "\"1.3.7\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
resValue "string", "git_sdk_revision", "\"${gitRevision()}\""
@ -156,7 +156,7 @@ dependencies {
implementation libs.apache.commonsImaging
// 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 'org.robolectric:robolectric:4.6.1'

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.api
import okhttp3.ConnectionSpec
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import java.net.Proxy
@ -44,6 +45,10 @@ data class MatrixConfiguration(
* You can create one using for instance Proxy(proxyType, InetSocketAddress.createUnresolved(hostname, port).
*/
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.
*/

View file

@ -105,9 +105,15 @@ interface AuthenticationService {
/**
* Authenticate with a matrixId and a password
* 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,
matrixId: 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 com.squareup.moshi.JsonClass
import okhttp3.CipherSuite
import okhttp3.ConnectionSpec
import okhttp3.TlsVersion
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder
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
* 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
*
* @param tlsLimitations true to use Tls limitations
* @param enableCompatibilityMode set to true for Android < 20
* @return this builder
*/
@Deprecated("TLS versions and cipher suites are limited by default")
fun withTlsLimitations(tlsLimitations: Boolean, enableCompatibilityMode: Boolean): Builder {
if (tlsLimitations) {
withShouldAcceptTlsExtensions(false)
// Tls versions
addAcceptedTlsVersion(TlsVersion.TLS_1_2)
addAcceptedTlsVersion(TlsVersion.TLS_1_3)
// TlS versions
ConnectionSpec.RESTRICTED_TLS.tlsVersions?.let { this.tlsVersions.addAll(it) }
forceUsageOfTlsVersions(enableCompatibilityMode)
// Cipher suites
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
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)
ConnectionSpec.RESTRICTED_TLS.cipherSuites?.let { this.tlsCipherSuites.addAll(it) }
if (enableCompatibilityMode) {
// 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
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.
@ -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 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
*/
suspend fun login(login: String,
password: String,
deviceName: String): Session
initialDeviceName: String,
deviceId: String? = null): Session
/**
* Exchange a login token to an access token.
@ -49,6 +52,12 @@ interface LoginWizard {
*/
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
* [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.
*/
sealed class QueryStringValue {
object NoCondition : QueryStringValue()
object IsNull : QueryStringValue()
object IsNotNull : QueryStringValue()
object IsEmpty : QueryStringValue()
object IsNotEmpty : QueryStringValue()
data class Equals(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue()
data class Contains(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue()
sealed interface QueryStringValue {
sealed interface ContentQueryStringValue : QueryStringValue {
val string: String
val case: Case
}
object NoCondition : 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 {
/**
* Match query sensitive to case
*/
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()
/**
* Launches infinite periodic background syncs
* This does not work in doze mode :/
* If battery optimization is on it can work in app standby but that's all :/
* Launches infinite self rescheduling background syncs via the WorkManager
*
* 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)

View file

@ -22,6 +22,8 @@ import org.json.JSONObject
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.MatrixError
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.MessageType
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
@ -310,3 +312,6 @@ fun Event.isEdition(): Boolean {
fun Event.getPresenceContent(): 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.
* @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.
* @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

View file

@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.session.space
import android.net.Uri
import androidx.lifecycle.LiveData
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.model.RoomSummary
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.
* @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,
reason: String? = null,

View file

@ -121,6 +121,10 @@ internal interface AuthAPI {
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login")
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.
*/

View file

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

View file

@ -49,51 +49,54 @@ internal data class PasswordLoginParams(
fun userIdentifier(user: String,
password: String,
deviceDisplayName: String? = null,
deviceId: String? = null): PasswordLoginParams {
deviceDisplayName: String?,
deviceId: String?): PasswordLoginParams {
return PasswordLoginParams(
mapOf(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_USER,
IDENTIFIER_KEY_USER to user
),
password,
LoginFlowTypes.PASSWORD,
deviceDisplayName,
deviceId)
password = password,
type = LoginFlowTypes.PASSWORD,
deviceDisplayName = deviceDisplayName,
deviceId = deviceId
)
}
fun thirdPartyIdentifier(medium: String,
address: String,
password: String,
deviceDisplayName: String? = null,
deviceId: String? = null): PasswordLoginParams {
deviceDisplayName: String?,
deviceId: String?): PasswordLoginParams {
return PasswordLoginParams(
mapOf(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_THIRD_PARTY,
IDENTIFIER_KEY_MEDIUM to medium,
IDENTIFIER_KEY_ADDRESS to address
),
password,
LoginFlowTypes.PASSWORD,
deviceDisplayName,
deviceId)
password = password,
type = LoginFlowTypes.PASSWORD,
deviceDisplayName = deviceDisplayName,
deviceId = deviceId
)
}
fun phoneIdentifier(country: String,
phone: String,
password: String,
deviceDisplayName: String? = null,
deviceId: String? = null): PasswordLoginParams {
deviceDisplayName: String?,
deviceId: String?): PasswordLoginParams {
return PasswordLoginParams(
mapOf(
identifier = mapOf(
IDENTIFIER_KEY_TYPE to IDENTIFIER_KEY_TYPE_PHONE,
IDENTIFIER_KEY_COUNTRY to country,
IDENTIFIER_KEY_PHONE to phone
),
password,
LoginFlowTypes.PASSWORD,
deviceDisplayName,
deviceId)
password = password,
type = LoginFlowTypes.PASSWORD,
deviceDisplayName = deviceDisplayName,
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.registration.RegisterThreePid
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.PendingSessionStore
import org.matrix.android.sdk.internal.auth.SessionCreator
@ -52,11 +53,23 @@ internal class DefaultLoginWizard(
override suspend fun login(login: String,
password: String,
deviceName: String): Session {
initialDeviceName: String,
deviceId: String?): Session {
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 {
PasswordLoginParams.userIdentifier(login, password, deviceName)
PasswordLoginParams.userIdentifier(
user = login,
password = password,
deviceDisplayName = initialDeviceName,
deviceId = deviceId
)
}
val credentials = executeRequest(null) {
authAPI.login(loginParams)
@ -79,6 +92,14 @@ internal class DefaultLoginWizard(
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) {
val param = RegisterAddThreePidTask.Params(
RegisterThreePid.Email(email),

View file

@ -37,7 +37,8 @@ internal interface DirectLoginTask : Task<DirectLoginTask.Params, Session> {
val homeServerConnectionConfig: HomeServerConnectionConfig,
val userId: 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)
.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 {
executeRequest(null) {

View file

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

View file

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

View file

@ -45,11 +45,24 @@ 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.di.MoshiProvider
import org.matrix.android.sdk.internal.query.process
import org.matrix.android.sdk.internal.util.Normalizer
import timber.log.Timber
import javax.inject.Inject
internal object RealmSessionStoreMigration : RealmMigration {
internal class RealmSessionStoreMigration @Inject constructor(
private val normalizer: Normalizer
) : RealmMigration {
const val SESSION_STORE_SCHEMA_VERSION = 18L
companion object {
const val SESSION_STORE_SCHEMA_VERSION = 19L
}
/**
* 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, oldVersion: Long, newVersion: Long) {
Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
@ -72,6 +85,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
if (oldVersion <= 15) migrateTo16(realm)
if (oldVersion <= 16) migrateTo17(realm)
if (oldVersion <= 17) migrateTo18(realm)
if (oldVersion <= 18) migrateTo19(realm)
}
private fun migrateTo1(realm: DynamicRealm) {
@ -364,4 +378,16 @@ internal object RealmSessionStoreMigration : RealmMigration {
realm.schema.get("RoomMemberSummaryEntity")
?.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(
private val realmKeysUtils: RealmKeysUtils,
private val realmSessionStoreMigration: RealmSessionStoreMigration,
@SessionFilesDirectory val directory: File,
@SessionId val sessionId: String,
@UserMd5 val userMd5: String,
@ -71,7 +72,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
.allowWritesOnUiThread(true)
.modules(SessionRealmModule())
.schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION)
.migration(RealmSessionStoreMigration)
.migration(realmSessionStoreMigration)
.build()
// 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.SpaceParentInfo
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.presence.toUserPresence
import org.matrix.android.sdk.internal.session.typing.DefaultTypingUsersTracker
import javax.inject.Inject
internal class RoomSummaryMapper @Inject constructor(private val timelineEventMapper: TimelineEventMapper,
private val typingUsersTracker: DefaultTypingUsersTracker) {
private val typingUsersTracker: TypingUsersTracker) {
fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary {
val tags = roomSummaryEntity.tags().map {
@ -42,7 +42,7 @@ internal class RoomSummaryMapper @Inject constructor(private val timelineEventMa
return RoomSummary(
roomId = roomSummaryEntity.roomId,
displayName = roomSummaryEntity.displayName ?: "",
displayName = roomSummaryEntity.displayName() ?: "",
name = roomSummaryEntity.name ?: "",
topic = roomSummaryEntity.topic ?: "",
avatarUrl = roomSummaryEntity.avatarUrl ?: "",

View file

@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary
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.internal.database.model.presence.UserPresenceEntity
import org.matrix.android.sdk.internal.session.room.membership.RoomName
internal open class RoomSummaryEntity(
@PrimaryKey var roomId: String = "",
@ -36,10 +37,24 @@ internal open class RoomSummaryEntity(
var children: RealmList<SpaceChildSummaryEntity> = RealmList()
) : RealmObject() {
var displayName: String? = ""
set(value) {
if (value != field) field = value
private var displayName: String? = ""
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? = ""
set(value) {
if (value != field) field = value
@ -284,5 +299,6 @@ internal open class RoomSummaryEntity(
roomEncryptionTrustLevelStr = value?.name
}
}
companion object
}

View file

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

View file

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

View file

@ -20,24 +20,41 @@ import io.realm.Case
import io.realm.RealmObject
import io.realm.RealmQuery
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> {
when (queryStringValue) {
is QueryStringValue.NoCondition -> Timber.v("No condition to process")
is QueryStringValue.IsNotNull -> isNotNull(field)
is QueryStringValue.IsNull -> isNull(field)
is QueryStringValue.IsEmpty -> isEmpty(field)
is QueryStringValue.IsNotEmpty -> isNotEmpty(field)
is QueryStringValue.Equals -> equalTo(field, queryStringValue.string, queryStringValue.case.toRealmCase())
is QueryStringValue.Contains -> contains(field, queryStringValue.string, queryStringValue.case.toRealmCase())
class QueryStringValueProcessor @Inject constructor(
private val normalizer: Normalizer
) {
fun <T : RealmObject> RealmQuery<T>.process(field: String, queryStringValue: QueryStringValue): RealmQuery<T> {
return when (queryStringValue) {
is QueryStringValue.NoCondition -> this
is QueryStringValue.IsNotNull -> isNotNull(field)
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 {
return when (this) {
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.group.GroupService
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.integrationmanager.IntegrationManagerService
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.WorkManagerProvider
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.job.SyncThread
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 accountService: Lazy<AccountService>,
private val eventService: Lazy<EventService>,
private val defaultIdentityService: DefaultIdentityService,
private val identityService: IdentityService,
private val integrationManagerService: IntegrationManagerService,
private val thirdPartyService: Lazy<ThirdPartyService>,
private val callSignalingService: Lazy<CallSignalingService>,
@ -275,7 +275,7 @@ internal class DefaultSession @Inject constructor(
override fun cryptoService(): CryptoService = cryptoService.get()
override fun identityService() = defaultIdentityService
override fun identityService() = identityService
override fun fileService(): FileService = defaultFileService.get()

View file

@ -163,6 +163,7 @@ internal abstract class SessionModule {
@JvmStatic
@Provides
@SessionFilesDirectory
@SessionScope
fun providesFilesDir(@UserMd5 userMd5: String,
@SessionId sessionId: String,
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.session.content.ContentUrlResolver
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.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.ProgressRequestBody
import org.matrix.android.sdk.internal.network.awaitResponse
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 java.io.File
import java.io.FileNotFoundException
@ -50,7 +50,7 @@ import javax.inject.Inject
internal class FileUploader @Inject constructor(
@Authenticated private val okHttpClient: OkHttpClient,
private val globalErrorReceiver: GlobalErrorReceiver,
private val homeServerCapabilitiesService: DefaultHomeServerCapabilitiesService,
private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
private val context: Context,
private val temporaryFileCreator: TemporaryFileCreator,
contentUrlResolver: ContentUrlResolver,

View file

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

View file

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.content
import com.otaliastudios.transcoder.Transcoder
import com.otaliastudios.transcoder.TranscoderListener
import com.otaliastudios.transcoder.source.FilePathDataSource
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.withContext
@ -43,7 +44,16 @@ internal class VideoCompressor @Inject constructor(
var result: Int = -1
var failure: Throwable? = null
Transcoder.into(destinationFile.path)
.addDataSource(videoFile.path)
.addDataSource(object : FilePathDataSource(videoFile.path) {
// https://github.com/natario1/Transcoder/issues/154
@Suppress("SENSELESS_COMPARISON") // Source is annotated as @NonNull, but can actually be null...
override fun isInitialized(): Boolean {
if (source == null) {
return false
}
return super.isInitialized()
}
})
.setListener(object : TranscoderListener {
override fun onTranscodeProgress(progress: Double) {
Timber.d("Compressing: $progress%")

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.query.where
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.util.fetchCopyMap
import javax.inject.Inject
internal class DefaultGroupService @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val groupFactory: GroupFactory) : GroupService {
internal class DefaultGroupService @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val groupFactory: GroupFactory,
private val queryStringValueProcessor: QueryStringValueProcessor,
) : GroupService {
override fun getGroup(groupId: String): Group? {
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> {
return GroupSummaryEntity.where(realm)
.process(GroupSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.process(GroupSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
return with(queryStringValueProcessor) {
GroupSummaryEntity.where(realm)
.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 accountDataDataSource: UserAccountDataDataSource,
private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
private val sign3pidInvitationTask: DefaultSign3pidInvitationTask,
private val sign3pidInvitationTask: Sign3pidInvitationTask,
private val sessionParams: SessionParams
) : IdentityService, SessionLifecycleObserver {

View file

@ -21,6 +21,7 @@ import dagger.Module
import dagger.Provides
import io.realm.RealmConfiguration
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.di.AuthenticatedIdentity
import org.matrix.android.sdk.internal.di.IdentityDatabase
@ -75,6 +76,9 @@ internal abstract class IdentityModule {
}
}
@Binds
abstract fun bindIdentityService(service: DefaultIdentityService): IdentityService
@Binds
@AuthenticatedIdentity
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.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.internal.di.UserId
import org.matrix.android.sdk.internal.task.Task
@ -48,14 +49,18 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
}
val newJoinEvents = params.syncResponse.join
.mapNotNull { (key, value) ->
value.timeline?.events?.map { it.copy(roomId = key) }
value.timeline?.events?.mapNotNull {
it.takeIf { !it.isInvitation() }?.copy(roomId = key)
}
}
.flatten()
val inviteEvents = params.syncResponse.invite
.mapNotNull { (key, value) ->
value.inviteState?.events?.map { it.copy(roomId = key) }
}
.flatten()
val allEvents = (newJoinEvents + inviteEvents).filter { event ->
when (event.type) {
EventType.MESSAGE,

View file

@ -85,12 +85,14 @@ internal class DefaultRoomService @Inject constructor(
return roomSummaryDataSource.getRoomSummary(roomIdOrAlias)
}
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
return roomSummaryDataSource.getRoomSummaries(queryParams)
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder): List<RoomSummary> {
return roomSummaryDataSource.getRoomSummaries(queryParams, sortOrder)
}
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getRoomSummariesLive(queryParams)
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getRoomSummariesLive(queryParams, sortOrder)
}
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.di.SessionDatabase
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.session.room.membership.admin.MembershipAdminTask
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 membershipAdminTask: MembershipAdminTask,
@UserId
private val userId: String
private val userId: String,
private val queryStringValueProcessor: QueryStringValueProcessor
) : MembershipService {
@AssistedFactory
@ -94,15 +96,17 @@ internal class DefaultMembershipService @AssistedInject constructor(
}
private fun roomMembersQuery(realm: Realm, queryParams: RoomMemberQueryParams): RealmQuery<RoomMemberSummaryEntity> {
return RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
.process(RoomMemberSummaryEntityFields.USER_ID, queryParams.userId)
.process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
.process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.apply {
if (queryParams.excludeSelf) {
notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
return with(queryStringValueProcessor) {
RoomMemberHelper(realm, roomId).queryRoomMembersEvent()
.process(RoomMemberSummaryEntityFields.USER_ID, queryParams.userId)
.process(RoomMemberSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
.process(RoomMemberSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
.apply {
if (queryParams.excludeSelf) {
notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
}
}
}
}
}
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.di.UserId
import org.matrix.android.sdk.internal.session.displayname.DisplayNameResolver
import org.matrix.android.sdk.internal.util.Normalizer
import javax.inject.Inject
/**
@ -42,6 +43,7 @@ import javax.inject.Inject
internal class RoomDisplayNameResolver @Inject constructor(
matrixConfiguration: MatrixConfiguration,
private val displayNameResolver: DisplayNameResolver,
private val normalizer: Normalizer,
@UserId private val userId: String
) {
@ -54,7 +56,7 @@ internal class RoomDisplayNameResolver @Inject constructor(
* @param roomId: the roomId to resolve the name of.
* @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
// https://github.com/matrix-org/matrix-js-sdk/blob/develop/lib/models/room.js#L617
// 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
name = ContentMapper.map(roomName?.content).toModel<RoomNameContent>()?.name
if (!name.isNullOrEmpty()) {
return name
return name.toRoomName()
}
val canonicalAlias = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_CANONICAL_ALIAS, stateKey = "")?.root
name = ContentMapper.map(canonicalAlias?.content).toModel<RoomCanonicalAliasContent>()?.canonicalAlias
if (!name.isNullOrEmpty()) {
return name
return name.toRoomName()
}
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] */
@ -165,4 +167,8 @@ internal class RoomDisplayNameResolver @Inject constructor(
"${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.CurrentStateEventEntityFields
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 javax.inject.Inject
internal class StateEventDataSource @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val realmSessionProvider: RealmSessionProvider) {
internal class StateEventDataSource @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val realmSessionProvider: RealmSessionProvider,
private val queryStringValueProcessor: QueryStringValueProcessor
) {
fun getStateEvent(roomId: String, eventType: String, stateKey: QueryStringValue): Event? {
return realmSessionProvider.withRealm { realm ->
@ -78,13 +82,15 @@ internal class StateEventDataSource @Inject constructor(@SessionDatabase private
eventTypes: Set<String>,
stateKey: QueryStringValue
): RealmQuery<CurrentStateEventEntity> {
return realm.where<CurrentStateEventEntity>()
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.apply {
if (eventTypes.isNotEmpty()) {
`in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray())
return with(queryStringValueProcessor) {
realm.where<CurrentStateEventEntity>()
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.apply {
if (eventTypes.isNotEmpty()) {
`in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray())
}
}
}
.process(CurrentStateEventEntityFields.STATE_KEY, stateKey)
.process(CurrentStateEventEntityFields.STATE_KEY, stateKey)
}
}
}

View file

@ -25,10 +25,10 @@ import androidx.paging.PagedList
import com.zhuinden.monarchy.Monarchy
import io.realm.Realm
import io.realm.RealmQuery
import io.realm.Sort
import io.realm.kotlin.where
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
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.RoomSortOrder
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
@ -48,12 +48,16 @@ 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.where
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.util.fetchCopyMap
import javax.inject.Inject
internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper) {
internal class RoomSummaryDataSource @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val queryStringValueProcessor: QueryStringValueProcessor
) {
fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {
return monarchy
@ -80,25 +84,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(
{ roomSummariesQuery(it, queryParams) },
{ roomSummariesQuery(it, queryParams).process(sortOrder) },
{ roomSummaryMapper.map(it) }
)
}
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{
roomSummariesQuery(it, queryParams)
.sort(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Sort.DESCENDING)
roomSummariesQuery(it, queryParams).process(sortOrder)
},
{ roomSummaryMapper.map(it) }
)
}
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> {
return getRoomSummariesLive(queryParams)
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
return getRoomSummariesLive(queryParams, sortOrder)
}
fun getSpaceSummary(roomIdOrAlias: String): RoomSummary? {
@ -122,8 +128,9 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
}
}
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> {
return getRoomSummaries(spaceSummaryQueryParams)
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary> {
return getRoomSummaries(spaceSummaryQueryParams, sortOrder)
}
fun getRootSpaceSummaries(): List<RoomSummary> {
@ -238,12 +245,20 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
}
private fun roomSummariesQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
val query = RoomSummaryEntity.where(realm)
query.process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId)
query.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
query.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias)
query.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
query.equalTo(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, false)
val query = with(queryStringValueProcessor) {
RoomSummaryEntity.where(realm)
.process(RoomSummaryEntityFields.ROOM_ID, queryParams.roomId)
.let {
if (queryParams.displayName.isNormalized()) {
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 {
when (it) {

View file

@ -65,6 +65,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.RoomMemberHelper
import org.matrix.android.sdk.internal.session.room.relationship.RoomChildRelationInfo
import org.matrix.android.sdk.internal.util.Normalizer
import timber.log.Timber
import javax.inject.Inject
import kotlin.system.measureTimeMillis
@ -75,7 +76,8 @@ internal class RoomSummaryUpdater @Inject constructor(
private val roomAvatarResolver: RoomAvatarResolver,
private val eventDecryptor: EventDecryptor,
private val crossSigningService: DefaultCrossSigningService,
private val roomAccountDataDataSource: RoomAccountDataDataSource) {
private val roomAccountDataDataSource: RoomAccountDataDataSource,
private val normalizer: Normalizer) {
fun update(realm: Realm,
roomId: String,
@ -136,7 +138,7 @@ internal class RoomSummaryUpdater @Inject constructor(
// avoid this call if we are sure there are unread events
!isEventRead(realm.configuration, userId, roomId, latestPreviewableEvent?.eventId)
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(realm, roomId)
roomSummaryEntity.setDisplayName(roomDisplayNameResolver.resolve(realm, roomId))
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId)
roomSummaryEntity.name = ContentMapper.map(lastNameEvent?.content).toModel<RoomNameContent>()?.name
roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel<RoomTopicContent>()?.topic

View file

@ -42,11 +42,12 @@ internal class DefaultSignInAgainTask @Inject constructor(
signOutAPI.loginAgain(
PasswordLoginParams.userIdentifier(
// Reuse the same userId
sessionParams.userId,
params.password,
user = sessionParams.userId,
password = params.password,
// The spec says the initial device name will be ignored
// https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-login
// but https://github.com/matrix-org/synapse/issues/6525
deviceDisplayName = null,
// Reuse the same 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.toContent
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.Membership
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
@ -94,12 +95,14 @@ internal class DefaultSpaceService @Inject constructor(
return spaceGetter.get(spaceId)
}
override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getSpaceSummariesLive(queryParams)
override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
return roomSummaryDataSource.getSpaceSummariesLive(queryParams, sortOrder)
}
override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> {
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams)
override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
sortOrder: RoomSortOrder): List<RoomSummary> {
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams, sortOrder)
}
override fun getRootSpaceSummaries(): List<RoomSummary> {

View file

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

View file

@ -166,7 +166,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
roomSummaryEntity.directUserId = userId
// Also update the avatar and displayname, there is a specific treatment for DMs
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
// Also update the avatar and displayname, there was a specific treatment for DMs
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