Merge branch 'feature/Perf' into develop
This commit is contained in:
commit
bc2d321a84
@ -35,11 +35,11 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation project(":matrix-sdk-android")
|
implementation project(":matrix-sdk-android")
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
|
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
|
||||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ import io.reactivex.Observable
|
|||||||
|
|
||||||
class RxRoom(private val room: Room) {
|
class RxRoom(private val room: Room) {
|
||||||
|
|
||||||
fun liveRoomSummary(): Observable<RoomSummary> {
|
fun liveRoomSummary(fetchLastEvent: Boolean): Observable<RoomSummary> {
|
||||||
return room.liveRoomSummary.asObservable()
|
return room.liveRoomSummary(fetchLastEvent).asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveRoomMemberIds(): Observable<List<String>> {
|
fun liveRoomMemberIds(): Observable<List<String>> {
|
||||||
|
@ -25,8 +25,8 @@ import io.reactivex.Observable
|
|||||||
|
|
||||||
class RxSession(private val session: Session) {
|
class RxSession(private val session: Session) {
|
||||||
|
|
||||||
fun liveRoomSummaries(): Observable<List<RoomSummary>> {
|
fun liveRoomSummaries(fetchLastEvents: Boolean): Observable<List<RoomSummary>> {
|
||||||
return session.liveRoomSummaries().asObservable()
|
return session.liveRoomSummaries(fetchLastEvents).asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
|
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
|
||||||
|
@ -86,7 +86,7 @@ static def gitRevisionDate() {
|
|||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
def arrow_version = "0.8.0"
|
def arrow_version = "0.8.0"
|
||||||
def support_version = '1.1.0-alpha03'
|
def support_version = '1.1.0-beta01'
|
||||||
def moshi_version = '1.8.0'
|
def moshi_version = '1.8.0'
|
||||||
def lifecycle_version = '2.0.0'
|
def lifecycle_version = '2.0.0'
|
||||||
def coroutines_version = "1.0.1"
|
def coroutines_version = "1.0.1"
|
||||||
@ -98,8 +98,8 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:$support_version"
|
implementation "androidx.appcompat:appcompat:1.1.0-beta01"
|
||||||
implementation "androidx.recyclerview:recyclerview:$support_version"
|
implementation "androidx.recyclerview:recyclerview:1.1.0-alpha06"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
||||||
@ -107,7 +107,7 @@ dependencies {
|
|||||||
// Network
|
// Network
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
|
||||||
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
|
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
|
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||||
implementation 'com.novoda:merlin:1.1.6'
|
implementation 'com.novoda:merlin:1.1.6'
|
||||||
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
||||||
@ -120,7 +120,7 @@ dependencies {
|
|||||||
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
||||||
|
|
||||||
// Work
|
// Work
|
||||||
implementation "androidx.work:work-runtime-ktx:2.1.0-beta01"
|
implementation "androidx.work:work-runtime-ktx:2.1.0-rc01"
|
||||||
|
|
||||||
// FP
|
// FP
|
||||||
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
||||||
@ -155,11 +155,11 @@ dependencies {
|
|||||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
androidTestImplementation "org.koin:koin-test:$koin_version"
|
androidTestImplementation "org.koin:koin-test:$koin_version"
|
||||||
androidTestImplementation 'androidx.test:core:1.1.0'
|
androidTestImplementation 'androidx.test:core:1.2.0'
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||||
androidTestImplementation 'androidx.test:rules:1.1.1'
|
androidTestImplementation 'androidx.test:rules:1.2.0'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
|
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
|
||||||
androidTestImplementation "io.mockk:mockk-android:1.8.13.kotlin13"
|
androidTestImplementation "io.mockk:mockk-android:1.8.13.kotlin13"
|
||||||
androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
|
androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
|
||||||
|
@ -47,8 +47,8 @@ interface Room :
|
|||||||
* A live [RoomSummary] associated with the room
|
* A live [RoomSummary] associated with the room
|
||||||
* You can observe this summary to get dynamic data from this room.
|
* You can observe this summary to get dynamic data from this room.
|
||||||
*/
|
*/
|
||||||
val liveRoomSummary: LiveData<RoomSummary>
|
fun liveRoomSummary(fetchLastEvent: Boolean = false): LiveData<RoomSummary>
|
||||||
|
|
||||||
val roomSummary: RoomSummary?
|
fun roomSummary(fetchLastEvent: Boolean = false): RoomSummary?
|
||||||
|
|
||||||
}
|
}
|
@ -43,6 +43,6 @@ interface RoomService {
|
|||||||
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
|
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
|
||||||
* @return the [LiveData] of [RoomSummary]
|
* @return the [LiveData] of [RoomSummary]
|
||||||
*/
|
*/
|
||||||
fun liveRoomSummaries(): LiveData<List<RoomSummary>>
|
fun liveRoomSummaries(fetchLastEvents: Boolean = true): LiveData<List<RoomSummary>>
|
||||||
|
|
||||||
}
|
}
|
@ -25,6 +25,7 @@ import android.text.TextUtils
|
|||||||
import arrow.core.Try
|
import arrow.core.Try
|
||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import dagger.Lazy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
@ -98,7 +99,7 @@ internal class CryptoManager @Inject constructor(
|
|||||||
private val olmManager: OlmManager,
|
private val olmManager: OlmManager,
|
||||||
// The credentials,
|
// The credentials,
|
||||||
private val credentials: Credentials,
|
private val credentials: Credentials,
|
||||||
private val myDeviceInfoHolder: MyDeviceInfoHolder,
|
private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>,
|
||||||
// the crypto store
|
// the crypto store
|
||||||
private val cryptoStore: IMXCryptoStore,
|
private val cryptoStore: IMXCryptoStore,
|
||||||
// Olm device
|
// Olm device
|
||||||
@ -190,7 +191,7 @@ internal class CryptoManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getMyDevice(): MXDeviceInfo {
|
override fun getMyDevice(): MXDeviceInfo {
|
||||||
return myDeviceInfoHolder.myDevice
|
return myDeviceInfoHolder.get().myDevice
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDevicesList(callback: MatrixCallback<DevicesListResponse>) {
|
override fun getDevicesList(callback: MatrixCallback<DevicesListResponse>) {
|
||||||
|
@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.crypto.verification
|
|||||||
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import dagger.Lazy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.CancelCode
|
import im.vector.matrix.android.api.session.crypto.sas.CancelCode
|
||||||
@ -55,7 +56,7 @@ import kotlin.collections.HashMap
|
|||||||
@SessionScope
|
@SessionScope
|
||||||
internal class DefaultSasVerificationService @Inject constructor(private val credentials: Credentials,
|
internal class DefaultSasVerificationService @Inject constructor(private val credentials: Credentials,
|
||||||
private val cryptoStore: IMXCryptoStore,
|
private val cryptoStore: IMXCryptoStore,
|
||||||
private val myDeviceInfoHolder: MyDeviceInfoHolder,
|
private val myDeviceInfoHolder: Lazy<MyDeviceInfoHolder>,
|
||||||
private val deviceListManager: DeviceListManager,
|
private val deviceListManager: DeviceListManager,
|
||||||
private val setDeviceVerificationAction: SetDeviceVerificationAction,
|
private val setDeviceVerificationAction: SetDeviceVerificationAction,
|
||||||
private val sendToDeviceTask: SendToDeviceTask,
|
private val sendToDeviceTask: SendToDeviceTask,
|
||||||
@ -197,7 +198,7 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
|
|||||||
cryptoStore,
|
cryptoStore,
|
||||||
sendToDeviceTask,
|
sendToDeviceTask,
|
||||||
taskExecutor,
|
taskExecutor,
|
||||||
myDeviceInfoHolder.myDevice.fingerprint()!!,
|
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
|
||||||
startReq.transactionID!!,
|
startReq.transactionID!!,
|
||||||
otherUserId)
|
otherUserId)
|
||||||
addTransaction(tx)
|
addTransaction(tx)
|
||||||
@ -366,7 +367,7 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre
|
|||||||
cryptoStore,
|
cryptoStore,
|
||||||
sendToDeviceTask,
|
sendToDeviceTask,
|
||||||
taskExecutor,
|
taskExecutor,
|
||||||
myDeviceInfoHolder.myDevice.fingerprint()!!,
|
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
|
||||||
txID,
|
txID,
|
||||||
userId,
|
userId,
|
||||||
deviceID)
|
deviceID)
|
||||||
|
@ -16,29 +16,24 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.database.mapper
|
package im.vector.matrix.android.internal.database.mapper
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.TimelineEventFactory
|
import im.vector.matrix.android.internal.session.room.timeline.TimelineEventFactory
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class RoomSummaryMapper @Inject constructor(private val timelineEventFactory: TimelineEventFactory) {
|
||||||
|
|
||||||
internal class RoomSummaryMapper @Inject constructor(
|
fun map(roomSummaryEntity: RoomSummaryEntity, getLatestEvent: Boolean = false): RoomSummary {
|
||||||
private val timelineEventFactory: TimelineEventFactory,
|
|
||||||
private val monarchy: Monarchy) {
|
|
||||||
|
|
||||||
fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary {
|
|
||||||
val tags = roomSummaryEntity.tags.map {
|
val tags = roomSummaryEntity.tags.map {
|
||||||
RoomTag(it.tagName, it.tagOrder)
|
RoomTag(it.tagName, it.tagOrder)
|
||||||
}
|
}
|
||||||
val latestEvent = roomSummaryEntity.latestEvent?.let {
|
val latestEvent = if (getLatestEvent) {
|
||||||
var ev: TimelineEvent? = null
|
roomSummaryEntity.latestEvent?.let {
|
||||||
monarchy.doWithRealm { realm ->
|
timelineEventFactory.create(it, it.realm)
|
||||||
ev = timelineEventFactory.create(it, realm)
|
|
||||||
}
|
}
|
||||||
ev
|
} else {
|
||||||
|
null
|
||||||
}
|
}
|
||||||
return RoomSummary(
|
return RoomSummary(
|
||||||
roomId = roomSummaryEntity.roomId,
|
roomId = roomSummaryEntity.roomId,
|
||||||
|
@ -48,58 +48,7 @@ internal class DefaultPushRuleService @Inject constructor(
|
|||||||
|
|
||||||
override fun fetchPushRules(scope: String) {
|
override fun fetchPushRules(scope: String) {
|
||||||
pushRulesTask
|
pushRulesTask
|
||||||
.configureWith(Unit)
|
.configureWith(GetPushRulesTask.Params(scope))
|
||||||
.dispatchTo(object : MatrixCallback<GetPushRulesResponse> {
|
|
||||||
override fun onSuccess(data: GetPushRulesResponse) {
|
|
||||||
monarchy.runTransactionSync { realm ->
|
|
||||||
//clear existings?
|
|
||||||
//TODO
|
|
||||||
realm.where(PushRulesEntity::class.java)
|
|
||||||
.equalTo(PusherEntityFields.USER_ID, sessionParams.credentials.userId)
|
|
||||||
.findAll().deleteAllFromRealm()
|
|
||||||
|
|
||||||
val content = PushRulesEntity(sessionParams.credentials.userId, scope, "content")
|
|
||||||
data.global.content?.forEach { rule ->
|
|
||||||
PushRulesMapper.map(rule).also {
|
|
||||||
content.pushRules.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
realm.insertOrUpdate(content)
|
|
||||||
|
|
||||||
val override = PushRulesEntity(sessionParams.credentials.userId, scope, "override")
|
|
||||||
data.global.override?.forEach { rule ->
|
|
||||||
PushRulesMapper.map(rule).also {
|
|
||||||
override.pushRules.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
realm.insertOrUpdate(override)
|
|
||||||
|
|
||||||
val rooms = PushRulesEntity(sessionParams.credentials.userId, scope, "room")
|
|
||||||
data.global.room?.forEach { rule ->
|
|
||||||
PushRulesMapper.map(rule).also {
|
|
||||||
rooms.pushRules.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
realm.insertOrUpdate(rooms)
|
|
||||||
|
|
||||||
val senders = PushRulesEntity(sessionParams.credentials.userId, scope, "sender")
|
|
||||||
data.global.sender?.forEach { rule ->
|
|
||||||
PushRulesMapper.map(rule).also {
|
|
||||||
senders.pushRules.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
realm.insertOrUpdate(senders)
|
|
||||||
|
|
||||||
val underrides = PushRulesEntity(sessionParams.credentials.userId, scope, "underride")
|
|
||||||
data.global.underride?.forEach { rule ->
|
|
||||||
PushRulesMapper.map(rule).also {
|
|
||||||
underrides.pushRules.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
realm.insertOrUpdate(underrides)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,22 +54,6 @@ internal class DefaultPusherService @Inject constructor(
|
|||||||
override fun refreshPushers() {
|
override fun refreshPushers() {
|
||||||
getPusherTask
|
getPusherTask
|
||||||
.configureWith(Unit)
|
.configureWith(Unit)
|
||||||
.dispatchTo(object : MatrixCallback<GetPushersResponse> {
|
|
||||||
override fun onSuccess(data: GetPushersResponse) {
|
|
||||||
monarchy.runTransactionSync { realm ->
|
|
||||||
//clear existings?
|
|
||||||
realm.where(PusherEntity::class.java)
|
|
||||||
.equalTo(PusherEntityFields.USER_ID, sessionParam.credentials.userId)
|
|
||||||
.findAll().deleteAllFromRealm()
|
|
||||||
data.pushers?.forEach { jsonPusher ->
|
|
||||||
jsonPusher.toEntity(sessionParam.credentials.userId).also {
|
|
||||||
it.state = PusherState.REGISTERED
|
|
||||||
realm.insertOrUpdate(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,19 +16,81 @@
|
|||||||
package im.vector.matrix.android.internal.session.pushers
|
package im.vector.matrix.android.internal.session.pushers
|
||||||
|
|
||||||
import arrow.core.Try
|
import arrow.core.Try
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.api.pushrules.rest.GetPushRulesResponse
|
import im.vector.matrix.android.api.pushrules.rest.GetPushRulesResponse
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.PushRulesMapper
|
||||||
|
import im.vector.matrix.android.internal.database.model.PushRulesEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.PusherEntityFields
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
import im.vector.matrix.android.internal.util.tryTransactionSync
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
internal interface GetPushRulesTask : Task<Unit, GetPushRulesResponse>
|
internal interface GetPushRulesTask : Task<GetPushRulesTask.Params, Unit> {
|
||||||
|
|
||||||
internal class DefaultGetPushRulesTask @Inject constructor(private val pushRulesApi: PushRulesApi) : GetPushRulesTask {
|
data class Params(val scope: String)
|
||||||
|
|
||||||
override suspend fun execute(params: Unit): Try<GetPushRulesResponse> {
|
}
|
||||||
return executeRequest {
|
|
||||||
|
|
||||||
|
internal class DefaultGetPushRulesTask @Inject constructor(private val pushRulesApi: PushRulesApi,
|
||||||
|
private val monarchy: Monarchy,
|
||||||
|
private val sessionParams: SessionParams) : GetPushRulesTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: GetPushRulesTask.Params): Try<Unit> {
|
||||||
|
return executeRequest<GetPushRulesResponse> {
|
||||||
apiCall = pushRulesApi.getAllRules()
|
apiCall = pushRulesApi.getAllRules()
|
||||||
|
}.flatMap { response ->
|
||||||
|
val scope = params.scope
|
||||||
|
return monarchy.tryTransactionSync { realm ->
|
||||||
|
//clear existings?
|
||||||
|
//TODO
|
||||||
|
realm.where(PushRulesEntity::class.java)
|
||||||
|
.equalTo(PusherEntityFields.USER_ID, sessionParams.credentials.userId)
|
||||||
|
.findAll().deleteAllFromRealm()
|
||||||
|
|
||||||
|
val content = PushRulesEntity(sessionParams.credentials.userId, scope, "content")
|
||||||
|
response.global.content?.forEach { rule ->
|
||||||
|
PushRulesMapper.map(rule).also {
|
||||||
|
content.pushRules.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(content)
|
||||||
|
|
||||||
|
val override = PushRulesEntity(sessionParams.credentials.userId, scope, "override")
|
||||||
|
response.global.override?.forEach { rule ->
|
||||||
|
PushRulesMapper.map(rule).also {
|
||||||
|
override.pushRules.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(override)
|
||||||
|
|
||||||
|
val rooms = PushRulesEntity(sessionParams.credentials.userId, scope, "room")
|
||||||
|
response.global.room?.forEach { rule ->
|
||||||
|
PushRulesMapper.map(rule).also {
|
||||||
|
rooms.pushRules.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(rooms)
|
||||||
|
|
||||||
|
val senders = PushRulesEntity(sessionParams.credentials.userId, scope, "sender")
|
||||||
|
response.global.sender?.forEach { rule ->
|
||||||
|
PushRulesMapper.map(rule).also {
|
||||||
|
senders.pushRules.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(senders)
|
||||||
|
|
||||||
|
val underrides = PushRulesEntity(sessionParams.credentials.userId, scope, "underride")
|
||||||
|
response.global.underride?.forEach { rule ->
|
||||||
|
PushRulesMapper.map(rule).also {
|
||||||
|
underrides.pushRules.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(underrides)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,17 +16,39 @@
|
|||||||
package im.vector.matrix.android.internal.session.pushers
|
package im.vector.matrix.android.internal.session.pushers
|
||||||
|
|
||||||
import arrow.core.Try
|
import arrow.core.Try
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
|
import im.vector.matrix.android.api.session.pushers.PusherState
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.toEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.PusherEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.PusherEntityFields
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
import im.vector.matrix.android.internal.util.tryTransactionSync
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface GetPushersTask : Task<Unit, GetPushersResponse>
|
internal interface GetPushersTask : Task<Unit, Unit>
|
||||||
|
|
||||||
internal class DefaultGetPusherTask @Inject constructor(private val pushersAPI: PushersAPI) : GetPushersTask {
|
internal class DefaultGetPusherTask @Inject constructor(private val pushersAPI: PushersAPI,
|
||||||
|
private val monarchy: Monarchy,
|
||||||
|
private val sessionParams: SessionParams) : GetPushersTask {
|
||||||
|
|
||||||
override suspend fun execute(params: Unit): Try<GetPushersResponse> {
|
override suspend fun execute(params: Unit): Try<Unit> {
|
||||||
return executeRequest {
|
return executeRequest<GetPushersResponse> {
|
||||||
apiCall = pushersAPI.getPushers()
|
apiCall = pushersAPI.getPushers()
|
||||||
|
}.flatMap { response ->
|
||||||
|
monarchy.tryTransactionSync { realm ->
|
||||||
|
//clear existings?
|
||||||
|
realm.where(PusherEntity::class.java)
|
||||||
|
.equalTo(PusherEntityFields.USER_ID, sessionParams.credentials.userId)
|
||||||
|
.findAll().deleteAllFromRealm()
|
||||||
|
response.pushers?.forEach { jsonPusher ->
|
||||||
|
jsonPusher.toEntity(sessionParams.credentials.userId).also {
|
||||||
|
it.state = PusherState.REGISTERED
|
||||||
|
realm.insertOrUpdate(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,6 +34,7 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
|||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.util.fetchCopied
|
import im.vector.matrix.android.internal.util.fetchCopied
|
||||||
|
import im.vector.matrix.android.internal.util.fetchCopyMap
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultRoom @Inject constructor(override val roomId: String,
|
internal class DefaultRoom @Inject constructor(override val roomId: String,
|
||||||
@ -47,19 +48,19 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||||||
private val relationService: RelationService,
|
private val relationService: RelationService,
|
||||||
private val roomMembersService: MembershipService
|
private val roomMembersService: MembershipService
|
||||||
) : Room,
|
) : Room,
|
||||||
TimelineService by timelineService,
|
TimelineService by timelineService,
|
||||||
SendService by sendService,
|
SendService by sendService,
|
||||||
StateService by stateService,
|
StateService by stateService,
|
||||||
ReadService by readService,
|
ReadService by readService,
|
||||||
RelationService by relationService,
|
RelationService by relationService,
|
||||||
MembershipService by roomMembersService {
|
MembershipService by roomMembersService {
|
||||||
|
|
||||||
override val liveRoomSummary: LiveData<RoomSummary> by lazy {
|
override fun liveRoomSummary(fetchLastEvent: Boolean): LiveData<RoomSummary> {
|
||||||
val liveRealmData = RealmLiveData<RoomSummaryEntity>(monarchy.realmConfiguration) { realm ->
|
val liveRealmData = RealmLiveData<RoomSummaryEntity>(monarchy.realmConfiguration) { realm ->
|
||||||
RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
|
RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
|
||||||
}
|
}
|
||||||
Transformations.map(liveRealmData) { results ->
|
return Transformations.map(liveRealmData) { results ->
|
||||||
val roomSummaries = results.map { roomSummaryMapper.map(it) }
|
val roomSummaries = results.map { roomSummaryMapper.map(it, fetchLastEvent) }
|
||||||
|
|
||||||
if (roomSummaries.isEmpty()) {
|
if (roomSummaries.isEmpty()) {
|
||||||
// Create a dummy RoomSummary to avoid Crash during Sign Out or clear cache
|
// Create a dummy RoomSummary to avoid Crash during Sign Out or clear cache
|
||||||
@ -70,11 +71,12 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val roomSummary: RoomSummary?
|
override fun roomSummary(fetchLastEvent: Boolean): RoomSummary? {
|
||||||
get() {
|
return monarchy.fetchAllMappedSync(
|
||||||
var sum: RoomSummaryEntity? = monarchy.fetchCopied { RoomSummaryEntity.where(it, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME).findFirst() }
|
{ realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
|
||||||
return sum?.let { roomSummaryMapper.map(it) }
|
{ roomSummaryMapper.map(it, fetchLastEvent) }
|
||||||
}
|
).firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
override fun isEncrypted(): Boolean {
|
override fun isEncrypted(): Boolean {
|
||||||
return cryptoService.isRoomEncrypted(roomId)
|
return cryptoService.isRoomEncrypted(roomId)
|
||||||
|
@ -52,10 +52,10 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
|
|||||||
return roomFactory.create(roomId)
|
return roomFactory.create(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun liveRoomSummaries(): LiveData<List<RoomSummary>> {
|
override fun liveRoomSummaries(fetchLastEvents: Boolean): LiveData<List<RoomSummary>> {
|
||||||
return monarchy.findAllMappedWithChanges(
|
return monarchy.findAllMappedWithChanges(
|
||||||
{ realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
|
{ realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
|
||||||
{ roomSummaryMapper.map(it) }
|
{ roomSummaryMapper.map(it, fetchLastEvents) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,7 +30,12 @@ import im.vector.matrix.android.api.util.addTo
|
|||||||
import im.vector.matrix.android.internal.crypto.NewSessionListener
|
import im.vector.matrix.android.internal.crypto.NewSessionListener
|
||||||
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.*
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.ChunkEntityFields
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||||
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.query.findIncludingEvent
|
import im.vector.matrix.android.internal.database.query.findIncludingEvent
|
||||||
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
@ -38,7 +43,13 @@ import im.vector.matrix.android.internal.database.query.whereInRoom
|
|||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import im.vector.matrix.android.internal.util.Debouncer
|
import im.vector.matrix.android.internal.util.Debouncer
|
||||||
import io.realm.*
|
import io.realm.OrderedCollectionChangeSet
|
||||||
|
import io.realm.OrderedRealmCollectionChangeListener
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
|
import io.realm.RealmQuery
|
||||||
|
import io.realm.RealmResults
|
||||||
|
import io.realm.Sort
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@ -50,7 +61,6 @@ import kotlin.collections.HashMap
|
|||||||
private const val INITIAL_LOAD_SIZE = 20
|
private const val INITIAL_LOAD_SIZE = 20
|
||||||
private const val MIN_FETCHING_COUNT = 30
|
private const val MIN_FETCHING_COUNT = 30
|
||||||
private const val DISPLAY_INDEX_UNKNOWN = Int.MIN_VALUE
|
private const val DISPLAY_INDEX_UNKNOWN = Int.MIN_VALUE
|
||||||
private const val THREAD_NAME = "TIMELINE_DB_THREAD"
|
|
||||||
|
|
||||||
internal class DefaultTimeline(
|
internal class DefaultTimeline(
|
||||||
private val roomId: String,
|
private val roomId: String,
|
||||||
@ -64,18 +74,22 @@ internal class DefaultTimeline(
|
|||||||
private val allowedTypes: List<String>?
|
private val allowedTypes: List<String>?
|
||||||
) : Timeline {
|
) : Timeline {
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val BACKGROUND_HANDLER = Handler(
|
||||||
|
HandlerThread("TIMELINE_DB_THREAD").apply { start() }.looper
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override var listener: Timeline.Listener? = null
|
override var listener: Timeline.Listener? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
backgroundHandler.get()?.post {
|
BACKGROUND_HANDLER.post {
|
||||||
postSnapshot()
|
postSnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isStarted = AtomicBoolean(false)
|
private val isStarted = AtomicBoolean(false)
|
||||||
private val isReady = AtomicBoolean(false)
|
private val isReady = AtomicBoolean(false)
|
||||||
private val backgroundHandlerThread = AtomicReference<HandlerThread>()
|
|
||||||
private val backgroundHandler = AtomicReference<Handler>()
|
|
||||||
private val mainHandler = Handler(Looper.getMainLooper())
|
private val mainHandler = Handler(Looper.getMainLooper())
|
||||||
private val backgroundRealm = AtomicReference<Realm>()
|
private val backgroundRealm = AtomicReference<Realm>()
|
||||||
private val cancelableBag = CancelableBag()
|
private val cancelableBag = CancelableBag()
|
||||||
@ -168,14 +182,14 @@ internal class DefaultTimeline(
|
|||||||
override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) {
|
override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) {
|
||||||
if (roomId == this@DefaultTimeline.roomId) {
|
if (roomId == this@DefaultTimeline.roomId) {
|
||||||
Timber.v("New session id detected for this room")
|
Timber.v("New session id detected for this room")
|
||||||
backgroundHandler.get()?.post {
|
BACKGROUND_HANDLER.post {
|
||||||
val realm = backgroundRealm.get()
|
val realm = backgroundRealm.get()
|
||||||
var hasChange = false
|
var hasChange = false
|
||||||
builtEvents.forEachIndexed { index, timelineEvent ->
|
builtEvents.forEachIndexed { index, timelineEvent ->
|
||||||
if (timelineEvent.isEncrypted()) {
|
if (timelineEvent.isEncrypted()) {
|
||||||
val eventContent = timelineEvent.root.content.toModel<EncryptedEventContent>()
|
val eventContent = timelineEvent.root.content.toModel<EncryptedEventContent>()
|
||||||
if (eventContent?.sessionId == sessionId
|
if (eventContent?.sessionId == sessionId
|
||||||
&& (timelineEvent.root.mClearEvent == null || timelineEvent.root.mCryptoError != null)) {
|
&& (timelineEvent.root.mClearEvent == null || timelineEvent.root.mCryptoError != null)) {
|
||||||
//we need to rebuild this event
|
//we need to rebuild this event
|
||||||
EventEntity.where(realm, eventId = timelineEvent.root.eventId!!).findFirst()?.let {
|
EventEntity.where(realm, eventId = timelineEvent.root.eventId!!).findFirst()?.let {
|
||||||
builtEvents[index] = timelineEventFactory.create(it, realm)
|
builtEvents[index] = timelineEventFactory.create(it, realm)
|
||||||
@ -194,7 +208,7 @@ internal class DefaultTimeline(
|
|||||||
// Public methods ******************************************************************************
|
// Public methods ******************************************************************************
|
||||||
|
|
||||||
override fun paginate(direction: Timeline.Direction, count: Int) {
|
override fun paginate(direction: Timeline.Direction, count: Int) {
|
||||||
backgroundHandler.get()?.post {
|
BACKGROUND_HANDLER.post {
|
||||||
if (!canPaginate(direction)) {
|
if (!canPaginate(direction)) {
|
||||||
return@post
|
return@post
|
||||||
}
|
}
|
||||||
@ -211,13 +225,8 @@ internal class DefaultTimeline(
|
|||||||
override fun start() {
|
override fun start() {
|
||||||
if (isStarted.compareAndSet(false, true)) {
|
if (isStarted.compareAndSet(false, true)) {
|
||||||
Timber.v("Start timeline for roomId: $roomId and eventId: $initialEventId")
|
Timber.v("Start timeline for roomId: $roomId and eventId: $initialEventId")
|
||||||
val handlerThread = HandlerThread(THREAD_NAME + hashCode())
|
|
||||||
handlerThread.start()
|
|
||||||
val handler = Handler(handlerThread.looper)
|
|
||||||
this.backgroundHandlerThread.set(handlerThread)
|
|
||||||
this.backgroundHandler.set(handler)
|
|
||||||
cryptoService.addNewSessionListener(newSessionListener)
|
cryptoService.addNewSessionListener(newSessionListener)
|
||||||
handler.post {
|
BACKGROUND_HANDLER.post {
|
||||||
val realm = Realm.getInstance(realmConfiguration)
|
val realm = Realm.getInstance(realmConfiguration)
|
||||||
backgroundRealm.set(realm)
|
backgroundRealm.set(realm)
|
||||||
clearUnlinkedEvents(realm)
|
clearUnlinkedEvents(realm)
|
||||||
@ -246,14 +255,12 @@ internal class DefaultTimeline(
|
|||||||
if (isStarted.compareAndSet(true, false)) {
|
if (isStarted.compareAndSet(true, false)) {
|
||||||
cryptoService.removeSessionListener(newSessionListener)
|
cryptoService.removeSessionListener(newSessionListener)
|
||||||
Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId")
|
Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId")
|
||||||
backgroundHandler.get()?.post {
|
BACKGROUND_HANDLER.post {
|
||||||
cancelableBag.cancel()
|
cancelableBag.cancel()
|
||||||
liveEvents.removeAllChangeListeners()
|
liveEvents.removeAllChangeListeners()
|
||||||
backgroundRealm.getAndSet(null).also {
|
backgroundRealm.getAndSet(null).also {
|
||||||
it.close()
|
it.close()
|
||||||
}
|
}
|
||||||
backgroundHandler.set(null)
|
|
||||||
backgroundHandlerThread.getAndSet(null)?.quit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,9 +394,9 @@ internal class DefaultTimeline(
|
|||||||
private fun executePaginationTask(direction: Timeline.Direction, limit: Int) {
|
private fun executePaginationTask(direction: Timeline.Direction, limit: Int) {
|
||||||
val token = getTokenLive(direction) ?: return
|
val token = getTokenLive(direction) ?: return
|
||||||
val params = PaginationTask.Params(roomId = roomId,
|
val params = PaginationTask.Params(roomId = roomId,
|
||||||
from = token,
|
from = token,
|
||||||
direction = direction.toPaginationDirection(),
|
direction = direction.toPaginationDirection(),
|
||||||
limit = limit)
|
limit = limit)
|
||||||
|
|
||||||
Timber.v("Should fetch $limit items $direction")
|
Timber.v("Should fetch $limit items $direction")
|
||||||
paginationTask.configureWith(params)
|
paginationTask.configureWith(params)
|
||||||
@ -400,7 +407,7 @@ internal class DefaultTimeline(
|
|||||||
Timber.v("Success fetching $limit items $direction from pagination request")
|
Timber.v("Success fetching $limit items $direction from pagination request")
|
||||||
} else {
|
} else {
|
||||||
// Database won't be updated, so we force pagination request
|
// Database won't be updated, so we force pagination request
|
||||||
backgroundHandler.get()?.post {
|
BACKGROUND_HANDLER.post {
|
||||||
executePaginationTask(direction, limit)
|
executePaginationTask(direction, limit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,6 +448,7 @@ internal class DefaultTimeline(
|
|||||||
if (count < 1) {
|
if (count < 1) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
val start = System.currentTimeMillis()
|
||||||
val offsetResults = getOffsetResults(startDisplayIndex, direction, count)
|
val offsetResults = getOffsetResults(startDisplayIndex, direction, count)
|
||||||
if (offsetResults.isEmpty()) {
|
if (offsetResults.isEmpty()) {
|
||||||
return 0
|
return 0
|
||||||
@ -459,7 +467,8 @@ internal class DefaultTimeline(
|
|||||||
builtEventsIdMap.entries.filter { it.value >= position }.forEach { it.setValue(it.value + 1) }
|
builtEventsIdMap.entries.filter { it.value >= position }.forEach { it.setValue(it.value + 1) }
|
||||||
builtEventsIdMap[eventEntity.eventId] = position
|
builtEventsIdMap[eventEntity.eventId] = position
|
||||||
}
|
}
|
||||||
Timber.v("Built ${offsetResults.size} items from db")
|
val time = System.currentTimeMillis() - start
|
||||||
|
Timber.v("Built ${offsetResults.size} items from db in $time ms")
|
||||||
return offsetResults.size
|
return offsetResults.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ internal class SimpleTimelineEventFactory @Inject constructor(private val roomMe
|
|||||||
val result = cryptoService.decryptEvent(event, UUID.randomUUID().toString())
|
val result = cryptoService.decryptEvent(event, UUID.randomUUID().toString())
|
||||||
event.setClearData(result)
|
event.setClearData(result)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
Timber.e(failure, "Encrypted event: decryption failed")
|
Timber.e("Encrypted event: decryption failed")
|
||||||
if (failure is MXDecryptionException) {
|
if (failure is MXDecryptionException) {
|
||||||
event.setCryptoError(failure.cryptoError)
|
event.setCryptoError(failure.cryptoError)
|
||||||
}
|
}
|
||||||
|
@ -156,9 +156,10 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
|
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
|
||||||
|
//Do not use beta2 at the moment, as it breaks things
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
|
||||||
implementation 'androidx.core:core-ktx:1.0.1'
|
implementation 'androidx.core:core-ktx:1.0.2'
|
||||||
|
|
||||||
implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'
|
implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'
|
||||||
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
||||||
@ -185,7 +186,7 @@ dependencies {
|
|||||||
implementation 'com.airbnb.android:mvrx:1.0.1'
|
implementation 'com.airbnb.android:mvrx:1.0.1'
|
||||||
|
|
||||||
// Work
|
// Work
|
||||||
implementation "androidx.work:work-runtime-ktx:2.1.0-beta01"
|
implementation "androidx.work:work-runtime-ktx:2.1.0-rc01"
|
||||||
|
|
||||||
// Functional Programming
|
// Functional Programming
|
||||||
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
||||||
@ -195,7 +196,7 @@ dependencies {
|
|||||||
|
|
||||||
// UI
|
// UI
|
||||||
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||||
implementation 'com.google.android.material:material:1.1.0-alpha04'
|
implementation 'com.google.android.material:material:1.1.0-alpha07'
|
||||||
implementation 'me.gujun.android:span:1.7'
|
implementation 'me.gujun.android:span:1.7'
|
||||||
implementation "ru.noties.markwon:core:$markwon_version"
|
implementation "ru.noties.markwon:core:$markwon_version"
|
||||||
implementation "ru.noties.markwon:html:$markwon_version"
|
implementation "ru.noties.markwon:html:$markwon_version"
|
||||||
@ -246,8 +247,8 @@ dependencies {
|
|||||||
|
|
||||||
// TESTS
|
// TESTS
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getGradle().getStartParameter().getTaskRequests().toString().contains("Fdroid")) {
|
if (!getGradle().getStartParameter().getTaskRequests().toString().contains("Fdroid")) {
|
||||||
|
@ -33,6 +33,7 @@ import im.vector.riotx.features.home.AvatarRenderer
|
|||||||
import im.vector.riotx.features.home.HomeNavigator
|
import im.vector.riotx.features.home.HomeNavigator
|
||||||
import im.vector.riotx.features.home.HomeRoomListObservableStore
|
import im.vector.riotx.features.home.HomeRoomListObservableStore
|
||||||
import im.vector.riotx.features.home.group.SelectedGroupStore
|
import im.vector.riotx.features.home.group.SelectedGroupStore
|
||||||
|
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||||
import im.vector.riotx.features.navigation.Navigator
|
import im.vector.riotx.features.navigation.Navigator
|
||||||
import im.vector.riotx.features.notifications.NotifiableEventResolver
|
import im.vector.riotx.features.notifications.NotifiableEventResolver
|
||||||
import im.vector.riotx.features.notifications.NotificationBroadcastReceiver
|
import im.vector.riotx.features.notifications.NotificationBroadcastReceiver
|
||||||
@ -68,6 +69,8 @@ interface VectorComponent {
|
|||||||
|
|
||||||
fun emojiCompatFontProvider(): EmojiCompatFontProvider
|
fun emojiCompatFontProvider(): EmojiCompatFontProvider
|
||||||
|
|
||||||
|
fun eventHtmlRenderer(): EventHtmlRenderer
|
||||||
|
|
||||||
fun navigator(): Navigator
|
fun navigator(): Navigator
|
||||||
|
|
||||||
fun homeNavigator(): HomeNavigator
|
fun homeNavigator(): HomeNavigator
|
||||||
|
@ -73,7 +73,7 @@ class HomeActivityViewModel @AssistedInject constructor(@Assisted initialState:
|
|||||||
private fun observeRoomAndGroup() {
|
private fun observeRoomAndGroup() {
|
||||||
Observable
|
Observable
|
||||||
.combineLatest<List<RoomSummary>, Option<GroupSummary>, List<RoomSummary>>(
|
.combineLatest<List<RoomSummary>, Option<GroupSummary>, List<RoomSummary>>(
|
||||||
session.rx().liveRoomSummaries().throttleLast(300, TimeUnit.MILLISECONDS),
|
session.rx().liveRoomSummaries(fetchLastEvents = true).throttleLast(300, TimeUnit.MILLISECONDS),
|
||||||
selectedGroupStore.observe(),
|
selectedGroupStore.observe(),
|
||||||
BiFunction { rooms, selectedGroupOption ->
|
BiFunction { rooms, selectedGroupOption ->
|
||||||
val selectedGroup = selectedGroupOption.orNull()
|
val selectedGroup = selectedGroupOption.orNull()
|
||||||
|
@ -498,7 +498,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomSummary() {
|
private fun observeRoomSummary() {
|
||||||
room.rx().liveRoomSummary()
|
room.rx().liveRoomSummary(false)
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(
|
copy(
|
||||||
asyncRoomSummary = async,
|
asyncRoomSummary = async,
|
||||||
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.timeline.action
|
|||||||
import com.airbnb.mvrx.*
|
import com.airbnb.mvrx.*
|
||||||
import com.squareup.inject.assisted.Assisted
|
import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
|
import dagger.Lazy
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
@ -84,7 +85,7 @@ data class MessageActionState(
|
|||||||
*/
|
*/
|
||||||
class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
initialState: MessageActionState,
|
initialState: MessageActionState,
|
||||||
private val eventHtmlRenderer: EventHtmlRenderer,
|
private val eventHtmlRenderer: Lazy<EventHtmlRenderer>,
|
||||||
session: Session,
|
session: Session,
|
||||||
private val noticeEventFormatter: NoticeEventFormatter
|
private val noticeEventFormatter: NoticeEventFormatter
|
||||||
) : VectorViewModel<MessageActionState>(initialState) {
|
) : VectorViewModel<MessageActionState>(initialState) {
|
||||||
@ -121,7 +122,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resolveBody(state: MessageActionState): CharSequence? {
|
fun resolveBody(state: MessageActionState): CharSequence? {
|
||||||
return state.messageBody(eventHtmlRenderer, noticeEventFormatter)
|
return state.messageBody(eventHtmlRenderer.get(), noticeEventFormatter)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -23,12 +23,20 @@ import android.text.style.ClickableSpan
|
|||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
import android.text.style.RelativeSizeSpan
|
import android.text.style.RelativeSizeSpan
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import dagger.Lazy
|
||||||
import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
import im.vector.matrix.android.api.permalinks.MatrixLinkify
|
||||||
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
|
||||||
import im.vector.matrix.android.api.session.events.model.RelationType
|
import im.vector.matrix.android.api.session.events.model.RelationType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
|
import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.message.*
|
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||||
import im.vector.matrix.android.api.session.room.send.SendState
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||||
@ -55,7 +63,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
private val colorProvider: ColorProvider,
|
private val colorProvider: ColorProvider,
|
||||||
private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
|
private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
|
||||||
private val htmlRenderer: EventHtmlRenderer,
|
private val htmlRenderer: Lazy<EventHtmlRenderer>,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val emojiCompatFontProvider: EmojiCompatFontProvider,
|
private val emojiCompatFontProvider: EmojiCompatFontProvider,
|
||||||
private val imageContentRenderer: ImageContentRenderer,
|
private val imageContentRenderer: ImageContentRenderer,
|
||||||
@ -79,9 +87,9 @@ class MessageItemFactory @Inject constructor(
|
|||||||
|
|
||||||
val messageContent: MessageContent =
|
val messageContent: MessageContent =
|
||||||
event.annotations?.editSummary?.aggregatedContent?.toModel()
|
event.annotations?.editSummary?.aggregatedContent?.toModel()
|
||||||
?: event.root.getClearContent().toModel()
|
?: event.root.getClearContent().toModel()
|
||||||
?: //Malformed content, we should echo something on screen
|
?: //Malformed content, we should echo something on screen
|
||||||
return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
|
return DefaultItem_().text(stringProvider.getString(R.string.malformed_message))
|
||||||
|
|
||||||
if (messageContent.relatesTo?.type == RelationType.REPLACE) {
|
if (messageContent.relatesTo?.type == RelationType.REPLACE) {
|
||||||
// ignore replace event, the targeted id is already edited
|
// ignore replace event, the targeted id is already edited
|
||||||
@ -91,16 +99,16 @@ class MessageItemFactory @Inject constructor(
|
|||||||
// val ev = all.toModel<Event>()
|
// val ev = all.toModel<Event>()
|
||||||
return when (messageContent) {
|
return when (messageContent) {
|
||||||
is MessageEmoteContent -> buildEmoteMessageItem(messageContent,
|
is MessageEmoteContent -> buildEmoteMessageItem(messageContent,
|
||||||
informationData,
|
informationData,
|
||||||
event.annotations?.editSummary,
|
event.annotations?.editSummary,
|
||||||
highlight,
|
highlight,
|
||||||
callback)
|
callback)
|
||||||
is MessageTextContent -> buildTextMessageItem(event.sendState,
|
is MessageTextContent -> buildTextMessageItem(event.sendState,
|
||||||
messageContent,
|
messageContent,
|
||||||
informationData,
|
informationData,
|
||||||
event.annotations?.editSummary,
|
event.annotations?.editSummary,
|
||||||
highlight,
|
highlight,
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, highlight, callback)
|
is MessageImageContent -> buildImageMessageItem(messageContent, informationData, highlight, callback)
|
||||||
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback)
|
is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback)
|
||||||
@ -134,7 +142,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +165,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
.clickListener(
|
.clickListener(
|
||||||
DebouncedClickListener(View.OnClickListener { _ ->
|
DebouncedClickListener(View.OnClickListener { _ ->
|
||||||
@ -210,7 +218,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +262,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
|
.clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) }
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +274,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
callback: TimelineEventController.Callback?): MessageTextItem? {
|
callback: TimelineEventController.Callback?): MessageTextItem? {
|
||||||
|
|
||||||
val bodyToUse = messageContent.formattedBody?.let {
|
val bodyToUse = messageContent.formattedBody?.let {
|
||||||
htmlRenderer.render(it.trim())
|
htmlRenderer.get().render(it.trim())
|
||||||
} ?: messageContent.body
|
} ?: messageContent.body
|
||||||
|
|
||||||
val linkifiedBody = linkifyBody(bodyToUse, callback)
|
val linkifiedBody = linkifyBody(bodyToUse, callback)
|
||||||
@ -294,7 +302,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,9 +334,9 @@ class MessageItemFactory @Inject constructor(
|
|||||||
//nop
|
//nop
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
editStart,
|
editStart,
|
||||||
editEnd,
|
editEnd,
|
||||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
||||||
return spannable
|
return spannable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +372,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +408,7 @@ class MessageItemFactory @Inject constructor(
|
|||||||
}))
|
}))
|
||||||
.longClickListener { view ->
|
.longClickListener { view ->
|
||||||
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,10 +18,9 @@ package im.vector.riotx.features.html
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.style.URLSpan
|
import android.text.style.URLSpan
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import im.vector.matrix.android.api.permalinks.PermalinkData
|
import im.vector.matrix.android.api.permalinks.PermalinkData
|
||||||
import im.vector.matrix.android.api.permalinks.PermalinkParser
|
import im.vector.matrix.android.api.permalinks.PermalinkParser
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.glide.GlideApp
|
import im.vector.riotx.core.glide.GlideApp
|
||||||
import im.vector.riotx.core.glide.GlideRequests
|
import im.vector.riotx.core.glide.GlideRequests
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
@ -37,12 +36,14 @@ import ru.noties.markwon.html.TagHandler
|
|||||||
import ru.noties.markwon.html.tag.*
|
import ru.noties.markwon.html.tag.*
|
||||||
import java.util.Arrays.asList
|
import java.util.Arrays.asList
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
class EventHtmlRenderer @Inject constructor(context: AppCompatActivity,
|
@Singleton
|
||||||
|
class EventHtmlRenderer @Inject constructor(context: Context,
|
||||||
val avatarRenderer: AvatarRenderer,
|
val avatarRenderer: AvatarRenderer,
|
||||||
session: Session) {
|
sessionHolder: ActiveSessionHolder) {
|
||||||
private val markwon = Markwon.builder(context)
|
private val markwon = Markwon.builder(context)
|
||||||
.usePlugin(MatrixPlugin.create(GlideApp.with(context), context, avatarRenderer, session))
|
.usePlugin(MatrixPlugin.create(GlideApp.with(context), context, avatarRenderer, sessionHolder))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun render(text: String): CharSequence {
|
fun render(text: String): CharSequence {
|
||||||
@ -54,7 +55,7 @@ class EventHtmlRenderer @Inject constructor(context: AppCompatActivity,
|
|||||||
private class MatrixPlugin private constructor(private val glideRequests: GlideRequests,
|
private class MatrixPlugin private constructor(private val glideRequests: GlideRequests,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
private val session: Session) : AbstractMarkwonPlugin() {
|
private val session: ActiveSessionHolder) : AbstractMarkwonPlugin() {
|
||||||
|
|
||||||
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
||||||
builder.htmlParser(MarkwonHtmlParserImpl.create())
|
builder.htmlParser(MarkwonHtmlParserImpl.create())
|
||||||
@ -99,7 +100,7 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR
|
|||||||
asList<String>("h1", "h2", "h3", "h4", "h5", "h6"),
|
asList<String>("h1", "h2", "h3", "h4", "h5", "h6"),
|
||||||
HeadingHandler())
|
HeadingHandler())
|
||||||
.setHandler("mx-reply",
|
.setHandler("mx-reply",
|
||||||
MxReplyTagHandler())
|
MxReplyTagHandler())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun create(glideRequests: GlideRequests, context: Context, avatarRenderer: AvatarRenderer, session: Session): MatrixPlugin {
|
fun create(glideRequests: GlideRequests, context: Context, avatarRenderer: AvatarRenderer, session: ActiveSessionHolder): MatrixPlugin {
|
||||||
return MatrixPlugin(glideRequests, context, avatarRenderer, session)
|
return MatrixPlugin(glideRequests, context, avatarRenderer, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +132,7 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR
|
|||||||
private class MxLinkHandler(private val glideRequests: GlideRequests,
|
private class MxLinkHandler(private val glideRequests: GlideRequests,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
private val session: Session) : TagHandler() {
|
private val sessionHolder: ActiveSessionHolder) : TagHandler() {
|
||||||
|
|
||||||
private val linkHandler = LinkHandler()
|
private val linkHandler = LinkHandler()
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ private class MxLinkHandler(private val glideRequests: GlideRequests,
|
|||||||
val permalinkData = PermalinkParser.parse(link)
|
val permalinkData = PermalinkParser.parse(link)
|
||||||
when (permalinkData) {
|
when (permalinkData) {
|
||||||
is PermalinkData.UserLink -> {
|
is PermalinkData.UserLink -> {
|
||||||
val user = session.getUser(permalinkData.userId)
|
val user = sessionHolder.getSafeActiveSession()?.getUser(permalinkData.userId)
|
||||||
val span = PillImageSpan(glideRequests, avatarRenderer, context, permalinkData.userId, user)
|
val span = PillImageSpan(glideRequests, avatarRenderer, context, permalinkData.userId, user)
|
||||||
SpannableBuilder.setSpans(
|
SpannableBuilder.setSpans(
|
||||||
visitor.builder(),
|
visitor.builder(),
|
||||||
|
@ -117,7 +117,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St
|
|||||||
val body = event.annotations?.editSummary?.aggregatedContent?.toModel<MessageContent>()?.body
|
val body = event.annotations?.editSummary?.aggregatedContent?.toModel<MessageContent>()?.body
|
||||||
?: event.root.getClearContent().toModel<MessageContent>()?.body
|
?: event.root.getClearContent().toModel<MessageContent>()?.body
|
||||||
?: stringProvider.getString(R.string.notification_unknown_new_event)
|
?: stringProvider.getString(R.string.notification_unknown_new_event)
|
||||||
val roomName = room.roomSummary?.displayName ?: ""
|
val roomName = room.roomSummary()?.displayName ?: ""
|
||||||
val senderDisplayName = event.senderName ?: event.root.senderId
|
val senderDisplayName = event.senderName ?: event.root.senderId
|
||||||
|
|
||||||
val notifiableEvent = NotifiableMessageEvent(
|
val notifiableEvent = NotifiableMessageEvent(
|
||||||
@ -129,7 +129,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St
|
|||||||
body = body,
|
body = body,
|
||||||
roomId = event.root.roomId!!,
|
roomId = event.root.roomId!!,
|
||||||
roomName = roomName,
|
roomName = roomName,
|
||||||
roomIsDirect = room.roomSummary?.isDirect ?: false)
|
roomIsDirect = room.roomSummary()?.isDirect ?: false)
|
||||||
|
|
||||||
notifiableEvent.matrixID = session.sessionParams.credentials.userId
|
notifiableEvent.matrixID = session.sessionParams.credentials.userId
|
||||||
notifiableEvent.soundName = null
|
notifiableEvent.soundName = null
|
||||||
@ -137,7 +137,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St
|
|||||||
// Get the avatars URL
|
// Get the avatars URL
|
||||||
// TODO They will be not displayed the first time (known limitation)
|
// TODO They will be not displayed the first time (known limitation)
|
||||||
notifiableEvent.roomAvatarPath = session.contentUrlResolver()
|
notifiableEvent.roomAvatarPath = session.contentUrlResolver()
|
||||||
.resolveThumbnail(room.roomSummary?.avatarUrl,
|
.resolveThumbnail(room.roomSummary()?.avatarUrl,
|
||||||
250,
|
250,
|
||||||
250,
|
250,
|
||||||
ContentUrlResolver.ThumbnailMethod.SCALE)
|
ContentUrlResolver.ThumbnailMethod.SCALE)
|
||||||
|
@ -100,8 +100,8 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
|
|||||||
session.sessionParams.credentials.userId,
|
session.sessionParams.credentials.userId,
|
||||||
message,
|
message,
|
||||||
room.roomId,
|
room.roomId,
|
||||||
room.roomSummary?.displayName ?: room.roomId,
|
room.roomSummary()?.displayName ?: room.roomId,
|
||||||
room.roomSummary?.isDirect == true
|
room.roomSummary()?.isDirect == true
|
||||||
)
|
)
|
||||||
notifiableMessageEvent.outGoingMessage = true
|
notifiableMessageEvent.outGoingMessage = true
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:
|
|||||||
private fun observeJoinedRooms() {
|
private fun observeJoinedRooms() {
|
||||||
session
|
session
|
||||||
.rx()
|
.rx()
|
||||||
.liveRoomSummaries()
|
.liveRoomSummaries(fetchLastEvents = false)
|
||||||
.subscribe { list ->
|
.subscribe { list ->
|
||||||
val joinedRoomIds = list
|
val joinedRoomIds = list
|
||||||
// Keep only joined room
|
// Keep only joined room
|
||||||
|
@ -54,7 +54,7 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted initialState: R
|
|||||||
private fun observeJoinedRooms() {
|
private fun observeJoinedRooms() {
|
||||||
session
|
session
|
||||||
.rx()
|
.rx()
|
||||||
.liveRoomSummaries()
|
.liveRoomSummaries(fetchLastEvents = false)
|
||||||
.subscribe { list ->
|
.subscribe { list ->
|
||||||
withState { state ->
|
withState { state ->
|
||||||
val isRoomJoined = list
|
val isRoomJoined = list
|
||||||
|
@ -23,6 +23,7 @@ import android.preference.PreferenceManager
|
|||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -75,7 +76,7 @@ object VectorLocale {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// init the known locales in background, using kotlin coroutines
|
// init the known locales in background, using kotlin coroutines
|
||||||
GlobalScope.launch {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
initApplicationLocales(context)
|
initApplicationLocales(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,9 +86,7 @@ class VectorSettingsActivity : VectorBaseActivity(),
|
|||||||
try {
|
try {
|
||||||
pref?.fragment?.let {
|
pref?.fragment?.let {
|
||||||
oFragment = supportFragmentManager.fragmentFactory
|
oFragment = supportFragmentManager.fragmentFactory
|
||||||
.instantiate(
|
.instantiate(classLoader, it)
|
||||||
classLoader,
|
|
||||||
it, pref.extras)
|
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
showSnackbar(getString(R.string.not_implemented))
|
showSnackbar(getString(R.string.not_implemented))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user