Merge remote-tracking branch 'origin/develop' into task/eric/replace_flatten_with_direct_parent

This commit is contained in:
ericdecanini 2022-07-01 15:47:30 +01:00
commit b437996208
349 changed files with 2484 additions and 886 deletions

View file

@ -100,12 +100,20 @@ body:
##### Release on MavenCentral
- [ ] Checkout the branch `main`
- [ ] Run the command `./gradlew publish --no-daemon --no-parallel`. You'll need some non-public element to do so
- [ ] Run the command `./gradlew closeAndReleaseRepository`. If it is working well, you can jump directly to the final step of this section.
If `./gradlew closeAndReleaseRepository` fails (for instance, several repositories are waiting to be handled), you have to close and release the repository manually. Do the following steps:
- [ ] Connect to https://s01.oss.sonatype.org
- [ ] Click on Staging Repositories and check the the files have been uploaded
- [ ] Click on close
- [ ] Wait (check Activity tab until step "Repository closed" is displayed)
- [ ] Click on release. The staging repository will disappear
Final step
- [ ] Check that the release is available in https://repo1.maven.org/maven2/org/matrix/android/matrix-android-sdk2/ (it can take a few minutes)
##### Release on GitHub

View file

@ -1,3 +1,59 @@
Changes in Element v1.4.26 (2022-06-30)
=======================================
Features ✨
----------
- Use UnifiedPush and allows user to have push without FCM. ([#3448](https://github.com/vector-im/element-android/issues/3448))
- Replace ffmpeg-kit with libopus and libopusenc. ([#6203](https://github.com/vector-im/element-android/issues/6203))
- Improve lock screen implementation. ([#6217](https://github.com/vector-im/element-android/issues/6217))
- Allow sharing text based content via android's share menu (eg .ics files) ([#6285](https://github.com/vector-im/element-android/issues/6285))
- Promote live location labs flag ([#6350](https://github.com/vector-im/element-android/issues/6350))
- [Location sharing] - Stop any active live before starting a new one ([#6364](https://github.com/vector-im/element-android/issues/6364))
- Expose pusher profile tag in advanced settings ([#6369](https://github.com/vector-im/element-android/issues/6369))
Bugfixes 🐛
----------
- Fixes concurrent modification crash when signing out or launching the app ([#5821](https://github.com/vector-im/element-android/issues/5821))
- Refactor - better naming, return native user id and not sip user id and create a dm with the native user instead of with the sip user. ([#6101](https://github.com/vector-im/element-android/issues/6101))
- Fixed /upgraderoom command not doing anything ([#6154](https://github.com/vector-im/element-android/issues/6154))
- Fixed crash when opening large images in the timeline ([#6290](https://github.com/vector-im/element-android/issues/6290))
- [Location sharing] Fix crash when starting/stopping a live when offline ([#6315](https://github.com/vector-im/element-android/issues/6315))
- Fix loop in timeline and simplify management of chunks and timeline events. ([#6318](https://github.com/vector-im/element-android/issues/6318))
- Update design and behaviour on widget permission bottom sheet ([#6326](https://github.com/vector-im/element-android/issues/6326))
- Fix | Some user verification requests couldn't be accepted/declined ([#6328](https://github.com/vector-im/element-android/issues/6328))
- [Location sharing] Fix stop of a live not possible from another device ([#6349](https://github.com/vector-im/element-android/issues/6349))
- Fix backslash escapes in formatted messages ([#6357](https://github.com/vector-im/element-android/issues/6357))
- Fixes wrong error message when signing in with wrong credentials ([#6371](https://github.com/vector-im/element-android/issues/6371))
- [Location Share] - Adding missing prefix "u=" for uncertainty in geo URI ([#6375](https://github.com/vector-im/element-android/issues/6375))
In development 🚧
----------------
- FTUE - Adds automatic homeserver selection when typing a full matrix id during registration or login ([#6162](https://github.com/vector-im/element-android/issues/6162))
Improved Documentation 📚
------------------------
- Update the PR process doc to come back to one reviewer with optional additional reviewers. ([#6396](https://github.com/vector-im/element-android/issues/6396))
SDK API changes ⚠️
------------------
- Group all location sharing related API into LocationSharingService ([#5864](https://github.com/vector-im/element-android/issues/5864))
- Add support for MSC2457 - opting in or out of logging out all devices when changing password ([#6191](https://github.com/vector-im/element-android/issues/6191))
- Create `QueryStateEventValue` to do query on `stateKey` for State Event. Also remove the default parameter values for those type. ([#6319](https://github.com/vector-im/element-android/issues/6319))
Other changes
-------------
- - Notify of the latest known location in LocationTracker to avoid multiple locations at start
- Debounce location updates
- Improve location providers access ([#5913](https://github.com/vector-im/element-android/issues/5913))
- Add unit tests for LiveLocationAggregationProcessor code ([#6155](https://github.com/vector-im/element-android/issues/6155))
- Making screenshots in bug reports opt in instead of opt out ([#6261](https://github.com/vector-im/element-android/issues/6261))
- Setup [Flipper](https://fbflipper.com/) ([#6300](https://github.com/vector-im/element-android/issues/6300))
- CreatePollViewModel unit tests ([#6320](https://github.com/vector-im/element-android/issues/6320))
- Fix flaky test in voice recording feature. ([#6329](https://github.com/vector-im/element-android/issues/6329))
- Poll view state unit tests ([#6366](https://github.com/vector-im/element-android/issues/6366))
- Let LoadRoomMembersTask insert by chunk to release db. ([#6394](https://github.com/vector-im/element-android/issues/6394))
Changes in Element v1.4.25 (2022-06-27)
=======================================

View file

@ -1 +0,0 @@
Use UnifiedPush and allows user to have push without FCM.

1
changelog.d/5284.wip Normal file
View file

@ -0,0 +1 @@
FTUE - Adds support for resetting the password during the FTUE onboarding journey

View file

@ -1 +0,0 @@
Fixes concurrent modification crash when signing out or launching the app

View file

@ -1 +0,0 @@
Group all location sharing related API into LocationSharingService

View file

@ -1,3 +0,0 @@
- Notify of the latest known location in LocationTracker to avoid multiple locations at start
- Debounce location updates
- Improve location providers access

View file

@ -1 +0,0 @@
Refactor - better naming, return native user id and not sip user id and create a dm with the native user instead of with the sip user.

View file

@ -1 +0,0 @@
Fixed /upgraderoom command not doing anything

View file

@ -1 +0,0 @@
Add unit tests for LiveLocationAggregationProcessor code

View file

@ -1 +0,0 @@
FTUE - Adds automatic homeserver selection when typing a full matrix id during registration or login

View file

@ -1 +0,0 @@
Add support for MSC2457 - opting in or out of logging out all devices when changing password

View file

@ -1 +0,0 @@
Replace ffmpeg-kit with libopus and libopusenc.

View file

@ -1 +0,0 @@
Improve lock screen implementation.

View file

@ -1 +0,0 @@
Making screenshots in bug reports opt in instead of opt out

View file

@ -1 +0,0 @@
Allow sharing text based content via android's share menu (eg .ics files)

1
changelog.d/6288.bugfix Normal file
View file

@ -0,0 +1 @@
Use stable endpoint for alias management instead of MSC2432. Contributed by Nico.

View file

@ -1 +0,0 @@
Fixed crash when opening large images in the timeline

View file

@ -1 +0,0 @@
Setup [Flipper](https://fbflipper.com/)

View file

@ -1 +0,0 @@
[Location sharing] Fix crash when starting/stopping a live when offline

View file

@ -1 +0,0 @@
Fix loop in timeline and simplify management of chunks and timeline events.

View file

@ -1 +0,0 @@
Create `QueryStateEventValue` to do query on `stateKey` for State Event. Also remove the default parameter values for those type.

View file

@ -1 +0,0 @@
CreatePollViewModel unit tests

View file

@ -1 +0,0 @@
Update design and behaviour on widget permission bottom sheet

View file

@ -1 +0,0 @@
Fix | Some user verification requests couldn't be accepted/declined

View file

@ -1 +0,0 @@
Fix flaky test in voice recording feature.

View file

@ -1 +0,0 @@
[Location sharing] Fix stop of a live not possible from another device

View file

@ -1 +0,0 @@
Promote live location labs flag

View file

@ -1 +0,0 @@
Fix backslash escapes in formatted messages

View file

@ -1 +0,0 @@
[Location sharing] - Stop any active live before starting a new one

View file

@ -1 +0,0 @@
Poll view state unit tests

View file

@ -1,2 +0,0 @@
Expose pusher profile tag in advanced settings

View file

@ -1 +0,0 @@
Fixes wrong error message when signing in with wrong credentials

View file

@ -1 +0,0 @@
[Location Share] - Adding missing prefix "u=" for uncertainty in geo URI

1
changelog.d/6389.misc Normal file
View file

@ -0,0 +1 @@
Replacing Epoxy annotation layout id references with getDefaultLayoutId

1
changelog.d/6392.misc Normal file
View file

@ -0,0 +1 @@
Ensure `RealmList<T>.clearWith()` extension is correctly used.

View file

@ -1 +0,0 @@
Update the PR process doc to come back to one reviewer with optional additional reviewers.

1
changelog.d/6401.feature Normal file
View file

@ -0,0 +1 @@
[Location sharing] - Reply action on a live message

1
changelog.d/6413.feature Normal file
View file

@ -0,0 +1 @@
Show a loader if all the Room Members are not yet loaded.

1
changelog.d/6429.misc Normal file
View file

@ -0,0 +1 @@
Add `android:hasFragileUserData="true"` in the manifest

View file

@ -21,7 +21,7 @@ def markwon = "4.6.2"
def moshi = "1.13.0"
def lifecycle = "2.4.1"
def flowBinding = "1.2.0"
def flipper = "0.151.1"
def flipper = "0.152.0"
def epoxy = "4.6.2"
def mavericks = "2.7.0"
def glide = "4.13.2"

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability.
Úplný seznam změn: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Main changes in this version: Use UnifiedPush and allows user to have push without FCM.
Full changelog: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Põhilised muutused selles versioonis: erinevate vigade parandused ja stabiilsust edendavad kohendused.
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases

View file

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

View file

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

View file

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

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Plusieurs corrections de bogues et daméliorations de stabilité.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Plusieurs corrections de bogues et daméliorations de stabilité.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principaux changements pour cette version : Plusieurs corrections de bogues et daméliorations de stabilité.
Intégralité des changements : https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas.
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas.
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas.
Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità.
Cronologia completa: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità.
Cronologia completa: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità.
Cronologia completa: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade.
Changelog completo: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade.
Changelog completo: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade.
Changelog completo: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability.
Úplný zoznam zmien: https://github.com/vector-im/element-android/releases

View file

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

View file

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

View file

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

View file

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

View file

@ -1,2 +1,2 @@
Основні зміни в цій версії: Хронологія тредів працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
Основні зміни в цій версії: Хронологія гілок працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.4.6

View file

@ -1,2 +1,2 @@
Основні зміни в цій версії: Хронологія тредів працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
Основні зміни в цій версії: Хронологія гілок працює наживо і швидше. Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність.
Вичерпний перелік змін: https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:多個臭蟲修復與穩定性改善。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:多個臭蟲修復與穩定性改善。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -0,0 +1,2 @@
此版本中的主要變動:多個臭蟲修復與穩定性改善。
完整的變更紀錄https://github.com/vector-im/element-android/releases

View file

@ -2,7 +2,6 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.jakewharton.butterknife'
buildscript {
repositories {
@ -15,9 +14,6 @@ buildscript {
url 'https://repo1.maven.org/maven2'
}
}
dependencies {
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
}
}
android {

View file

@ -29,7 +29,7 @@ import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
@EpoxyModelClass(layout = R2.layout.item_jv_base_value)
@EpoxyModelClass
internal abstract class ValueItem : EpoxyModelWithHolder<ValueItem.Holder>() {
@EpoxyAttribute
@ -44,6 +44,8 @@ internal abstract class ValueItem : EpoxyModelWithHolder<ValueItem.Holder>() {
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var itemClickListener: View.OnClickListener? = null
override fun getDefaultLayout() = R.layout.item_jv_base_value
override fun bind(holder: Holder) {
super.bind(holder)
holder.textView.text = text?.charSequence

View file

@ -53,6 +53,13 @@ class FlowRoom(private val room: Room) {
}
}
fun liveAreAllMembersLoaded(): Flow<Boolean> {
return room.membershipService().areAllMembersLoadedLive().asFlow()
.startWith(room.coroutineDispatchers.io) {
room.membershipService().areAllMembersLoaded()
}
}
fun liveAnnotationSummary(eventId: String): Flow<Optional<EventAnnotationsSummary>> {
return room.relationService().getEventAnnotationsSummaryLive(eventId).asFlow()
.startWith(room.coroutineDispatchers.io) {

View file

@ -17,7 +17,7 @@ buildscript {
}
}
dependencies {
classpath "io.realm:realm-gradle-plugin:10.9.0"
classpath "io.realm:realm-gradle-plugin:10.11.0"
}
}
@ -60,7 +60,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "SDK_VERSION", "\"1.4.26\""
buildConfigField "String", "SDK_VERSION", "\"1.4.28\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
@ -199,7 +199,7 @@ dependencies {
implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.50'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.51'
testImplementation libs.tests.junit
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281

View file

@ -162,7 +162,7 @@ enum class ApiPath(val path: String, val method: String) {
KICK_USER(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/kick", "POST"),
REDACT_EVENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/redact/{eventId}/{txnId}", "PUT"),
REPORT_CONTENT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/report/{eventId}", "POST"),
GET_ALIASES(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "org.matrix.msc2432/rooms/{roomId}/aliases", "GET"),
GET_ALIASES(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/aliases", "GET"),
SEND_TYPING_STATE(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/typing/{userId}", "PUT"),
PUT_TAG(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/rooms/{roomId}/tags/{tag}", "PUT"),
DELETE_TAG(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/rooms/{roomId}/tags/{tag}", "DELETE"),

View file

@ -48,9 +48,10 @@ interface LocationSharingService {
/**
* Starts sharing live location in the room.
* @param timeoutMillis timeout of the live in milliseconds
* @param description description of the live for text fallback
* @return the result of the update of the live
*/
suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult
suspend fun startLiveLocationShare(timeoutMillis: Long, description: String): UpdateLiveLocationShareResult
/**
* Stops sharing live location in the room.

View file

@ -30,6 +30,20 @@ interface MembershipService {
*/
suspend fun loadRoomMembersIfNeeded()
/**
* All the room members can be not loaded, for instance after an initial sync.
* All the members will be loaded when calling [loadRoomMembersIfNeeded], or when sending an encrypted
* event to the room.
* The fun let the app know if all the members have been loaded for this room.
* @return true if all the members are loaded, or false elsewhere.
*/
suspend fun areAllMembersLoaded(): Boolean
/**
* Live version for [areAllMembersLoaded].
*/
fun areAllMembersLoadedLive(): LiveData<Boolean>
/**
* Return the roomMember with userId or null.
* @param userId the userId param to look for

View file

@ -20,6 +20,7 @@ import io.realm.RealmList
import io.realm.RealmObject
import io.realm.RealmObjectSchema
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
import org.matrix.android.sdk.internal.util.fatalError
internal fun RealmObject.assertIsManaged() {
check(isManaged) { "${javaClass.simpleName} entity should be managed to use this function" }
@ -27,10 +28,19 @@ internal fun RealmObject.assertIsManaged() {
/**
* Clear a RealmList by deleting all its items calling the provided lambda.
* The lambda is supposed to delete the item, which means that after this operation, the list will be empty.
*/
internal fun <T> RealmList<T>.clearWith(delete: (T) -> Unit) {
while (!isEmpty()) {
first()?.let { delete.invoke(it) }
map { item ->
// Create a lambda for all items of the list
{ delete(item) }
}.forEach { lambda ->
// Then invoke all the lambda
lambda.invoke()
}
if (isNotEmpty()) {
fatalError("`clearWith` MUST delete all elements of the RealmList")
}
}

View file

@ -377,7 +377,7 @@ internal interface RoomAPI {
* Get a list of aliases maintained by the local server for the given room.
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-aliases
*/
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "org.matrix.msc2432/rooms/{roomId}/aliases")
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/aliases")
suspend fun getAliases(@Path("roomId") roomId: String): GetAliasesResponse
/**

View file

@ -0,0 +1,55 @@
/*
* Copyright 2022 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.session.room
import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy
import io.realm.Realm
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.internal.database.model.RoomEntity
import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType
import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase
import javax.inject.Inject
internal class RoomDataSource @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
) {
fun getRoomMembersLoadStatus(roomId: String): RoomMembersLoadStatusType {
var result: RoomMembersLoadStatusType?
Realm.getInstance(monarchy.realmConfiguration).use {
result = RoomEntity.where(it, roomId).findFirst()?.membersLoadStatus
}
return result ?: RoomMembersLoadStatusType.NONE
}
fun getRoomMembersLoadStatusLive(roomId: String): LiveData<Boolean> {
val liveData = monarchy.findAllMappedWithChanges(
{
RoomEntity.where(it, roomId)
},
{
it.membersLoadStatus == RoomMembersLoadStatusType.LOADED
}
)
return Transformations.map(liveData) { results ->
results.firstOrNull().orFalse()
}
}
}

View file

@ -34,7 +34,6 @@ internal class DefaultGetRoomLocalAliasesTask @Inject constructor(
) : GetRoomLocalAliasesTask {
override suspend fun execute(params: GetRoomLocalAliasesTask.Params): List<String> {
// We do not check for "org.matrix.msc2432", so the API may be missing
val response = executeRequest(globalErrorReceiver) {
roomAPI.getAliases(roomId = params.roomId)
}

View file

@ -72,7 +72,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
return sendLiveLocationTask.execute(params)
}
override suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult {
override suspend fun startLiveLocationShare(timeoutMillis: Long, description: String): UpdateLiveLocationShareResult {
// Ensure to stop any active live before starting a new one
if (checkIfExistingActiveLive()) {
val result = stopLiveLocationShare()
@ -82,7 +82,8 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
}
val params = StartLiveLocationShareTask.Params(
roomId = roomId,
timeoutMillis = timeoutMillis
timeoutMillis = timeoutMillis,
description = description
)
return startLiveLocationShareTask.execute(params)
}

View file

@ -30,6 +30,7 @@ internal interface StartLiveLocationShareTask : Task<StartLiveLocationShareTask.
data class Params(
val roomId: String,
val timeoutMillis: Long,
val description: String,
)
}
@ -41,6 +42,7 @@ internal class DefaultStartLiveLocationShareTask @Inject constructor(
override suspend fun execute(params: StartLiveLocationShareTask.Params): UpdateLiveLocationShareResult {
val beaconContent = MessageBeaconInfoContent(
body = params.description,
timeout = params.timeoutMillis,
isLive = true,
unstableTimestampMillis = clock.epochMillis()

View file

@ -31,10 +31,12 @@ import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
import org.matrix.android.sdk.internal.database.mapper.asDomain
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.RoomMembersLoadStatusType
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.RoomDataSource
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.threepid.InviteThreePidTask
@ -47,6 +49,7 @@ internal class DefaultMembershipService @AssistedInject constructor(
private val inviteTask: InviteTask,
private val inviteThreePidTask: InviteThreePidTask,
private val membershipAdminTask: MembershipAdminTask,
private val roomDataSource: RoomDataSource,
@UserId
private val userId: String,
private val queryStringValueProcessor: QueryStringValueProcessor
@ -58,10 +61,19 @@ internal class DefaultMembershipService @AssistedInject constructor(
}
override suspend fun loadRoomMembersIfNeeded() {
val params = LoadRoomMembersTask.Params(roomId, Membership.LEAVE)
val params = LoadRoomMembersTask.Params(roomId, excludeMembership = Membership.LEAVE)
loadRoomMembersTask.execute(params)
}
override suspend fun areAllMembersLoaded(): Boolean {
val status = roomDataSource.getRoomMembersLoadStatus(roomId)
return status == RoomMembersLoadStatusType.LOADED
}
override fun areAllMembersLoadedLive(): LiveData<Boolean> {
return roomDataSource.getRoomMembersLoadStatusLive(roomId)
}
override fun getRoomMember(userId: String): RoomMemberSummary? {
val roomMemberEntity = monarchy.fetchCopied {
RoomMemberHelper(it, roomId).getLastRoomMember(userId)

View file

@ -17,7 +17,6 @@
package org.matrix.android.sdk.internal.session.room.membership
import com.zhuinden.monarchy.Monarchy
import io.realm.Realm
import io.realm.kotlin.createObject
import kotlinx.coroutines.TimeoutCancellationException
import org.matrix.android.sdk.api.session.room.model.Membership
@ -38,11 +37,13 @@ import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.room.RoomAPI
import org.matrix.android.sdk.internal.session.room.RoomDataSource
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater
import org.matrix.android.sdk.internal.session.sync.SyncTokenStore
import org.matrix.android.sdk.internal.task.Task
import org.matrix.android.sdk.internal.util.awaitTransaction
import org.matrix.android.sdk.internal.util.time.Clock
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -57,6 +58,7 @@ internal interface LoadRoomMembersTask : Task<LoadRoomMembersTask.Params, Unit>
internal class DefaultLoadRoomMembersTask @Inject constructor(
private val roomAPI: RoomAPI,
@SessionDatabase private val monarchy: Monarchy,
private val roomDataSource: RoomDataSource,
private val syncTokenStore: SyncTokenStore,
private val roomSummaryUpdater: RoomSummaryUpdater,
private val roomMemberEventHandler: RoomMemberEventHandler,
@ -67,7 +69,7 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(
) : LoadRoomMembersTask {
override suspend fun execute(params: LoadRoomMembersTask.Params) {
when (getRoomMembersLoadStatus(params.roomId)) {
when (roomDataSource.getRoomMembersLoadStatus(params.roomId)) {
RoomMembersLoadStatusType.NONE -> doRequest(params)
RoomMembersLoadStatusType.LOADING -> waitPreviousRequestToFinish(params)
RoomMembersLoadStatusType.LOADED -> Unit
@ -105,45 +107,42 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(
}
private suspend fun insertInDb(response: RoomMembersResponse, roomId: String) {
val chunks = response.roomMemberEvents.chunked(500)
chunks.forEach { roomMemberEvents ->
monarchy.awaitTransaction { realm ->
Timber.v("Insert ${roomMemberEvents.size} member events in room $roomId")
// We ignore all the already known members
val now = clock.epochMillis()
for (roomMemberEvent in roomMemberEvents) {
if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null || roomMemberEvent.type == null) {
continue
}
val ageLocalTs = now - (roomMemberEvent.unsignedData?.age ?: 0)
val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION)
CurrentStateEventEntity.getOrCreate(
realm,
roomId,
roomMemberEvent.stateKey,
roomMemberEvent.type
).apply {
eventId = roomMemberEvent.eventId
root = eventEntity
}
roomMemberEventHandler.handle(realm, roomId, roomMemberEvent, false)
}
}
}
monarchy.awaitTransaction { realm ->
// We ignore all the already known members
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)
val now = clock.epochMillis()
for (roomMemberEvent in response.roomMemberEvents) {
if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null || roomMemberEvent.type == null) {
continue
}
val ageLocalTs = now - (roomMemberEvent.unsignedData?.age ?: 0)
val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION)
CurrentStateEventEntity.getOrCreate(
realm,
roomId,
roomMemberEvent.stateKey,
roomMemberEvent.type
).apply {
eventId = roomMemberEvent.eventId
root = eventEntity
}
roomMemberEventHandler.handle(realm, roomId, roomMemberEvent, false)
}
roomEntity.membersLoadStatus = RoomMembersLoadStatusType.LOADED
roomSummaryUpdater.update(realm, roomId, updateMembers = true)
}
if (cryptoSessionInfoProvider.isRoomEncrypted(roomId)) {
deviceListManager.onRoomMembersLoadedFor(roomId)
}
}
private fun getRoomMembersLoadStatus(roomId: String): RoomMembersLoadStatusType {
var result: RoomMembersLoadStatusType?
Realm.getInstance(monarchy.realmConfiguration).use {
result = RoomEntity.where(it, roomId).findFirst()?.membersLoadStatus
}
return result ?: RoomMembersLoadStatusType.NONE
}
private suspend fun setRoomMembersLoadStatus(roomId: String, status: RoomMembersLoadStatusType) {
monarchy.awaitTransaction { realm ->
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)

View file

@ -83,23 +83,21 @@ internal class RoomMemberEventHandler @Inject constructor(
userId: String,
roomMember: RoomMemberContent
) {
val roomMemberEntity = RoomMemberEntityFactory.create(
roomId,
userId,
roomMember,
// When an update is happening, insertOrUpdate replace existing values with null if they are not provided,
// but we want to preserve presence record value and not replace it with null
getExistingPresenceState(realm, roomId, userId)
)
realm.insertOrUpdate(roomMemberEntity)
}
/**
* Get the already existing presence state for a specific user & room in order NOT to be replaced in RoomMemberSummaryEntity
* by NULL value.
*/
private fun getExistingPresenceState(realm: Realm, roomId: String, userId: String): UserPresenceEntity? {
return RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()?.userPresenceEntity
val existingRoomMemberSummary = RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()
if (existingRoomMemberSummary != null) {
existingRoomMemberSummary.displayName = roomMember.displayName
existingRoomMemberSummary.avatarUrl = roomMember.avatarUrl
existingRoomMemberSummary.membership = roomMember.membership
} else {
val presenceEntity = UserPresenceEntity.where(realm, userId).findFirst()
val roomMemberEntity = RoomMemberEntityFactory.create(
roomId,
userId,
roomMember,
presenceEntity
)
realm.insert(roomMemberEntity)
}
}
private fun saveUserEntityLocallyIfNecessary(

View file

@ -20,6 +20,7 @@ import android.content.Context
import android.graphics.Bitmap
import android.media.MediaMetadataRetriever
import androidx.exifinterface.media.ExifInterface
import org.matrix.android.sdk.api.extensions.ensureNotEmpty
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event
@ -700,6 +701,7 @@ internal class LocalEchoEventFactory @Inject constructor(
MessageType.MSGTYPE_AUDIO -> return TextContent("sent an audio file.")
MessageType.MSGTYPE_IMAGE -> return TextContent("sent an image.")
MessageType.MSGTYPE_VIDEO -> return TextContent("sent a video.")
MessageType.MSGTYPE_BEACON_INFO -> return TextContent(content.body.ensureNotEmpty() ?: "shared live location.")
MessageType.MSGTYPE_POLL_START -> {
return TextContent((content as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "")
}

View file

@ -33,6 +33,7 @@ import kotlinx.coroutines.withContext
import okhttp3.internal.closeQuietly
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
@ -388,7 +389,7 @@ internal class DefaultTimeline(
}
private suspend fun loadRoomMembersIfNeeded() {
val loadRoomMembersParam = LoadRoomMembersTask.Params(roomId)
val loadRoomMembersParam = LoadRoomMembersTask.Params(roomId, excludeMembership = Membership.LEAVE)
try {
loadRoomMembersTask.execute(loadRoomMembersParam)
} catch (failure: Throwable) {

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.util
import org.matrix.android.sdk.BuildConfig
import timber.log.Timber
/**
* Throws in debug, only log in production.
* As this method does not always throw, next statement should be a return.
*/
internal fun fatalError(message: String) {
if (BuildConfig.DEBUG) {
error(message)
} else {
Timber.e(message)
}
}

View file

@ -51,6 +51,7 @@ private const val A_LATITUDE = 1.4
private const val A_LONGITUDE = 40.0
private const val AN_UNCERTAINTY = 5.0
private const val A_TIMEOUT = 15_000L
private const val A_DESCRIPTION = "description"
@ExperimentalCoroutinesApi
internal class DefaultLocationSharingServiceTest {
@ -137,7 +138,7 @@ internal class DefaultLocationSharingServiceTest {
coEvery { stopLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success("stopped-event-id")
coEvery { startLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT, A_DESCRIPTION)
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
@ -150,7 +151,8 @@ internal class DefaultLocationSharingServiceTest {
coVerify { stopLiveLocationShareTask.execute(expectedStopParams) }
val expectedStartParams = StartLiveLocationShareTask.Params(
roomId = A_ROOM_ID,
timeoutMillis = A_TIMEOUT
timeoutMillis = A_TIMEOUT,
description = A_DESCRIPTION
)
coVerify { startLiveLocationShareTask.execute(expectedStartParams) }
}
@ -161,7 +163,7 @@ internal class DefaultLocationSharingServiceTest {
val error = Throwable()
coEvery { stopLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Failure(error)
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT, A_DESCRIPTION)
result shouldBeEqualTo UpdateLiveLocationShareResult.Failure(error)
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
@ -179,7 +181,7 @@ internal class DefaultLocationSharingServiceTest {
coEvery { checkIfExistingActiveLiveTask.execute(any()) } returns false
coEvery { startLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT, A_DESCRIPTION)
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
@ -188,7 +190,8 @@ internal class DefaultLocationSharingServiceTest {
coVerify { checkIfExistingActiveLiveTask.execute(expectedCheckExistingParams) }
val expectedStartParams = StartLiveLocationShareTask.Params(
roomId = A_ROOM_ID,
timeoutMillis = A_TIMEOUT
timeoutMillis = A_TIMEOUT,
description = A_DESCRIPTION
)
coVerify { startLiveLocationShareTask.execute(expectedStartParams) }
}

View file

@ -34,6 +34,7 @@ import org.matrix.android.sdk.test.fakes.FakeSendStateTask
private const val A_USER_ID = "user-id"
private const val A_ROOM_ID = "room-id"
private const val AN_EVENT_ID = "event-id"
private const val A_DESCRIPTION = "description"
private const val A_TIMEOUT = 15_000L
private const val AN_EPOCH = 1655210176L
@ -58,7 +59,8 @@ internal class DefaultStartLiveLocationShareTaskTest {
fun `given parameters and no error when calling the task then result is success`() = runTest {
val params = StartLiveLocationShareTask.Params(
roomId = A_ROOM_ID,
timeoutMillis = A_TIMEOUT
timeoutMillis = A_TIMEOUT,
description = A_DESCRIPTION
)
fakeClock.givenEpoch(AN_EPOCH)
fakeSendStateTask.givenExecuteRetryReturns(AN_EVENT_ID)
@ -67,6 +69,7 @@ internal class DefaultStartLiveLocationShareTaskTest {
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
val expectedBeaconContent = MessageBeaconInfoContent(
body = A_DESCRIPTION,
timeout = params.timeoutMillis,
isLive = true,
unstableTimestampMillis = AN_EPOCH
@ -87,7 +90,8 @@ internal class DefaultStartLiveLocationShareTaskTest {
fun `given parameters and an empty returned event id when calling the task then result is failure`() = runTest {
val params = StartLiveLocationShareTask.Params(
roomId = A_ROOM_ID,
timeoutMillis = A_TIMEOUT
timeoutMillis = A_TIMEOUT,
description = A_DESCRIPTION
)
fakeClock.givenEpoch(AN_EPOCH)
fakeSendStateTask.givenExecuteRetryReturns("")
@ -101,7 +105,8 @@ internal class DefaultStartLiveLocationShareTaskTest {
fun `given parameters and error during event sending when calling the task then result is failure`() = runTest {
val params = StartLiveLocationShareTask.Params(
roomId = A_ROOM_ID,
timeoutMillis = A_TIMEOUT
timeoutMillis = A_TIMEOUT,
description = A_DESCRIPTION
)
fakeClock.givenEpoch(AN_EPOCH)
val error = Throwable()

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