mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-27 03:49:04 +03:00
Merge branch 'develop' into feature/read_marker
This commit is contained in:
commit
05d09bf950
99 changed files with 987 additions and 575 deletions
34
CHANGES.md
34
CHANGES.md
|
@ -1,4 +1,25 @@
|
||||||
Changes in RiotX 0.6.0 (2019-XX-XX)
|
Changes in RiotX 0.7.0 (2019-XX-XX)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
-
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
-
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
-
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
-
|
||||||
|
|
||||||
|
Translations:
|
||||||
|
-
|
||||||
|
|
||||||
|
Build:
|
||||||
|
-
|
||||||
|
|
||||||
|
Changes in RiotX 0.6.0 (2019-09-24)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
@ -10,14 +31,15 @@ Improvements:
|
||||||
- Remove any notification of a redacted event (#563)
|
- Remove any notification of a redacted event (#563)
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
- Fix a few accessibility issues
|
||||||
|
|
||||||
Bugfix:
|
Bugfix:
|
||||||
- Fix characters erased from the Search field when the result are coming (#545)
|
- Fix characters erased from the Search field when the result are coming (#545)
|
||||||
- "No connection" banner was displayed by mistake
|
- "No connection" banner was displayed by mistake
|
||||||
|
- Leaving community (from another client) has no effect on RiotX (#497)
|
||||||
Translations:
|
- Push rules was not retrieved after a clear cache
|
||||||
-
|
- m.notice messages trigger push notifications (#238)
|
||||||
|
- Embiggen messages with multiple emojis also for edited messages (#458)
|
||||||
|
|
||||||
Build:
|
Build:
|
||||||
- Fix (again) issue with bad versionCode generated by Buildkite (#553)
|
- Fix (again) issue with bad versionCode generated by Buildkite (#553)
|
||||||
|
@ -26,7 +48,7 @@ Changes in RiotX 0.5.0 (2019-09-17)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
- Implementation of login to homeserver with SSO
|
- Implementation of login to homeserver with SSO (#557)
|
||||||
- Handle M_CONSENT_NOT_GIVEN error (#64)
|
- Handle M_CONSENT_NOT_GIVEN error (#64)
|
||||||
- Auto configure homeserver and identity server URLs of LoginActivity with a magic link
|
- Auto configure homeserver and identity server URLs of LoginActivity with a magic link
|
||||||
|
|
||||||
|
|
|
@ -19,77 +19,92 @@ import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
|
||||||
class Action(val type: Type) {
|
sealed class Action {
|
||||||
|
object Notify : Action()
|
||||||
enum class Type(val value: String) {
|
object DoNotNotify : Action()
|
||||||
NOTIFY("notify"),
|
data class Sound(val sound: String) : Action()
|
||||||
DONT_NOTIFY("dont_notify"),
|
data class Highlight(val highlight: Boolean) : Action()
|
||||||
COALESCE("coalesce"),
|
}
|
||||||
SET_TWEAK("set_tweak");
|
|
||||||
|
|
||||||
companion object {
|
private const val ACTION_NOTIFY = "notify"
|
||||||
|
private const val ACTION_DONT_NOTIFY = "dont_notify"
|
||||||
fun safeValueOf(value: String): Type? {
|
private const val ACTION_COALESCE = "coalesce"
|
||||||
try {
|
|
||||||
return valueOf(value)
|
// Ref: https://matrix.org/docs/spec/client_server/latest#tweaks
|
||||||
} catch (e: IllegalArgumentException) {
|
private const val ACTION_OBJECT_SET_TWEAK_KEY = "set_tweak"
|
||||||
return null
|
|
||||||
}
|
private const val ACTION_OBJECT_SET_TWEAK_VALUE_SOUND = "sound"
|
||||||
}
|
private const val ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT = "highlight"
|
||||||
}
|
|
||||||
}
|
private const val ACTION_OBJECT_VALUE_KEY = "value"
|
||||||
|
private const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default"
|
||||||
var tweak_action: String? = null
|
|
||||||
var stringValue: String? = null
|
/**
|
||||||
var boolValue: Boolean? = null
|
* Ref: https://matrix.org/docs/spec/client_server/latest#actions
|
||||||
|
*
|
||||||
companion object {
|
* Convert
|
||||||
fun mapFrom(pushRule: PushRule): List<Action>? {
|
* <pre>
|
||||||
val actions = ArrayList<Action>()
|
* "actions": [
|
||||||
pushRule.actions.forEach { actionStrOrObj ->
|
* "notify",
|
||||||
if (actionStrOrObj is String) {
|
* {
|
||||||
when (actionStrOrObj) {
|
* "set_tweak": "sound",
|
||||||
Action.Type.NOTIFY.value -> Action(Action.Type.NOTIFY)
|
* "value": "default"
|
||||||
Action.Type.DONT_NOTIFY.value -> Action(Action.Type.DONT_NOTIFY)
|
* },
|
||||||
else -> {
|
* {
|
||||||
Timber.w("Unsupported action type ${actionStrOrObj}")
|
* "set_tweak": "highlight"
|
||||||
null
|
* }
|
||||||
}
|
* ]
|
||||||
}?.let {
|
*
|
||||||
actions.add(it)
|
* To
|
||||||
}
|
* [
|
||||||
} else if (actionStrOrObj is Map<*, *>) {
|
* Action.Notify,
|
||||||
val tweakAction = actionStrOrObj["set_tweak"] as? String
|
* Action.Sound("default"),
|
||||||
when (tweakAction) {
|
* Action.Highlight(true)
|
||||||
"sound" -> {
|
* ]
|
||||||
(actionStrOrObj["value"] as? String)?.let { stringValue ->
|
*
|
||||||
Action(Action.Type.SET_TWEAK).also {
|
* </pre>
|
||||||
it.tweak_action = "sound"
|
*/
|
||||||
it.stringValue = stringValue
|
fun PushRule.getActions(): List<Action> {
|
||||||
actions.add(it)
|
val result = ArrayList<Action>()
|
||||||
}
|
|
||||||
}
|
actions.forEach { actionStrOrObj ->
|
||||||
}
|
when (actionStrOrObj) {
|
||||||
"highlight" -> {
|
ACTION_NOTIFY -> Action.Notify
|
||||||
(actionStrOrObj["value"] as? Boolean)?.let { boolValue ->
|
ACTION_DONT_NOTIFY -> Action.DoNotNotify
|
||||||
Action(Action.Type.SET_TWEAK).also {
|
is Map<*, *> -> {
|
||||||
it.tweak_action = "highlight"
|
when (actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]) {
|
||||||
it.boolValue = boolValue
|
ACTION_OBJECT_SET_TWEAK_VALUE_SOUND -> {
|
||||||
actions.add(it)
|
(actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? String)?.let { stringValue ->
|
||||||
}
|
Action.Sound(stringValue)
|
||||||
}
|
}
|
||||||
}
|
// When the value is not there, default sound (not specified by the spec)
|
||||||
else -> {
|
?: Action.Sound(ACTION_OBJECT_VALUE_VALUE_DEFAULT)
|
||||||
Timber.w("Unsupported action type ${actionStrOrObj}")
|
|
||||||
}
|
}
|
||||||
}
|
ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> {
|
||||||
} else {
|
(actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue ->
|
||||||
Timber.w("Unsupported action type ${actionStrOrObj}")
|
Action.Highlight(boolValue)
|
||||||
return null
|
}
|
||||||
}
|
// When the value is not there, default is true, says the spec
|
||||||
}
|
?: Action.Highlight(true)
|
||||||
return if (actions.isEmpty()) null else actions
|
}
|
||||||
}
|
else -> {
|
||||||
}
|
Timber.w("Unsupported set_tweak value ${actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Timber.w("Unsupported action type $actionStrOrObj")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}?.let {
|
||||||
|
result.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,14 +25,14 @@ interface PushRuleService {
|
||||||
/**
|
/**
|
||||||
* Fetch the push rules from the server
|
* Fetch the push rules from the server
|
||||||
*/
|
*/
|
||||||
fun fetchPushRules(scope: String = "global")
|
fun fetchPushRules(scope: String = RuleScope.GLOBAL)
|
||||||
|
|
||||||
//TODO get push rule set
|
//TODO get push rule set
|
||||||
fun getPushRules(scope: String = "global"): List<PushRule>
|
fun getPushRules(scope: String = RuleScope.GLOBAL): List<PushRule>
|
||||||
|
|
||||||
//TODO update rule
|
//TODO update rule
|
||||||
|
|
||||||
fun updatePushRuleEnableStatus(kind: String, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
fun addPushRuleListener(listener: PushRuleListener)
|
fun addPushRuleListener(listener: PushRuleListener)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ object RuleIds {
|
||||||
|
|
||||||
// Default Underride Rules
|
// Default Underride Rules
|
||||||
const val RULE_ID_CALL = ".m.rule.call"
|
const val RULE_ID_CALL = ".m.rule.call"
|
||||||
const val RULE_ID_one_to_one_encrypted_room = ".m.rule.encrypted_room_one_to_one"
|
const val RULE_ID_ONE_TO_ONE_ENCRYPTED_ROOM = ".m.rule.encrypted_room_one_to_one"
|
||||||
const val RULE_ID_ONE_TO_ONE_ROOM = ".m.rule.room_one_to_one"
|
const val RULE_ID_ONE_TO_ONE_ROOM = ".m.rule.room_one_to_one"
|
||||||
const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message"
|
const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message"
|
||||||
const val RULE_ID_ENCRYPTED = ".m.rule.encrypted"
|
const val RULE_ID_ENCRYPTED = ".m.rule.encrypted"
|
||||||
|
|
|
@ -15,12 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.api.pushrules
|
package im.vector.matrix.android.api.pushrules
|
||||||
|
|
||||||
|
object RuleScope {
|
||||||
enum class RulesetKey(val value: String) {
|
const val GLOBAL = "global"
|
||||||
CONTENT("content"),
|
}
|
||||||
OVERRIDE("override"),
|
|
||||||
ROOM("room"),
|
|
||||||
SENDER("sender"),
|
|
||||||
UNDERRIDE("underride"),
|
|
||||||
UNKNOWN("")
|
|
||||||
}
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* 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 im.vector.matrix.android.api.pushrules
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules
|
||||||
|
*/
|
||||||
|
enum class RuleSetKey(val value: String) {
|
||||||
|
CONTENT("content"),
|
||||||
|
OVERRIDE("override"),
|
||||||
|
ROOM("room"),
|
||||||
|
SENDER("sender"),
|
||||||
|
UNDERRIDE("underride")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules-scope-kind-ruleid
|
||||||
|
*/
|
||||||
|
typealias RuleKind = RuleSetKey
|
|
@ -71,7 +71,7 @@ data class PushCondition(
|
||||||
this.key?.let { SenderNotificationPermissionCondition(it) }
|
this.key?.let { SenderNotificationPermissionCondition(it) }
|
||||||
}
|
}
|
||||||
Condition.Kind.UNRECOGNIZE -> {
|
Condition.Kind.UNRECOGNIZE -> {
|
||||||
Timber.e("Unknwon kind $kind")
|
Timber.e("Unknown kind $kind")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,15 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.api.session.group.model
|
package im.vector.matrix.android.api.session.group.model
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds some data of a group.
|
* This class holds some data of a group.
|
||||||
* It can be retrieved through [im.vector.matrix.android.api.session.group.GroupService]
|
* It can be retrieved through [im.vector.matrix.android.api.session.group.GroupService]
|
||||||
*/
|
*/
|
||||||
data class GroupSummary(
|
data class GroupSummary(
|
||||||
val groupId: String,
|
val groupId: String,
|
||||||
|
val membership: Membership,
|
||||||
val displayName: String = "",
|
val displayName: String = "",
|
||||||
val shortDescription: String = "",
|
val shortDescription: String = "",
|
||||||
val avatarUrl: String = "",
|
val avatarUrl: String = "",
|
||||||
|
|
|
@ -16,9 +16,6 @@
|
||||||
package im.vector.matrix.android.api.session.pushers
|
package im.vector.matrix.android.api.session.pushers
|
||||||
|
|
||||||
data class Pusher(
|
data class Pusher(
|
||||||
|
|
||||||
val userId: String,
|
|
||||||
|
|
||||||
val pushKey: String,
|
val pushKey: String,
|
||||||
val kind: String,
|
val kind: String,
|
||||||
val appId: String,
|
val appId: String,
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.util.Patterns
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.MatrixPatterns.isUserId
|
import im.vector.matrix.android.api.MatrixPatterns.isUserId
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
|
@ -219,7 +218,7 @@ class CreateRoomParams {
|
||||||
* @param ids the participant ids to add.
|
* @param ids the participant ids to add.
|
||||||
*/
|
*/
|
||||||
fun addParticipantIds(hsConfig: HomeServerConnectionConfig,
|
fun addParticipantIds(hsConfig: HomeServerConnectionConfig,
|
||||||
credentials: Credentials,
|
userId: String,
|
||||||
ids: List<String>) {
|
ids: List<String>) {
|
||||||
for (id in ids) {
|
for (id in ids) {
|
||||||
if (Patterns.EMAIL_ADDRESS.matcher(id).matches() && hsConfig.identityServerUri != null) {
|
if (Patterns.EMAIL_ADDRESS.matcher(id).matches() && hsConfig.identityServerUri != null) {
|
||||||
|
@ -233,7 +232,7 @@ class CreateRoomParams {
|
||||||
invite3pids!!.add(pid)
|
invite3pids!!.add(pid)
|
||||||
} else if (isUserId(id)) {
|
} else if (isUserId(id)) {
|
||||||
// do not invite oneself
|
// do not invite oneself
|
||||||
if (credentials.userId != id) {
|
if (userId != id) {
|
||||||
if (null == invitedUserIds) {
|
if (null == invitedUserIds) {
|
||||||
invitedUserIds = ArrayList()
|
invitedUserIds = ArrayList()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,14 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto.actions
|
package im.vector.matrix.android.internal.crypto.actions
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
|
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
|
||||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class SetDeviceVerificationAction @Inject constructor(private val cryptoStore: IMXCryptoStore,
|
internal class SetDeviceVerificationAction @Inject constructor(private val cryptoStore: IMXCryptoStore,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val keysBackup: KeysBackup) {
|
private val keysBackup: KeysBackup) {
|
||||||
|
|
||||||
fun handle(verificationStatus: Int, deviceId: String, userId: String) {
|
fun handle(verificationStatus: Int, deviceId: String, userId: String) {
|
||||||
|
@ -39,7 +39,7 @@ internal class SetDeviceVerificationAction @Inject constructor(private val crypt
|
||||||
device.verified = verificationStatus
|
device.verified = verificationStatus
|
||||||
cryptoStore.storeUserDevice(userId, device)
|
cryptoStore.storeUserDevice(userId, device)
|
||||||
|
|
||||||
if (userId == credentials.userId) {
|
if (userId == this.userId) {
|
||||||
// If one of the user's own devices is being marked as verified / unverified,
|
// If one of the user's own devices is being marked as verified / unverified,
|
||||||
// check the key backup status, since whether or not we use this depends on
|
// check the key backup status, since whether or not we use this depends on
|
||||||
// whether it has a signature from a verified device
|
// whether it has a signature from a verified device
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
package im.vector.matrix.android.internal.crypto.algorithms.megolm
|
package im.vector.matrix.android.internal.crypto.algorithms.megolm
|
||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
|
@ -40,7 +39,7 @@ import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
internal class MXMegolmDecryption(private val credentials: Credentials,
|
internal class MXMegolmDecryption(private val userId: String,
|
||||||
private val olmDevice: MXOlmDevice,
|
private val olmDevice: MXOlmDevice,
|
||||||
private val deviceListManager: DeviceListManager,
|
private val deviceListManager: DeviceListManager,
|
||||||
private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
|
private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
|
||||||
|
@ -146,11 +145,11 @@ internal class MXMegolmDecryption(private val credentials: Credentials,
|
||||||
|
|
||||||
val selfMap = HashMap<String, String>()
|
val selfMap = HashMap<String, String>()
|
||||||
// TODO Replace this hard coded keys (see OutgoingRoomKeyRequestManager)
|
// TODO Replace this hard coded keys (see OutgoingRoomKeyRequestManager)
|
||||||
selfMap["userId"] = credentials.userId
|
selfMap["userId"] = userId
|
||||||
selfMap["deviceId"] = "*"
|
selfMap["deviceId"] = "*"
|
||||||
recipients.add(selfMap)
|
recipients.add(selfMap)
|
||||||
|
|
||||||
if (!TextUtils.equals(sender, credentials.userId)) {
|
if (!TextUtils.equals(sender, userId)) {
|
||||||
val senderMap = HashMap<String, String>()
|
val senderMap = HashMap<String, String>()
|
||||||
senderMap["userId"] = sender
|
senderMap["userId"] = sender
|
||||||
senderMap["deviceId"] = encryptedEventContent.deviceId!!
|
senderMap["deviceId"] = encryptedEventContent.deviceId!!
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto.algorithms.megolm
|
package im.vector.matrix.android.internal.crypto.algorithms.megolm
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
||||||
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
||||||
import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequestManager
|
import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequestManager
|
||||||
|
@ -24,10 +23,11 @@ import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForDevi
|
||||||
import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter
|
import im.vector.matrix.android.internal.crypto.actions.MessageEncrypter
|
||||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class MXMegolmDecryptionFactory @Inject constructor(private val credentials: Credentials,
|
internal class MXMegolmDecryptionFactory @Inject constructor(@UserId private val userId: String,
|
||||||
private val olmDevice: MXOlmDevice,
|
private val olmDevice: MXOlmDevice,
|
||||||
private val deviceListManager: DeviceListManager,
|
private val deviceListManager: DeviceListManager,
|
||||||
private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
|
private val outgoingRoomKeyRequestManager: OutgoingRoomKeyRequestManager,
|
||||||
|
@ -39,7 +39,7 @@ internal class MXMegolmDecryptionFactory @Inject constructor(private val credent
|
||||||
|
|
||||||
fun create(): MXMegolmDecryption {
|
fun create(): MXMegolmDecryption {
|
||||||
return MXMegolmDecryption(
|
return MXMegolmDecryption(
|
||||||
credentials,
|
userId,
|
||||||
olmDevice,
|
olmDevice,
|
||||||
deviceListManager,
|
deviceListManager,
|
||||||
outgoingRoomKeyRequestManager,
|
outgoingRoomKeyRequestManager,
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto.algorithms.olm
|
package im.vector.matrix.android.internal.crypto.algorithms.olm
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
|
@ -35,8 +34,8 @@ import timber.log.Timber
|
||||||
internal class MXOlmDecryption(
|
internal class MXOlmDecryption(
|
||||||
// The olm device interface
|
// The olm device interface
|
||||||
private val olmDevice: MXOlmDevice,
|
private val olmDevice: MXOlmDevice,
|
||||||
// the matrix credentials
|
// the matrix userId
|
||||||
private val credentials: Credentials)
|
private val userId: String)
|
||||||
: IMXDecrypting {
|
: IMXDecrypting {
|
||||||
|
|
||||||
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult {
|
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult {
|
||||||
|
@ -97,9 +96,9 @@ internal class MXOlmDecryption(
|
||||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY, reason)
|
throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_PROPERTY, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (olmPayloadContent.recipient != credentials.userId) {
|
if (olmPayloadContent.recipient != userId) {
|
||||||
Timber.e("## decryptEvent() : Event ${event.eventId}:" +
|
Timber.e("## decryptEvent() : Event ${event.eventId}:" +
|
||||||
" Intended recipient ${olmPayloadContent.recipient} does not match our id ${credentials.userId}")
|
" Intended recipient ${olmPayloadContent.recipient} does not match our id $userId")
|
||||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_RECIPIENT,
|
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_RECIPIENT,
|
||||||
String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient))
|
String.format(MXCryptoError.BAD_RECIPIENT_REASON, olmPayloadContent.recipient))
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,16 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto.algorithms.olm
|
package im.vector.matrix.android.internal.crypto.algorithms.olm
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class MXOlmDecryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice,
|
internal class MXOlmDecryptionFactory @Inject constructor(private val olmDevice: MXOlmDevice,
|
||||||
private val credentials: Credentials) {
|
@UserId private val userId: String) {
|
||||||
|
|
||||||
fun create(): MXOlmDecryption {
|
fun create(): MXOlmDecryption {
|
||||||
return MXOlmDecryption(
|
return MXOlmDecryption(
|
||||||
olmDevice,
|
olmDevice,
|
||||||
credentials)
|
userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,11 +16,11 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto.tasks
|
package im.vector.matrix.android.internal.crypto.tasks
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
||||||
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DeleteDeviceAuth
|
import im.vector.matrix.android.internal.crypto.model.rest.DeleteDeviceAuth
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DeleteDeviceParams
|
import im.vector.matrix.android.internal.crypto.model.rest.DeleteDeviceParams
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -34,7 +34,7 @@ internal interface DeleteDeviceWithUserPasswordTask : Task<DeleteDeviceWithUserP
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultDeleteDeviceWithUserPasswordTask @Inject constructor(private val cryptoApi: CryptoApi,
|
internal class DefaultDeleteDeviceWithUserPasswordTask @Inject constructor(private val cryptoApi: CryptoApi,
|
||||||
private val credentials: Credentials)
|
@UserId private val userId: String)
|
||||||
: DeleteDeviceWithUserPasswordTask {
|
: DeleteDeviceWithUserPasswordTask {
|
||||||
|
|
||||||
override suspend fun execute(params: DeleteDeviceWithUserPasswordTask.Params) {
|
override suspend fun execute(params: DeleteDeviceWithUserPasswordTask.Params) {
|
||||||
|
@ -45,7 +45,7 @@ internal class DefaultDeleteDeviceWithUserPasswordTask @Inject constructor(priva
|
||||||
.apply {
|
.apply {
|
||||||
type = LoginFlowTypes.PASSWORD
|
type = LoginFlowTypes.PASSWORD
|
||||||
session = params.authSession
|
session = params.authSession
|
||||||
user = credentials.userId
|
user = userId
|
||||||
password = params.password
|
password = params.password
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,14 +22,15 @@ import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
||||||
|
|
||||||
internal object GroupSummaryMapper {
|
internal object GroupSummaryMapper {
|
||||||
|
|
||||||
fun map(roomSummaryEntity: GroupSummaryEntity): GroupSummary {
|
fun map(groupSummaryEntity: GroupSummaryEntity): GroupSummary {
|
||||||
return GroupSummary(
|
return GroupSummary(
|
||||||
roomSummaryEntity.groupId,
|
groupSummaryEntity.groupId,
|
||||||
roomSummaryEntity.displayName,
|
groupSummaryEntity.membership,
|
||||||
roomSummaryEntity.shortDescription,
|
groupSummaryEntity.displayName,
|
||||||
roomSummaryEntity.avatarUrl,
|
groupSummaryEntity.shortDescription,
|
||||||
roomSummaryEntity.roomIds.toList(),
|
groupSummaryEntity.avatarUrl,
|
||||||
roomSummaryEntity.userIds.toList()
|
groupSummaryEntity.roomIds.toList(),
|
||||||
|
groupSummaryEntity.userIds.toList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ internal object PushersMapper {
|
||||||
fun map(pushEntity: PusherEntity): Pusher {
|
fun map(pushEntity: PusherEntity): Pusher {
|
||||||
|
|
||||||
return Pusher(
|
return Pusher(
|
||||||
userId = pushEntity.userId,
|
|
||||||
pushKey = pushEntity.pushKey,
|
pushKey = pushEntity.pushKey,
|
||||||
kind = pushEntity.kind ?: "",
|
kind = pushEntity.kind ?: "",
|
||||||
appId = pushEntity.appId,
|
appId = pushEntity.appId,
|
||||||
|
@ -39,9 +38,8 @@ internal object PushersMapper {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun map(pusher: JsonPusher, userId: String): PusherEntity {
|
fun map(pusher: JsonPusher): PusherEntity {
|
||||||
return PusherEntity(
|
return PusherEntity(
|
||||||
userId = userId,
|
|
||||||
pushKey = pusher.pushKey,
|
pushKey = pusher.pushKey,
|
||||||
kind = pusher.kind,
|
kind = pusher.kind,
|
||||||
appId = pusher.appId,
|
appId = pusher.appId,
|
||||||
|
@ -58,6 +56,6 @@ internal fun PusherEntity.asDomain(): Pusher {
|
||||||
return PushersMapper.map(this)
|
return PushersMapper.map(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun JsonPusher.toEntity(userId: String): PusherEntity {
|
internal fun JsonPusher.toEntity(): PusherEntity {
|
||||||
return PushersMapper.map(this, userId)
|
return PushersMapper.map(this)
|
||||||
}
|
}
|
|
@ -20,9 +20,13 @@ import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.annotations.PrimaryKey
|
import io.realm.annotations.PrimaryKey
|
||||||
|
|
||||||
internal open class GroupEntity(@PrimaryKey var groupId: String = ""
|
/**
|
||||||
|
* This class is used to store group info (groupId and membership) from the sync response.
|
||||||
) : RealmObject() {
|
* Then [im.vector.matrix.android.internal.session.group.GroupSummaryUpdater] observes change and
|
||||||
|
* makes requests to fetch group information from the homeserver
|
||||||
|
*/
|
||||||
|
internal open class GroupEntity(@PrimaryKey var groupId: String = "")
|
||||||
|
: RealmObject() {
|
||||||
|
|
||||||
private var membershipStr: String = Membership.NONE.name
|
private var membershipStr: String = Membership.NONE.name
|
||||||
var membership: Membership
|
var membership: Membership
|
||||||
|
|
|
@ -16,18 +16,28 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.database.model
|
package im.vector.matrix.android.internal.database.model
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.annotations.PrimaryKey
|
import io.realm.annotations.PrimaryKey
|
||||||
|
|
||||||
internal open class GroupSummaryEntity(@PrimaryKey var groupId: String = "",
|
internal open class GroupSummaryEntity(@PrimaryKey var groupId: String = "",
|
||||||
var displayName: String = "",
|
var displayName: String = "",
|
||||||
var shortDescription: String = "",
|
var shortDescription: String = "",
|
||||||
var avatarUrl: String = "",
|
var avatarUrl: String = "",
|
||||||
var roomIds: RealmList<String> = RealmList(),
|
var roomIds: RealmList<String> = RealmList(),
|
||||||
var userIds: RealmList<String> = RealmList()
|
var userIds: RealmList<String> = RealmList()
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
||||||
|
private var membershipStr: String = Membership.NONE.name
|
||||||
|
var membership: Membership
|
||||||
|
get() {
|
||||||
|
return Membership.valueOf(membershipStr)
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
membershipStr = value.name
|
||||||
|
}
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,17 +15,24 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.database.model
|
package im.vector.matrix.android.internal.database.model
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleKind
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.annotations.Index
|
|
||||||
|
|
||||||
|
|
||||||
internal open class PushRulesEntity(
|
internal open class PushRulesEntity(
|
||||||
@Index var userId: String = "",
|
|
||||||
var scope: String = "",
|
var scope: String = "",
|
||||||
// "content", etc.
|
|
||||||
var rulesetKey: String = "",
|
|
||||||
var pushRules: RealmList<PushRuleEntity> = RealmList()
|
var pushRules: RealmList<PushRuleEntity> = RealmList()
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
||||||
|
private var kindStr: String = RuleKind.CONTENT.name
|
||||||
|
var kind: RuleKind
|
||||||
|
get() {
|
||||||
|
return RuleKind.valueOf(kindStr)
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
kindStr = value.name
|
||||||
|
}
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
|
@ -17,7 +17,6 @@ package im.vector.matrix.android.internal.database.model
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.pushers.PusherState
|
import im.vector.matrix.android.api.session.pushers.PusherState
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.annotations.Index
|
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
// at java.lang.Thread.run(Thread.java:764)
|
// at java.lang.Thread.run(Thread.java:764)
|
||||||
|
@ -29,7 +28,6 @@ import io.realm.annotations.Index
|
||||||
// at im.vector.matrix.android.internal.session.pushers.AddHttpPusherWorker$doWork$$inlined$fold$lambda$2.execute(AddHttpPusherWorker.kt:70)
|
// at im.vector.matrix.android.internal.session.pushers.AddHttpPusherWorker$doWork$$inlined$fold$lambda$2.execute(AddHttpPusherWorker.kt:70)
|
||||||
// at io.realm.Realm.executeTransaction(Realm.java:1493)
|
// at io.realm.Realm.executeTransaction(Realm.java:1493)
|
||||||
internal open class PusherEntity(
|
internal open class PusherEntity(
|
||||||
@Index var userId: String = "",
|
|
||||||
var pushKey: String = "",
|
var pushKey: String = "",
|
||||||
var kind: String? = null,
|
var kind: String? = null,
|
||||||
var appId: String = "",
|
var appId: String = "",
|
||||||
|
|
|
@ -23,9 +23,9 @@ import io.realm.Realm
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
|
|
||||||
internal fun GroupEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<GroupEntity> {
|
internal fun GroupEntity.Companion.where(realm: Realm, groupId: String): RealmQuery<GroupEntity> {
|
||||||
return realm.where<GroupEntity>()
|
return realm.where<GroupEntity>()
|
||||||
.equalTo(GroupEntityFields.GROUP_ID, roomId)
|
.equalTo(GroupEntityFields.GROUP_ID, groupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun GroupEntity.Companion.where(realm: Realm, membership: Membership? = null): RealmQuery<GroupEntity> {
|
internal fun GroupEntity.Companion.where(realm: Realm, membership: Membership? = null): RealmQuery<GroupEntity> {
|
||||||
|
|
|
@ -30,3 +30,7 @@ internal fun GroupSummaryEntity.Companion.where(realm: Realm, groupId: String? =
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun GroupSummaryEntity.Companion.where(realm: Realm, groupIds: List<String>): RealmQuery<GroupSummaryEntity> {
|
||||||
|
return realm.where<GroupSummaryEntity>()
|
||||||
|
.`in`(GroupSummaryEntityFields.GROUP_ID, groupIds.toTypedArray())
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.database.query
|
package im.vector.matrix.android.internal.database.query
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleKind
|
||||||
import im.vector.matrix.android.internal.database.model.PushRulesEntity
|
import im.vector.matrix.android.internal.database.model.PushRulesEntity
|
||||||
import im.vector.matrix.android.internal.database.model.PushRulesEntityFields
|
import im.vector.matrix.android.internal.database.model.PushRulesEntityFields
|
||||||
import im.vector.matrix.android.internal.database.model.PusherEntity
|
import im.vector.matrix.android.internal.database.model.PusherEntity
|
||||||
|
@ -24,10 +25,8 @@ import io.realm.RealmQuery
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
|
|
||||||
internal fun PusherEntity.Companion.where(realm: Realm,
|
internal fun PusherEntity.Companion.where(realm: Realm,
|
||||||
userId: String,
|
|
||||||
pushKey: String? = null): RealmQuery<PusherEntity> {
|
pushKey: String? = null): RealmQuery<PusherEntity> {
|
||||||
return realm.where<PusherEntity>()
|
return realm.where<PusherEntity>()
|
||||||
.equalTo(PusherEntityFields.USER_ID, userId)
|
|
||||||
.apply {
|
.apply {
|
||||||
if (pushKey != null) {
|
if (pushKey != null) {
|
||||||
equalTo(PusherEntityFields.PUSH_KEY, pushKey)
|
equalTo(PusherEntityFields.PUSH_KEY, pushKey)
|
||||||
|
@ -36,11 +35,9 @@ internal fun PusherEntity.Companion.where(realm: Realm,
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun PushRulesEntity.Companion.where(realm: Realm,
|
internal fun PushRulesEntity.Companion.where(realm: Realm,
|
||||||
userId: String,
|
|
||||||
scope: String,
|
scope: String,
|
||||||
ruleSetKey: String): RealmQuery<PushRulesEntity> {
|
kind: RuleKind): RealmQuery<PushRulesEntity> {
|
||||||
return realm.where<PushRulesEntity>()
|
return realm.where<PushRulesEntity>()
|
||||||
.equalTo(PushRulesEntityFields.USER_ID, userId)
|
|
||||||
.equalTo(PushRulesEntityFields.SCOPE, scope)
|
.equalTo(PushRulesEntityFields.SCOPE, scope)
|
||||||
.equalTo(PushRulesEntityFields.RULESET_KEY, ruleSetKey)
|
.equalTo(PushRulesEntityFields.KIND_STR, kind.name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,18 @@ internal fun isEventRead(monarchy: Monarchy,
|
||||||
var isEventRead = false
|
var isEventRead = false
|
||||||
|
|
||||||
monarchy.doWithRealm { realm ->
|
monarchy.doWithRealm { realm ->
|
||||||
val readReceipt = ReadReceiptEntity.where(realm, roomId, userId).findFirst() ?: return@doWithRealm
|
|
||||||
val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId) ?: return@doWithRealm
|
val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId) ?: return@doWithRealm
|
||||||
val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.root?.displayIndex ?: Int.MIN_VALUE
|
val eventToCheck = liveChunk.timelineEvents.find(eventId)?.root
|
||||||
val eventToCheckIndex = liveChunk.timelineEvents.find(eventId)?.root?.displayIndex ?: Int.MAX_VALUE
|
|
||||||
|
|
||||||
isEventRead = eventToCheckIndex <= readReceiptIndex
|
isEventRead = if (eventToCheck?.sender == userId) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
val readReceipt = ReadReceiptEntity.where(realm, roomId, userId).findFirst() ?: return@doWithRealm
|
||||||
|
val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.root?.displayIndex ?: Int.MIN_VALUE
|
||||||
|
val eventToCheckIndex = eventToCheck?.displayIndex ?: Int.MAX_VALUE
|
||||||
|
|
||||||
|
eventToCheckIndex <= readReceiptIndex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isEventRead
|
return isEventRead
|
||||||
|
|
|
@ -23,6 +23,7 @@ import im.vector.matrix.android.internal.network.parsing.UriMoshiAdapter
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountData
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountData
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataFallback
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataFallback
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataPushRules
|
||||||
|
|
||||||
|
|
||||||
object MoshiProvider {
|
object MoshiProvider {
|
||||||
|
@ -31,6 +32,7 @@ object MoshiProvider {
|
||||||
.add(UriMoshiAdapter())
|
.add(UriMoshiAdapter())
|
||||||
.add(RuntimeJsonAdapterFactory.of(UserAccountData::class.java, "type", UserAccountDataFallback::class.java)
|
.add(RuntimeJsonAdapterFactory.of(UserAccountData::class.java, "type", UserAccountDataFallback::class.java)
|
||||||
.registerSubtype(UserAccountDataDirectMessages::class.java, UserAccountData.TYPE_DIRECT_MESSAGES)
|
.registerSubtype(UserAccountDataDirectMessages::class.java, UserAccountData.TYPE_DIRECT_MESSAGES)
|
||||||
|
.registerSubtype(UserAccountDataPushRules::class.java, UserAccountData.TYPE_PUSH_RULES)
|
||||||
)
|
)
|
||||||
.add(RuntimeJsonAdapterFactory.of(MessageContent::class.java, "msgtype", MessageDefaultContent::class.java)
|
.add(RuntimeJsonAdapterFactory.of(MessageContent::class.java, "msgtype", MessageDefaultContent::class.java)
|
||||||
.registerSubtype(MessageTextContent::class.java, MessageType.MSGTYPE_TEXT)
|
.registerSubtype(MessageTextContent::class.java, MessageType.MSGTYPE_TEXT)
|
||||||
|
|
|
@ -18,6 +18,16 @@ package im.vector.matrix.android.internal.di
|
||||||
|
|
||||||
import javax.inject.Qualifier
|
import javax.inject.Qualifier
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to inject the userId
|
||||||
|
*/
|
||||||
@Qualifier
|
@Qualifier
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class UserMd5
|
internal annotation class UserId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to inject the md5 of the userId
|
||||||
|
*/
|
||||||
|
@Qualifier
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class UserMd5
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context
|
||||||
import com.novoda.merlin.Merlin
|
import com.novoda.merlin.Merlin
|
||||||
import com.novoda.merlin.MerlinsBeard
|
import com.novoda.merlin.MerlinsBeard
|
||||||
import im.vector.matrix.android.internal.di.MatrixScope
|
import im.vector.matrix.android.internal.di.MatrixScope
|
||||||
|
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -27,7 +28,9 @@ import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
@MatrixScope
|
@MatrixScope
|
||||||
internal class NetworkConnectivityChecker @Inject constructor(context: Context) {
|
internal class NetworkConnectivityChecker @Inject constructor(context: Context,
|
||||||
|
backgroundDetectionObserver: BackgroundDetectionObserver)
|
||||||
|
: BackgroundDetectionObserver.Listener {
|
||||||
|
|
||||||
private val merlin = Merlin.Builder()
|
private val merlin = Merlin.Builder()
|
||||||
.withConnectableCallbacks()
|
.withConnectableCallbacks()
|
||||||
|
@ -41,7 +44,12 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
backgroundDetectionObserver.register(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMoveToForeground() {
|
||||||
merlin.bind()
|
merlin.bind()
|
||||||
|
|
||||||
merlin.registerDisconnectable {
|
merlin.registerDisconnectable {
|
||||||
if (hasInternetAccess) {
|
if (hasInternetAccess) {
|
||||||
Timber.v("On Disconnect")
|
Timber.v("On Disconnect")
|
||||||
|
@ -64,6 +72,10 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onMoveToBackground() {
|
||||||
|
merlin.unbind()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun waitUntilConnected() {
|
suspend fun waitUntilConnected() {
|
||||||
if (hasInternetAccess) {
|
if (hasInternetAccess) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -20,11 +20,11 @@ import android.content.Context
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import arrow.core.Try
|
import arrow.core.Try
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
|
||||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||||
import im.vector.matrix.android.api.session.file.FileService
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
|
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
|
||||||
|
import im.vector.matrix.android.internal.di.UserMd5
|
||||||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import im.vector.matrix.android.internal.util.md5
|
import im.vector.matrix.android.internal.util.md5
|
||||||
|
@ -40,7 +40,7 @@ import java.io.IOException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultFileService @Inject constructor(private val context: Context,
|
internal class DefaultFileService @Inject constructor(private val context: Context,
|
||||||
private val sessionParams: SessionParams,
|
@UserMd5 private val userMd5: String,
|
||||||
private val contentUrlResolver: ContentUrlResolver,
|
private val contentUrlResolver: ContentUrlResolver,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers) : FileService {
|
private val coroutineDispatchers: MatrixCoroutineDispatchers) : FileService {
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ internal class DefaultFileService @Inject constructor(private val context: Conte
|
||||||
// Create dir tree (MF stands for Matrix File):
|
// Create dir tree (MF stands for Matrix File):
|
||||||
// <cache>/MF/<md5(userId)>/<md5(id)>/
|
// <cache>/MF/<md5(userId)>/<md5(id)>/
|
||||||
val tmpFolderRoot = File(context.cacheDir, "MF")
|
val tmpFolderRoot = File(context.cacheDir, "MF")
|
||||||
val tmpFolderUser = File(tmpFolderRoot, sessionParams.credentials.userId.md5())
|
val tmpFolderUser = File(tmpFolderRoot, userMd5)
|
||||||
File(tmpFolderUser, id.md5())
|
File(tmpFolderUser, id.md5())
|
||||||
}
|
}
|
||||||
FileService.DownloadMode.TO_EXPORT -> {
|
FileService.DownloadMode.TO_EXPORT -> {
|
||||||
|
|
|
@ -67,11 +67,18 @@ internal abstract class SessionModule {
|
||||||
return sessionParams.credentials
|
return sessionParams.credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@UserId
|
||||||
|
@Provides
|
||||||
|
fun providesUserId(credentials: Credentials): String {
|
||||||
|
return credentials.userId
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@UserMd5
|
@UserMd5
|
||||||
@Provides
|
@Provides
|
||||||
fun providesUserMd5(sessionParams: SessionParams): String {
|
fun providesUserMd5(@UserId userId: String): String {
|
||||||
return sessionParams.credentials.userId.md5()
|
return userId.md5()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.session.filter
|
package im.vector.matrix.android.internal.session.filter
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -33,7 +33,7 @@ internal interface SaveFilterTask : Task<SaveFilterTask.Params, Unit> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultSaveFilterTask @Inject constructor(private val sessionParams: SessionParams,
|
internal class DefaultSaveFilterTask @Inject constructor(@UserId private val userId: String,
|
||||||
private val filterAPI: FilterApi,
|
private val filterAPI: FilterApi,
|
||||||
private val filterRepository: FilterRepository
|
private val filterRepository: FilterRepository
|
||||||
) : SaveFilterTask {
|
) : SaveFilterTask {
|
||||||
|
@ -41,7 +41,7 @@ internal class DefaultSaveFilterTask @Inject constructor(private val sessionPara
|
||||||
override suspend fun execute(params: SaveFilterTask.Params) {
|
override suspend fun execute(params: SaveFilterTask.Params) {
|
||||||
val filterResponse = executeRequest<FilterResponse> {
|
val filterResponse = executeRequest<FilterResponse> {
|
||||||
// TODO auto retry
|
// TODO auto retry
|
||||||
apiCall = filterAPI.uploadFilter(sessionParams.credentials.userId, params.filter)
|
apiCall = filterAPI.uploadFilter(userId, params.filter)
|
||||||
}
|
}
|
||||||
filterRepository.storeFilterId(params.filter, filterResponse.filterId)
|
filterRepository.storeFilterId(params.filter, filterResponse.filterId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package im.vector.matrix.android.internal.session.group
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
|
@ -64,8 +65,7 @@ internal class DefaultGetGroupDataTask @Inject constructor(
|
||||||
groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: ""
|
groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: ""
|
||||||
val name = groupSummary.profile?.name
|
val name = groupSummary.profile?.name
|
||||||
groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else name
|
groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else name
|
||||||
groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription
|
groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription ?: ""
|
||||||
?: ""
|
|
||||||
|
|
||||||
val roomIds = groupRooms.rooms.map { it.roomId }
|
val roomIds = groupRooms.rooms.map { it.roomId }
|
||||||
groupSummaryEntity.roomIds.clear()
|
groupSummaryEntity.roomIds.clear()
|
||||||
|
@ -74,8 +74,12 @@ internal class DefaultGetGroupDataTask @Inject constructor(
|
||||||
val userIds = groupUsers.users.map { it.userId }
|
val userIds = groupUsers.users.map { it.userId }
|
||||||
groupSummaryEntity.userIds.clear()
|
groupSummaryEntity.userIds.clear()
|
||||||
groupSummaryEntity.userIds.addAll(userIds)
|
groupSummaryEntity.userIds.addAll(userIds)
|
||||||
|
|
||||||
|
groupSummaryEntity.membership = when (groupSummary.user?.membership) {
|
||||||
|
Membership.JOIN.value -> Membership.JOIN
|
||||||
|
Membership.INVITE.value -> Membership.INVITE
|
||||||
|
else -> Membership.LEAVE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,35 +20,48 @@ import android.content.Context
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||||
import im.vector.matrix.android.internal.database.model.GroupEntity
|
import im.vector.matrix.android.internal.database.model.GroupEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
||||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||||
import io.realm.OrderedCollectionChangeSet
|
import io.realm.OrderedCollectionChangeSet
|
||||||
import io.realm.RealmConfiguration
|
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
||||||
|
|
||||||
internal class GroupSummaryUpdater @Inject constructor(private val context: Context,
|
internal class GroupSummaryUpdater @Inject constructor(private val context: Context,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
@SessionDatabase realmConfiguration: RealmConfiguration)
|
private val monarchy: Monarchy)
|
||||||
: RealmLiveEntityObserver<GroupEntity>(realmConfiguration) {
|
: RealmLiveEntityObserver<GroupEntity>(monarchy.realmConfiguration) {
|
||||||
|
|
||||||
override val query = Monarchy.Query<GroupEntity> { GroupEntity.where(it) }
|
override val query = Monarchy.Query { GroupEntity.where(it) }
|
||||||
|
|
||||||
override fun onChange(results: RealmResults<GroupEntity>, changeSet: OrderedCollectionChangeSet) {
|
override fun onChange(results: RealmResults<GroupEntity>, changeSet: OrderedCollectionChangeSet) {
|
||||||
val newGroupIds = changeSet.insertions
|
// `insertions` for new groups and `changes` to handle left groups
|
||||||
|
val modifiedGroupEntity = (changeSet.insertions + changeSet.changes)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.mapNotNull { results[it]?.groupId}
|
.mapNotNull { results[it] }
|
||||||
.toList()
|
|
||||||
|
fetchGroupsData(modifiedGroupEntity
|
||||||
|
.filter { it.membership == Membership.JOIN || it.membership == Membership.INVITE }
|
||||||
|
.map { it.groupId }
|
||||||
|
.toList())
|
||||||
|
|
||||||
|
deleteGroups(modifiedGroupEntity
|
||||||
|
.filter { it.membership == Membership.LEAVE }
|
||||||
|
.map { it.groupId }
|
||||||
|
.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchGroupsData(groupIds: List<String>) {
|
||||||
|
val getGroupDataWorkerParams = GetGroupDataWorker.Params(userId, groupIds)
|
||||||
|
|
||||||
val getGroupDataWorkerParams = GetGroupDataWorker.Params(credentials.userId, newGroupIds)
|
|
||||||
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
|
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
|
||||||
|
|
||||||
val sendWork = matrixOneTimeWorkRequestBuilder<GetGroupDataWorker>()
|
val sendWork = matrixOneTimeWorkRequestBuilder<GetGroupDataWorker>()
|
||||||
|
@ -61,4 +74,15 @@ internal class GroupSummaryUpdater @Inject constructor(private val context: Cont
|
||||||
.enqueue()
|
.enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the GroupSummaryEntity of left groups
|
||||||
|
*/
|
||||||
|
private fun deleteGroups(groupIds: List<String>) {
|
||||||
|
monarchy
|
||||||
|
.writeAsync { realm ->
|
||||||
|
GroupSummaryEntity.where(realm, groupIds)
|
||||||
|
.findAll()
|
||||||
|
.deleteAllFromRealm()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -17,9 +17,10 @@ package im.vector.matrix.android.internal.session.notification
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
|
||||||
import im.vector.matrix.android.api.pushrules.Action
|
|
||||||
import im.vector.matrix.android.api.pushrules.PushRuleService
|
import im.vector.matrix.android.api.pushrules.PushRuleService
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleKind
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleSetKey
|
||||||
|
import im.vector.matrix.android.api.pushrules.getActions
|
||||||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
@ -35,53 +36,60 @@ import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal class DefaultPushRuleService @Inject constructor(
|
internal class DefaultPushRuleService @Inject constructor(private val getPushRulesTask: GetPushRulesTask,
|
||||||
private val sessionParams: SessionParams,
|
private val updatePushRuleEnableStatusTask: UpdatePushRuleEnableStatusTask,
|
||||||
private val pushRulesTask: GetPushRulesTask,
|
private val taskExecutor: TaskExecutor,
|
||||||
private val updatePushRuleEnableStatusTask: UpdatePushRuleEnableStatusTask,
|
private val monarchy: Monarchy
|
||||||
private val taskExecutor: TaskExecutor,
|
|
||||||
private val monarchy: Monarchy
|
|
||||||
) : PushRuleService {
|
) : PushRuleService {
|
||||||
|
|
||||||
private var listeners = ArrayList<PushRuleService.PushRuleListener>()
|
private var listeners = ArrayList<PushRuleService.PushRuleListener>()
|
||||||
|
|
||||||
override fun fetchPushRules(scope: String) {
|
override fun fetchPushRules(scope: String) {
|
||||||
pushRulesTask
|
getPushRulesTask
|
||||||
.configureWith(GetPushRulesTask.Params(scope))
|
.configureWith(GetPushRulesTask.Params(scope))
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPushRules(scope: String): List<PushRule> {
|
override fun getPushRules(scope: String): List<PushRule> {
|
||||||
|
|
||||||
var contentRules: List<PushRule> = emptyList()
|
var contentRules: List<PushRule> = emptyList()
|
||||||
var overrideRules: List<PushRule> = emptyList()
|
var overrideRules: List<PushRule> = emptyList()
|
||||||
var roomRules: List<PushRule> = emptyList()
|
var roomRules: List<PushRule> = emptyList()
|
||||||
var senderRules: List<PushRule> = emptyList()
|
var senderRules: List<PushRule> = emptyList()
|
||||||
var underrideRules: List<PushRule> = emptyList()
|
var underrideRules: List<PushRule> = emptyList()
|
||||||
|
|
||||||
// TODO Create const for ruleSetKey
|
|
||||||
monarchy.doWithRealm { realm ->
|
monarchy.doWithRealm { realm ->
|
||||||
PushRulesEntity.where(realm, sessionParams.credentials.userId, scope, "content").findFirst()?.let { re ->
|
PushRulesEntity.where(realm, scope, RuleSetKey.CONTENT)
|
||||||
contentRules = re.pushRules.map { PushRulesMapper.mapContentRule(it) }
|
.findFirst()
|
||||||
}
|
?.let { pushRulesEntity ->
|
||||||
PushRulesEntity.where(realm, sessionParams.credentials.userId, scope, "override").findFirst()?.let { re ->
|
contentRules = pushRulesEntity.pushRules.map { PushRulesMapper.mapContentRule(it) }
|
||||||
overrideRules = re.pushRules.map { PushRulesMapper.map(it) }
|
}
|
||||||
}
|
PushRulesEntity.where(realm, scope, RuleSetKey.OVERRIDE)
|
||||||
PushRulesEntity.where(realm, sessionParams.credentials.userId, scope, "room").findFirst()?.let { re ->
|
.findFirst()
|
||||||
roomRules = re.pushRules.map { PushRulesMapper.mapRoomRule(it) }
|
?.let { pushRulesEntity ->
|
||||||
}
|
overrideRules = pushRulesEntity.pushRules.map { PushRulesMapper.map(it) }
|
||||||
PushRulesEntity.where(realm, sessionParams.credentials.userId, scope, "sender").findFirst()?.let { re ->
|
}
|
||||||
senderRules = re.pushRules.map { PushRulesMapper.mapSenderRule(it) }
|
PushRulesEntity.where(realm, scope, RuleSetKey.ROOM)
|
||||||
}
|
.findFirst()
|
||||||
PushRulesEntity.where(realm, sessionParams.credentials.userId, scope, "underride").findFirst()?.let { re ->
|
?.let { pushRulesEntity ->
|
||||||
underrideRules = re.pushRules.map { PushRulesMapper.map(it) }
|
roomRules = pushRulesEntity.pushRules.map { PushRulesMapper.mapRoomRule(it) }
|
||||||
}
|
}
|
||||||
|
PushRulesEntity.where(realm, scope, RuleSetKey.SENDER)
|
||||||
|
.findFirst()
|
||||||
|
?.let { pushRulesEntity ->
|
||||||
|
senderRules = pushRulesEntity.pushRules.map { PushRulesMapper.mapSenderRule(it) }
|
||||||
|
}
|
||||||
|
PushRulesEntity.where(realm, scope, RuleSetKey.UNDERRIDE)
|
||||||
|
.findFirst()
|
||||||
|
?.let { pushRulesEntity ->
|
||||||
|
underrideRules = pushRulesEntity.pushRules.map { PushRulesMapper.map(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return contentRules + overrideRules + roomRules + senderRules + underrideRules
|
// Ref. for the order: https://matrix.org/docs/spec/client_server/latest#push-rules
|
||||||
|
return overrideRules + contentRules + roomRules + senderRules + underrideRules
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updatePushRuleEnableStatus(kind: String, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
return updatePushRuleEnableStatusTask
|
return updatePushRuleEnableStatusTask
|
||||||
.configureWith(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled)) {
|
.configureWith(UpdatePushRuleEnableStatusTask.Params(kind, pushRule, enabled)) {
|
||||||
this.callback = callback
|
this.callback = callback
|
||||||
|
@ -114,8 +122,9 @@ internal class DefaultPushRuleService @Inject constructor(
|
||||||
|
|
||||||
fun dispatchBing(event: Event, rule: PushRule) {
|
fun dispatchBing(event: Event, rule: PushRule) {
|
||||||
try {
|
try {
|
||||||
|
val actionsList = rule.getActions()
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onMatchRule(event, Action.mapFrom(rule) ?: emptyList())
|
it.onMatchRule(event, actionsList)
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Timber.e(e, "Error while dispatching bing")
|
Timber.e(e, "Error while dispatching bing")
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.session.notification
|
package im.vector.matrix.android.internal.session.notification
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
|
||||||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
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.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.pushers.DefaultConditionResolver
|
import im.vector.matrix.android.internal.session.pushers.DefaultConditionResolver
|
||||||
import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
@ -37,7 +37,7 @@ internal interface ProcessEventForPushTask : Task<ProcessEventForPushTask.Params
|
||||||
internal class DefaultProcessEventForPushTask @Inject constructor(
|
internal class DefaultProcessEventForPushTask @Inject constructor(
|
||||||
private val defaultPushRuleService: DefaultPushRuleService,
|
private val defaultPushRuleService: DefaultPushRuleService,
|
||||||
private val roomService: RoomService,
|
private val roomService: RoomService,
|
||||||
private val sessionParams: SessionParams
|
@UserId private val userId: String
|
||||||
) : ProcessEventForPushTask {
|
) : ProcessEventForPushTask {
|
||||||
|
|
||||||
override suspend fun execute(params: ProcessEventForPushTask.Params) {
|
override suspend fun execute(params: ProcessEventForPushTask.Params) {
|
||||||
|
@ -68,7 +68,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}.filter {
|
}.filter {
|
||||||
it.senderId != sessionParams.credentials.userId
|
it.senderId != userId
|
||||||
}
|
}
|
||||||
Timber.v("[PushRules] Found ${allEvents.size} out of ${(newJoinEvents + inviteEvents).size}" +
|
Timber.v("[PushRules] Found ${allEvents.size} out of ${(newJoinEvents + inviteEvents).size}" +
|
||||||
" to check for push rules with ${params.rules.size} rules")
|
" to check for push rules with ${params.rules.size} rules")
|
||||||
|
@ -101,7 +101,8 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fulfilledBingRule(event: Event, rules: List<PushRule>): PushRule? {
|
private fun fulfilledBingRule(event: Event, rules: List<PushRule>): PushRule? {
|
||||||
val conditionResolver = DefaultConditionResolver(event, roomService, sessionParams)
|
// TODO This should be injected
|
||||||
|
val conditionResolver = DefaultConditionResolver(event, roomService, userId)
|
||||||
rules.filter { it.enabled }.forEach { rule ->
|
rules.filter { it.enabled }.forEach { rule ->
|
||||||
val isFullfilled = rule.conditions?.map {
|
val isFullfilled = rule.conditions?.map {
|
||||||
it.asExecutableCondition()?.isSatisfied(conditionResolver) ?: false
|
it.asExecutableCondition()?.isSatisfied(conditionResolver) ?: false
|
||||||
|
|
|
@ -57,14 +57,14 @@ internal class AddHttpPusherWorker(context: Context, params: WorkerParameters)
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
return try {
|
return try {
|
||||||
setPusher(pusher, params.userId)
|
setPusher(pusher)
|
||||||
Result.success()
|
Result.success()
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
when (exception) {
|
when (exception) {
|
||||||
is Failure.NetworkConnection -> Result.retry()
|
is Failure.NetworkConnection -> Result.retry()
|
||||||
else -> {
|
else -> {
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
PusherEntity.where(realm, params.userId, pusher.pushKey).findFirst()?.let {
|
PusherEntity.where(realm, pusher.pushKey).findFirst()?.let {
|
||||||
//update it
|
//update it
|
||||||
it.state = PusherState.FAILED_TO_REGISTER
|
it.state = PusherState.FAILED_TO_REGISTER
|
||||||
}
|
}
|
||||||
|
@ -76,12 +76,12 @@ internal class AddHttpPusherWorker(context: Context, params: WorkerParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun setPusher(pusher: JsonPusher, userId: String) {
|
private suspend fun setPusher(pusher: JsonPusher) {
|
||||||
executeRequest<Unit> {
|
executeRequest<Unit> {
|
||||||
apiCall = pushersAPI.setPusher(pusher)
|
apiCall = pushersAPI.setPusher(pusher)
|
||||||
}
|
}
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
val echo = PusherEntity.where(realm, userId, pusher.pushKey).findFirst()
|
val echo = PusherEntity.where(realm, pusher.pushKey).findFirst()
|
||||||
if (echo != null) {
|
if (echo != null) {
|
||||||
//update it
|
//update it
|
||||||
echo.appDisplayName = pusher.appDisplayName
|
echo.appDisplayName = pusher.appDisplayName
|
||||||
|
@ -93,7 +93,7 @@ internal class AddHttpPusherWorker(context: Context, params: WorkerParameters)
|
||||||
echo.data?.url = pusher.data?.url
|
echo.data?.url = pusher.data?.url
|
||||||
echo.state = PusherState.REGISTERED
|
echo.state = PusherState.REGISTERED
|
||||||
} else {
|
} else {
|
||||||
pusher.toEntity(userId).also {
|
pusher.toEntity().also {
|
||||||
it.state = PusherState.REGISTERED
|
it.state = PusherState.REGISTERED
|
||||||
realm.insertOrUpdate(it)
|
realm.insertOrUpdate(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.session.pushers
|
package im.vector.matrix.android.internal.session.pushers
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
|
||||||
import im.vector.matrix.android.api.pushrules.*
|
import im.vector.matrix.android.api.pushrules.*
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
// TODO Inject constructor
|
||||||
internal class DefaultConditionResolver(private val event: Event,
|
internal class DefaultConditionResolver(private val event: Event,
|
||||||
private val roomService: RoomService,
|
private val roomService: RoomService,
|
||||||
private val sessionParams: SessionParams) : ConditionResolver {
|
@UserId private val userId: String) : ConditionResolver {
|
||||||
|
|
||||||
|
|
||||||
override fun resolveEventMatchCondition(eventMatchCondition: EventMatchCondition): Boolean {
|
override fun resolveEventMatchCondition(eventMatchCondition: EventMatchCondition): Boolean {
|
||||||
|
@ -45,8 +46,7 @@ internal class DefaultConditionResolver(private val event: Event,
|
||||||
override fun resolveContainsDisplayNameCondition(containsDisplayNameCondition: ContainsDisplayNameCondition): Boolean {
|
override fun resolveContainsDisplayNameCondition(containsDisplayNameCondition: ContainsDisplayNameCondition): Boolean {
|
||||||
val roomId = event.roomId ?: return false
|
val roomId = event.roomId ?: return false
|
||||||
val room = roomService.getRoom(roomId) ?: return false
|
val room = roomService.getRoom(roomId) ?: return false
|
||||||
val myDisplayName = room.getRoomMember(sessionParams.credentials.userId)?.displayName
|
val myDisplayName = room.getRoomMember(userId)?.displayName ?: return false
|
||||||
?: return false
|
|
||||||
return containsDisplayNameCondition.isSatisfied(event, myDisplayName)
|
return containsDisplayNameCondition.isSatisfied(event, myDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,29 +21,28 @@ import androidx.work.BackoffPolicy
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
|
||||||
import im.vector.matrix.android.api.session.pushers.Pusher
|
import im.vector.matrix.android.api.session.pushers.Pusher
|
||||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||||
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.PusherEntity
|
import im.vector.matrix.android.internal.database.model.PusherEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
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.worker.WorkManagerUtil
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
||||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||||
import java.util.UUID
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
internal class DefaultPusherService @Inject constructor(
|
internal class DefaultPusherService @Inject constructor(private val context: Context,
|
||||||
private val context: Context,
|
private val monarchy: Monarchy,
|
||||||
private val monarchy: Monarchy,
|
@UserId private val userId: String,
|
||||||
private val sessionParam: SessionParams,
|
private val getPusherTask: GetPushersTask,
|
||||||
private val getPusherTask: GetPushersTask,
|
private val removePusherTask: RemovePusherTask,
|
||||||
private val removePusherTask: RemovePusherTask,
|
private val taskExecutor: TaskExecutor
|
||||||
private val taskExecutor: TaskExecutor
|
|
||||||
) : PushersService {
|
) : PushersService {
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +69,7 @@ internal class DefaultPusherService @Inject constructor(
|
||||||
append = append)
|
append = append)
|
||||||
|
|
||||||
|
|
||||||
val params = AddHttpPusherWorker.Params(pusher, sessionParam.credentials.userId)
|
val params = AddHttpPusherWorker.Params(pusher, userId)
|
||||||
|
|
||||||
val request = matrixOneTimeWorkRequestBuilder<AddHttpPusherWorker>()
|
val request = matrixOneTimeWorkRequestBuilder<AddHttpPusherWorker>()
|
||||||
.setConstraints(WorkManagerUtil.workConstraints)
|
.setConstraints(WorkManagerUtil.workConstraints)
|
||||||
|
@ -82,7 +81,7 @@ internal class DefaultPusherService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>) {
|
override fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>) {
|
||||||
val params = RemovePusherTask.Params(sessionParam.credentials.userId, pushkey, appId)
|
val params = RemovePusherTask.Params(pushkey, appId)
|
||||||
removePusherTask
|
removePusherTask
|
||||||
.configureWith(params) {
|
.configureWith(params) {
|
||||||
this.callback = callback
|
this.callback = callback
|
||||||
|
@ -93,12 +92,12 @@ internal class DefaultPusherService @Inject constructor(
|
||||||
|
|
||||||
override fun livePushers(): LiveData<List<Pusher>> {
|
override fun livePushers(): LiveData<List<Pusher>> {
|
||||||
return monarchy.findAllMappedWithChanges(
|
return monarchy.findAllMappedWithChanges(
|
||||||
{ realm -> PusherEntity.where(realm, sessionParam.credentials.userId) },
|
{ realm -> PusherEntity.where(realm) },
|
||||||
{ it.asDomain() }
|
{ it.asDomain() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pushers(): List<Pusher> {
|
override fun pushers(): List<Pusher> {
|
||||||
return monarchy.fetchAllCopiedSync { PusherEntity.where(it, sessionParam.credentials.userId) }.map { it.asDomain() }
|
return monarchy.fetchAllCopiedSync { PusherEntity.where(it) }.map { it.asDomain() }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,80 +15,27 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.session.pushers
|
package im.vector.matrix.android.internal.session.pushers
|
||||||
|
|
||||||
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.awaitTransaction
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
internal interface GetPushRulesTask : Task<GetPushRulesTask.Params, Unit> {
|
internal interface GetPushRulesTask : Task<GetPushRulesTask.Params, Unit> {
|
||||||
|
|
||||||
data class Params(val scope: String)
|
data class Params(val scope: String)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We keep this task, but it should not be used anymore, the push rules comes from the sync response
|
||||||
|
*/
|
||||||
internal class DefaultGetPushRulesTask @Inject constructor(private val pushRulesApi: PushRulesApi,
|
internal class DefaultGetPushRulesTask @Inject constructor(private val pushRulesApi: PushRulesApi,
|
||||||
private val monarchy: Monarchy,
|
private val savePushRulesTask: SavePushRulesTask) : GetPushRulesTask {
|
||||||
private val sessionParams: SessionParams) : GetPushRulesTask {
|
|
||||||
|
|
||||||
override suspend fun execute(params: GetPushRulesTask.Params) {
|
override suspend fun execute(params: GetPushRulesTask.Params) {
|
||||||
val response = executeRequest<GetPushRulesResponse> {
|
val response = executeRequest<GetPushRulesResponse> {
|
||||||
apiCall = pushRulesApi.getAllRules()
|
apiCall = pushRulesApi.getAllRules()
|
||||||
}
|
}
|
||||||
val scope = params.scope
|
|
||||||
monarchy.awaitTransaction { 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")
|
savePushRulesTask.execute(SavePushRulesTask.Params(response))
|
||||||
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,11 +16,9 @@
|
||||||
package im.vector.matrix.android.internal.session.pushers
|
package im.vector.matrix.android.internal.session.pushers
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
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.api.session.pushers.PusherState
|
||||||
import im.vector.matrix.android.internal.database.mapper.toEntity
|
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.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.awaitTransaction
|
import im.vector.matrix.android.internal.util.awaitTransaction
|
||||||
|
@ -29,8 +27,7 @@ import javax.inject.Inject
|
||||||
internal interface GetPushersTask : Task<Unit, Unit>
|
internal interface GetPushersTask : Task<Unit, Unit>
|
||||||
|
|
||||||
internal class DefaultGetPusherTask @Inject constructor(private val pushersAPI: PushersAPI,
|
internal class DefaultGetPusherTask @Inject constructor(private val pushersAPI: PushersAPI,
|
||||||
private val monarchy: Monarchy,
|
private val monarchy: Monarchy) : GetPushersTask {
|
||||||
private val sessionParams: SessionParams) : GetPushersTask {
|
|
||||||
|
|
||||||
override suspend fun execute(params: Unit) {
|
override suspend fun execute(params: Unit) {
|
||||||
val response = executeRequest<GetPushersResponse> {
|
val response = executeRequest<GetPushersResponse> {
|
||||||
|
@ -39,10 +36,9 @@ internal class DefaultGetPusherTask @Inject constructor(private val pushersAPI:
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
//clear existings?
|
//clear existings?
|
||||||
realm.where(PusherEntity::class.java)
|
realm.where(PusherEntity::class.java)
|
||||||
.equalTo(PusherEntityFields.USER_ID, sessionParams.credentials.userId)
|
|
||||||
.findAll().deleteAllFromRealm()
|
.findAll().deleteAllFromRealm()
|
||||||
response.pushers?.forEach { jsonPusher ->
|
response.pushers?.forEach { jsonPusher ->
|
||||||
jsonPusher.toEntity(sessionParams.credentials.userId).also {
|
jsonPusher.toEntity().also {
|
||||||
it.state = PusherState.REGISTERED
|
it.state = PusherState.REGISTERED
|
||||||
realm.insertOrUpdate(it)
|
realm.insertOrUpdate(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,9 @@ internal abstract class PushersModule {
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindGetPushRulesTask(getPushRulesTask: DefaultGetPushRulesTask): GetPushRulesTask
|
abstract fun bindGetPushRulesTask(getPushRulesTask: DefaultGetPushRulesTask): GetPushRulesTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindSavePushRulesTask(savePushRulesTask: DefaultSavePushRulesTask): SavePushRulesTask
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindRemovePusherTask(removePusherTask: DefaultRemovePusherTask): RemovePusherTask
|
abstract fun bindRemovePusherTask(removePusherTask: DefaultRemovePusherTask): RemovePusherTask
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,7 @@ import io.realm.Realm
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface RemovePusherTask : Task<RemovePusherTask.Params, Unit> {
|
internal interface RemovePusherTask : Task<RemovePusherTask.Params, Unit> {
|
||||||
data class Params(val userId: String,
|
data class Params(val pushKey: String,
|
||||||
val pushKey: String,
|
|
||||||
val pushAppId: String)
|
val pushAppId: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,12 +39,12 @@ internal class DefaultRemovePusherTask @Inject constructor(
|
||||||
|
|
||||||
override suspend fun execute(params: RemovePusherTask.Params) {
|
override suspend fun execute(params: RemovePusherTask.Params) {
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
val existingEntity = PusherEntity.where(realm, params.userId, params.pushKey).findFirst()
|
val existingEntity = PusherEntity.where(realm, params.pushKey).findFirst()
|
||||||
existingEntity?.state = PusherState.UNREGISTERING
|
existingEntity?.state = PusherState.UNREGISTERING
|
||||||
}
|
}
|
||||||
|
|
||||||
val existing = Realm.getInstance(monarchy.realmConfiguration).use { realm ->
|
val existing = Realm.getInstance(monarchy.realmConfiguration).use { realm ->
|
||||||
PusherEntity.where(realm, params.userId, params.pushKey).findFirst()?.asDomain()
|
PusherEntity.where(realm, params.pushKey).findFirst()?.asDomain()
|
||||||
} ?: throw Exception("No existing pusher")
|
} ?: throw Exception("No existing pusher")
|
||||||
|
|
||||||
val deleteBody = JsonPusher(
|
val deleteBody = JsonPusher(
|
||||||
|
@ -64,7 +63,7 @@ internal class DefaultRemovePusherTask @Inject constructor(
|
||||||
apiCall = pushersAPI.setPusher(deleteBody)
|
apiCall = pushersAPI.setPusher(deleteBody)
|
||||||
}
|
}
|
||||||
monarchy.awaitTransaction {
|
monarchy.awaitTransaction {
|
||||||
PusherEntity.where(it, params.userId, params.pushKey).findFirst()?.deleteFromRealm()
|
PusherEntity.where(it, params.pushKey).findFirst()?.deleteFromRealm()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* 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 im.vector.matrix.android.internal.session.pushers
|
||||||
|
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleScope
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleSetKey
|
||||||
|
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.task.Task
|
||||||
|
import im.vector.matrix.android.internal.util.awaitTransaction
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the push rules in DB
|
||||||
|
*/
|
||||||
|
internal interface SavePushRulesTask : Task<SavePushRulesTask.Params, Unit> {
|
||||||
|
data class Params(val pushRules: GetPushRulesResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultSavePushRulesTask @Inject constructor(private val monarchy: Monarchy) : SavePushRulesTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: SavePushRulesTask.Params) {
|
||||||
|
monarchy.awaitTransaction { realm ->
|
||||||
|
// clear current push rules
|
||||||
|
realm.where(PushRulesEntity::class.java)
|
||||||
|
.findAll()
|
||||||
|
.deleteAllFromRealm()
|
||||||
|
|
||||||
|
// Save only global rules for the moment
|
||||||
|
val globalRules = params.pushRules.global
|
||||||
|
|
||||||
|
val content = PushRulesEntity(RuleScope.GLOBAL).apply { kind = RuleSetKey.CONTENT }
|
||||||
|
globalRules.content?.forEach { rule ->
|
||||||
|
content.pushRules.add(PushRulesMapper.map(rule))
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(content)
|
||||||
|
|
||||||
|
val override = PushRulesEntity(RuleScope.GLOBAL).apply { kind = RuleSetKey.OVERRIDE }
|
||||||
|
globalRules.override?.forEach { rule ->
|
||||||
|
PushRulesMapper.map(rule).also {
|
||||||
|
override.pushRules.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(override)
|
||||||
|
|
||||||
|
val rooms = PushRulesEntity(RuleScope.GLOBAL).apply { kind = RuleSetKey.ROOM }
|
||||||
|
globalRules.room?.forEach { rule ->
|
||||||
|
rooms.pushRules.add(PushRulesMapper.map(rule))
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(rooms)
|
||||||
|
|
||||||
|
val senders = PushRulesEntity(RuleScope.GLOBAL).apply { kind = RuleSetKey.SENDER }
|
||||||
|
globalRules.sender?.forEach { rule ->
|
||||||
|
senders.pushRules.add(PushRulesMapper.map(rule))
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(senders)
|
||||||
|
|
||||||
|
val underrides = PushRulesEntity(RuleScope.GLOBAL).apply { kind = RuleSetKey.UNDERRIDE }
|
||||||
|
globalRules.underride?.forEach { rule ->
|
||||||
|
underrides.pushRules.add(PushRulesMapper.map(rule))
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(underrides)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.session.pushers
|
package im.vector.matrix.android.internal.session.pushers
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleKind
|
||||||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
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
|
||||||
|
@ -22,7 +23,7 @@ import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
internal interface UpdatePushRuleEnableStatusTask : Task<UpdatePushRuleEnableStatusTask.Params, Unit> {
|
internal interface UpdatePushRuleEnableStatusTask : Task<UpdatePushRuleEnableStatusTask.Params, Unit> {
|
||||||
data class Params(val kind: String,
|
data class Params(val kind: RuleKind,
|
||||||
val pushRule: PushRule,
|
val pushRule: PushRule,
|
||||||
val enabled: Boolean)
|
val enabled: Boolean)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +33,7 @@ internal class DefaultUpdatePushRuleEnableStatusTask @Inject constructor(private
|
||||||
|
|
||||||
override suspend fun execute(params: UpdatePushRuleEnableStatusTask.Params) {
|
override suspend fun execute(params: UpdatePushRuleEnableStatusTask.Params) {
|
||||||
return executeRequest {
|
return executeRequest {
|
||||||
apiCall = pushRulesApi.updateEnableRuleStatus(params.kind, params.pushRule.ruleId, params.enabled)
|
apiCall = pushRulesApi.updateEnableRuleStatus(params.kind.value, params.pushRule.ruleId, params.enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,13 +16,13 @@
|
||||||
package im.vector.matrix.android.internal.session.room
|
package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
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.internal.database.RealmLiveEntityObserver
|
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||||
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.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.types
|
import im.vector.matrix.android.internal.database.query.types
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
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 io.realm.OrderedCollectionChangeSet
|
import io.realm.OrderedCollectionChangeSet
|
||||||
|
@ -38,7 +38,7 @@ import javax.inject.Inject
|
||||||
*/
|
*/
|
||||||
|
|
||||||
internal class EventRelationsAggregationUpdater @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
|
internal class EventRelationsAggregationUpdater @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val task: EventRelationsAggregationTask,
|
private val task: EventRelationsAggregationTask,
|
||||||
private val taskExecutor: TaskExecutor) :
|
private val taskExecutor: TaskExecutor) :
|
||||||
RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
|
RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
|
||||||
|
@ -61,7 +61,7 @@ internal class EventRelationsAggregationUpdater @Inject constructor(@SessionData
|
||||||
.toList()
|
.toList()
|
||||||
val params = EventRelationsAggregationTask.Params(
|
val params = EventRelationsAggregationTask.Params(
|
||||||
insertedDomains,
|
insertedDomains,
|
||||||
credentials.userId
|
userId
|
||||||
)
|
)
|
||||||
task.configureWith(params).executeBy(taskExecutor)
|
task.configureWith(params).executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package im.vector.matrix.android.internal.session.room
|
package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
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
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomAvatarContent
|
import im.vector.matrix.android.api.session.room.model.RoomAvatarContent
|
||||||
|
@ -27,11 +26,12 @@ 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.EventEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.prev
|
import im.vector.matrix.android.internal.database.query.prev
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class RoomAvatarResolver @Inject constructor(private val monarchy: Monarchy,
|
internal class RoomAvatarResolver @Inject constructor(private val monarchy: Monarchy,
|
||||||
private val credentials: Credentials) {
|
@UserId private val userId: String) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the room avatar url
|
* Compute the room avatar url
|
||||||
|
@ -52,7 +52,7 @@ internal class RoomAvatarResolver @Inject constructor(private val monarchy: Mona
|
||||||
if (members.size == 1) {
|
if (members.size == 1) {
|
||||||
res = members.firstOrNull()?.toRoomMember()?.avatarUrl
|
res = members.firstOrNull()?.toRoomMember()?.avatarUrl
|
||||||
} else if (members.size == 2) {
|
} else if (members.size == 2) {
|
||||||
val firstOtherMember = members.where().notEqualTo(EventEntityFields.STATE_KEY, credentials.userId).findFirst()
|
val firstOtherMember = members.where().notEqualTo(EventEntityFields.STATE_KEY, userId).findFirst()
|
||||||
res = firstOtherMember?.toRoomMember()?.avatarUrl
|
res = firstOtherMember?.toRoomMember()?.avatarUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package im.vector.matrix.android.internal.session.room
|
package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
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
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
|
@ -31,6 +30,7 @@ import im.vector.matrix.android.internal.database.query.isEventRead
|
||||||
import im.vector.matrix.android.internal.database.query.latestEvent
|
import im.vector.matrix.android.internal.database.query.latestEvent
|
||||||
import im.vector.matrix.android.internal.database.query.prev
|
import im.vector.matrix.android.internal.database.query.prev
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
|
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
|
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
|
||||||
|
@ -39,7 +39,7 @@ import io.realm.Realm
|
||||||
import io.realm.kotlin.createObject
|
import io.realm.kotlin.createObject
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class RoomSummaryUpdater @Inject constructor(private val credentials: Credentials,
|
internal class RoomSummaryUpdater @Inject constructor(@UserId private val userId: String,
|
||||||
private val roomDisplayNameResolver: RoomDisplayNameResolver,
|
private val roomDisplayNameResolver: RoomDisplayNameResolver,
|
||||||
private val roomAvatarResolver: RoomAvatarResolver,
|
private val roomAvatarResolver: RoomAvatarResolver,
|
||||||
private val monarchy: Monarchy) {
|
private val monarchy: Monarchy) {
|
||||||
|
@ -92,11 +92,11 @@ internal class RoomSummaryUpdater @Inject constructor(private val credentials: C
|
||||||
|
|
||||||
roomSummaryEntity.hasUnreadMessages = roomSummaryEntity.notificationCount > 0
|
roomSummaryEntity.hasUnreadMessages = roomSummaryEntity.notificationCount > 0
|
||||||
//avoid this call if we are sure there are unread events
|
//avoid this call if we are sure there are unread events
|
||||||
|| !isEventRead(monarchy, credentials.userId, roomId, latestPreviewableEvent?.eventId)
|
|| !isEventRead(monarchy, userId, roomId, latestPreviewableEvent?.eventId)
|
||||||
|
|
||||||
val otherRoomMembers = RoomMembers(realm, roomId)
|
val otherRoomMembers = RoomMembers(realm, roomId)
|
||||||
.queryRoomMembersEvent()
|
.queryRoomMembersEvent()
|
||||||
.notEqualTo(EventEntityFields.STATE_KEY, credentials.userId)
|
.notEqualTo(EventEntityFields.STATE_KEY, userId)
|
||||||
.findAll()
|
.findAll()
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.map { it.stateKey }
|
.map { it.stateKey }
|
||||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.session.room.membership
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.R
|
import im.vector.matrix.android.R
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
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
|
||||||
import im.vector.matrix.android.api.session.room.model.*
|
import im.vector.matrix.android.api.session.room.model.*
|
||||||
|
@ -30,6 +29,7 @@ import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.prev
|
import im.vector.matrix.android.internal.database.query.prev
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +37,7 @@ import javax.inject.Inject
|
||||||
*/
|
*/
|
||||||
internal class RoomDisplayNameResolver @Inject constructor(private val context: Context,
|
internal class RoomDisplayNameResolver @Inject constructor(private val context: Context,
|
||||||
private val monarchy: Monarchy,
|
private val monarchy: Monarchy,
|
||||||
private val credentials: Credentials
|
@UserId private val userId: String
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +79,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
||||||
|
|
||||||
|
|
||||||
if (roomEntity?.membership == Membership.INVITE) {
|
if (roomEntity?.membership == Membership.INVITE) {
|
||||||
val inviteMeEvent = roomMembers.queryRoomMemberEvent(credentials.userId).findFirst()
|
val inviteMeEvent = roomMembers.queryRoomMemberEvent(userId).findFirst()
|
||||||
val inviterId = inviteMeEvent?.sender
|
val inviterId = inviteMeEvent?.sender
|
||||||
name = if (inviterId != null) {
|
name = if (inviterId != null) {
|
||||||
val inviterMemberEvent = loadedMembers.where()
|
val inviterMemberEvent = loadedMembers.where()
|
||||||
|
@ -97,7 +97,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loadedMembers.where()
|
loadedMembers.where()
|
||||||
.notEqualTo(EventEntityFields.STATE_KEY, credentials.userId)
|
.notEqualTo(EventEntityFields.STATE_KEY, userId)
|
||||||
.limit(3)
|
.limit(3)
|
||||||
.findAll()
|
.findAll()
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,13 @@
|
||||||
package im.vector.matrix.android.internal.session.room.prune
|
package im.vector.matrix.android.internal.session.room.prune
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
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.internal.database.RealmLiveEntityObserver
|
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||||
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.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.types
|
import im.vector.matrix.android.internal.database.query.types
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
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 io.realm.OrderedCollectionChangeSet
|
import io.realm.OrderedCollectionChangeSet
|
||||||
|
@ -37,7 +37,7 @@ import javax.inject.Inject
|
||||||
* As it will actually delete the content, it should be called last in the list of listener.
|
* As it will actually delete the content, it should be called last in the list of listener.
|
||||||
*/
|
*/
|
||||||
internal class EventsPruner @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
|
internal class EventsPruner @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val pruneEventTask: PruneEventTask,
|
private val pruneEventTask: PruneEventTask,
|
||||||
private val taskExecutor: TaskExecutor) :
|
private val taskExecutor: TaskExecutor) :
|
||||||
RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
|
RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
|
||||||
|
@ -54,7 +54,7 @@ internal class EventsPruner @Inject constructor(@SessionDatabase realmConfigurat
|
||||||
|
|
||||||
val params = PruneEventTask.Params(
|
val params = PruneEventTask.Params(
|
||||||
insertedDomains,
|
insertedDomains,
|
||||||
credentials.userId
|
userId
|
||||||
)
|
)
|
||||||
pruneEventTask.configureWith(params).executeBy(taskExecutor)
|
pruneEventTask.configureWith(params).executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
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.session.room.model.ReadReceipt
|
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
||||||
import im.vector.matrix.android.api.session.room.read.ReadService
|
import im.vector.matrix.android.api.session.room.read.ReadService
|
||||||
import im.vector.matrix.android.api.util.Optional
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
@ -33,6 +32,7 @@ import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
|
||||||
import im.vector.matrix.android.internal.database.model.ReadReceiptsSummaryEntity
|
import im.vector.matrix.android.internal.database.model.ReadReceiptsSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.isEventRead
|
import im.vector.matrix.android.internal.database.query.isEventRead
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
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
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ internal class DefaultReadService @AssistedInject constructor(@Assisted private
|
||||||
private val taskExecutor: TaskExecutor,
|
private val taskExecutor: TaskExecutor,
|
||||||
private val setReadMarkersTask: SetReadMarkersTask,
|
private val setReadMarkersTask: SetReadMarkersTask,
|
||||||
private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper,
|
private val readReceiptsSummaryMapper: ReadReceiptsSummaryMapper,
|
||||||
private val credentials: Credentials
|
@UserId private val userId: String
|
||||||
) : ReadService {
|
) : ReadService {
|
||||||
|
|
||||||
@AssistedInject.Factory
|
@AssistedInject.Factory
|
||||||
|
@ -78,7 +78,7 @@ internal class DefaultReadService @AssistedInject constructor(@Assisted private
|
||||||
|
|
||||||
|
|
||||||
override fun isEventRead(eventId: String): Boolean {
|
override fun isEventRead(eventId: String): Boolean {
|
||||||
return isEventRead(monarchy, credentials.userId, roomId, eventId)
|
return isEventRead(monarchy, userId, roomId, eventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getReadMarkerLive(): LiveData<Optional<String>> {
|
override fun getReadMarkerLive(): LiveData<Optional<String>> {
|
||||||
|
@ -92,7 +92,7 @@ internal class DefaultReadService @AssistedInject constructor(@Assisted private
|
||||||
|
|
||||||
override fun getMyReadReceiptLive(): LiveData<Optional<String>> {
|
override fun getMyReadReceiptLive(): LiveData<Optional<String>> {
|
||||||
val liveRealmData = RealmLiveData(monarchy.realmConfiguration) { realm ->
|
val liveRealmData = RealmLiveData(monarchy.realmConfiguration) { realm ->
|
||||||
ReadReceiptEntity.where(realm, roomId = roomId, userId = credentials.userId)
|
ReadReceiptEntity.where(realm, roomId = roomId, userId = userId)
|
||||||
}
|
}
|
||||||
return Transformations.map(liveRealmData) { results ->
|
return Transformations.map(liveRealmData) { results ->
|
||||||
Optional.from(results.firstOrNull()?.eventId)
|
Optional.from(results.firstOrNull()?.eventId)
|
||||||
|
|
|
@ -17,16 +17,15 @@
|
||||||
package im.vector.matrix.android.internal.session.room.read
|
package im.vector.matrix.android.internal.session.room.read
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.database.model.ReadMarkerEntity
|
import im.vector.matrix.android.internal.database.model.ReadMarkerEntity
|
||||||
import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
|
import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.find
|
import im.vector.matrix.android.internal.database.query.*
|
||||||
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
|
||||||
import im.vector.matrix.android.internal.database.query.latestEvent
|
import im.vector.matrix.android.internal.database.query.latestEvent
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.session.room.RoomAPI
|
import im.vector.matrix.android.internal.session.room.RoomAPI
|
||||||
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
|
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
|
||||||
|
@ -52,11 +51,11 @@ private const val READ_MARKER = "m.fully_read"
|
||||||
private const val READ_RECEIPT = "m.read"
|
private const val READ_RECEIPT = "m.read"
|
||||||
|
|
||||||
internal class DefaultSetReadMarkersTask @Inject constructor(private val roomAPI: RoomAPI,
|
internal class DefaultSetReadMarkersTask @Inject constructor(private val roomAPI: RoomAPI,
|
||||||
private val credentials: Credentials,
|
|
||||||
private val monarchy: Monarchy,
|
private val monarchy: Monarchy,
|
||||||
private val roomFullyReadHandler: RoomFullyReadHandler,
|
private val roomFullyReadHandler: RoomFullyReadHandler,
|
||||||
private val readReceiptHandler: ReadReceiptHandler
|
private val readReceiptHandler: ReadReceiptHandler,
|
||||||
) : SetReadMarkersTask {
|
@UserId private val userId: String)
|
||||||
|
: SetReadMarkersTask {
|
||||||
|
|
||||||
override suspend fun execute(params: SetReadMarkersTask.Params) {
|
override suspend fun execute(params: SetReadMarkersTask.Params) {
|
||||||
val markers = HashMap<String, String>()
|
val markers = HashMap<String, String>()
|
||||||
|
@ -84,7 +83,7 @@ internal class DefaultSetReadMarkersTask @Inject constructor(private val roomAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readReceiptEventId != null
|
if (readReceiptEventId != null
|
||||||
&& !isEventRead(params.roomId, readReceiptEventId)) {
|
&& !isEventRead(monarchy, userId, params.roomId, readReceiptEventId)) {
|
||||||
if (LocalEchoEventFactory.isLocalEchoId(readReceiptEventId)) {
|
if (LocalEchoEventFactory.isLocalEchoId(readReceiptEventId)) {
|
||||||
Timber.w("Can't set read receipt for local event $readReceiptEventId")
|
Timber.w("Can't set read receipt for local event $readReceiptEventId")
|
||||||
} else {
|
} else {
|
||||||
|
@ -108,12 +107,12 @@ internal class DefaultSetReadMarkersTask @Inject constructor(private val roomAPI
|
||||||
roomFullyReadHandler.handle(realm, roomId, FullyReadContent(readMarkerId))
|
roomFullyReadHandler.handle(realm, roomId, FullyReadContent(readMarkerId))
|
||||||
}
|
}
|
||||||
if (readReceiptId != null) {
|
if (readReceiptId != null) {
|
||||||
val readReceiptContent = ReadReceiptHandler.createContent(credentials.userId, readReceiptId)
|
val readReceiptContent = ReadReceiptHandler.createContent(userId, readReceiptId)
|
||||||
readReceiptHandler.handle(realm, roomId, readReceiptContent, false)
|
readReceiptHandler.handle(realm, roomId, readReceiptContent, false)
|
||||||
val isLatestReceived = TimelineEventEntity.latestEvent(realm, roomId = roomId, includesSending = false)?.eventId == readReceiptId
|
val isLatestReceived = TimelineEventEntity.latestEvent(realm, roomId = roomId, includesSending = false)?.eventId == readReceiptId
|
||||||
if (isLatestReceived) {
|
if (isLatestReceived) {
|
||||||
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
|
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
|
||||||
?: return@awaitTransaction
|
?: return@awaitTransaction
|
||||||
roomSummary.notificationCount = 0
|
roomSummary.notificationCount = 0
|
||||||
roomSummary.highlightCount = 0
|
roomSummary.highlightCount = 0
|
||||||
roomSummary.hasUnreadMessages = false
|
roomSummary.hasUnreadMessages = false
|
||||||
|
@ -133,19 +132,4 @@ internal class DefaultSetReadMarkersTask @Inject constructor(private val roomAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isEventRead(roomId: String, eventId: String): Boolean {
|
|
||||||
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
|
|
||||||
val readReceipt = ReadReceiptEntity.where(realm, roomId, credentials.userId).findFirst()
|
|
||||||
?: return false
|
|
||||||
val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
|
|
||||||
?: return false
|
|
||||||
val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.root?.displayIndex
|
|
||||||
?: Int.MIN_VALUE
|
|
||||||
val eventToCheckIndex = liveChunk.timelineEvents.find(eventId)?.root?.displayIndex
|
|
||||||
?: Int.MAX_VALUE
|
|
||||||
eventToCheckIndex <= readReceiptIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,7 +23,6 @@ import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
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.session.crypto.CryptoService
|
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||||
|
@ -37,6 +36,7 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
|
import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.room.send.EncryptEventWorker
|
import im.vector.matrix.android.internal.session.room.send.EncryptEventWorker
|
||||||
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
|
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
|
||||||
import im.vector.matrix.android.internal.session.room.send.RedactEventWorker
|
import im.vector.matrix.android.internal.session.room.send.RedactEventWorker
|
||||||
|
@ -50,7 +50,7 @@ import timber.log.Timber
|
||||||
|
|
||||||
internal class DefaultRelationService @AssistedInject constructor(@Assisted private val roomId: String,
|
internal class DefaultRelationService @AssistedInject constructor(@Assisted private val roomId: String,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val eventFactory: LocalEchoEventFactory,
|
private val eventFactory: LocalEchoEventFactory,
|
||||||
private val cryptoService: CryptoService,
|
private val cryptoService: CryptoService,
|
||||||
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
|
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
|
||||||
|
@ -111,7 +111,7 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
||||||
//TODO duplicate with send service?
|
//TODO duplicate with send service?
|
||||||
private fun createRedactEventWork(localEvent: Event, eventId: String, reason: String?): OneTimeWorkRequest {
|
private fun createRedactEventWork(localEvent: Event, eventId: String, reason: String?): OneTimeWorkRequest {
|
||||||
val sendContentWorkerParams = RedactEventWorker.Params(
|
val sendContentWorkerParams = RedactEventWorker.Params(
|
||||||
credentials.userId,
|
userId,
|
||||||
localEvent.eventId!!,
|
localEvent.eventId!!,
|
||||||
roomId,
|
roomId,
|
||||||
eventId,
|
eventId,
|
||||||
|
@ -199,13 +199,13 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
|
||||||
|
|
||||||
private fun createEncryptEventWork(event: Event, keepKeys: List<String>?): OneTimeWorkRequest {
|
private fun createEncryptEventWork(event: Event, keepKeys: List<String>?): OneTimeWorkRequest {
|
||||||
// Same parameter
|
// Same parameter
|
||||||
val params = EncryptEventWorker.Params(credentials.userId, roomId, event, keepKeys)
|
val params = EncryptEventWorker.Params(userId, roomId, event, keepKeys)
|
||||||
val sendWorkData = WorkerParamsFactory.toData(params)
|
val sendWorkData = WorkerParamsFactory.toData(params)
|
||||||
return TimelineSendEventWorkCommon.createWork<EncryptEventWorker>(sendWorkData, true)
|
return TimelineSendEventWorkCommon.createWork<EncryptEventWorker>(sendWorkData, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
|
private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
|
||||||
val sendContentWorkerParams = SendEventWorker.Params(credentials.userId, roomId, event)
|
val sendContentWorkerParams = SendEventWorker.Params(userId, roomId, event)
|
||||||
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
||||||
return TimelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
|
return TimelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,10 @@
|
||||||
package im.vector.matrix.android.internal.session.room.send
|
package im.vector.matrix.android.internal.session.room.send
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.Transformations
|
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
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 com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.BuildConfig
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||||
import im.vector.matrix.android.api.session.events.model.*
|
import im.vector.matrix.android.api.session.events.model.*
|
||||||
|
@ -32,16 +28,16 @@ import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
import im.vector.matrix.android.api.session.room.send.SendService
|
import im.vector.matrix.android.api.session.room.send.SendService
|
||||||
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.send.UserDraft
|
|
||||||
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.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.api.util.CancelableBag
|
import im.vector.matrix.android.api.util.CancelableBag
|
||||||
import im.vector.matrix.android.internal.database.RealmLiveData
|
|
||||||
import im.vector.matrix.android.internal.database.mapper.DraftMapper
|
|
||||||
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.EventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
import im.vector.matrix.android.internal.database.query.findAllInRoomWithSendStates
|
import im.vector.matrix.android.internal.database.query.findAllInRoomWithSendStates
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.content.UploadContentWorker
|
import im.vector.matrix.android.internal.session.content.UploadContentWorker
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEventWorkCommon
|
import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEventWorkCommon
|
||||||
import im.vector.matrix.android.internal.util.CancelableWork
|
import im.vector.matrix.android.internal.util.CancelableWork
|
||||||
|
@ -59,7 +55,7 @@ private const val BACKOFF_DELAY = 10_000L
|
||||||
|
|
||||||
internal class DefaultSendService @AssistedInject constructor(@Assisted private val roomId: String,
|
internal class DefaultSendService @AssistedInject constructor(@Assisted private val roomId: String,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val localEchoEventFactory: LocalEchoEventFactory,
|
private val localEchoEventFactory: LocalEchoEventFactory,
|
||||||
private val cryptoService: CryptoService,
|
private val cryptoService: CryptoService,
|
||||||
private val monarchy: Monarchy
|
private val monarchy: Monarchy
|
||||||
|
@ -292,7 +288,7 @@ internal class DefaultSendService @AssistedInject constructor(@Assisted private
|
||||||
|
|
||||||
private fun createEncryptEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
|
private fun createEncryptEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
|
||||||
// Same parameter
|
// Same parameter
|
||||||
val params = EncryptEventWorker.Params(credentials.userId, roomId, event)
|
val params = EncryptEventWorker.Params(userId, roomId, event)
|
||||||
val sendWorkData = WorkerParamsFactory.toData(params)
|
val sendWorkData = WorkerParamsFactory.toData(params)
|
||||||
|
|
||||||
return matrixOneTimeWorkRequestBuilder<EncryptEventWorker>()
|
return matrixOneTimeWorkRequestBuilder<EncryptEventWorker>()
|
||||||
|
@ -304,7 +300,7 @@ internal class DefaultSendService @AssistedInject constructor(@Assisted private
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
|
private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest {
|
||||||
val sendContentWorkerParams = SendEventWorker.Params(credentials.userId, roomId, event)
|
val sendContentWorkerParams = SendEventWorker.Params(userId, roomId, event)
|
||||||
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
||||||
|
|
||||||
return TimelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
|
return TimelineSendEventWorkCommon.createWork<SendEventWorker>(sendWorkData, startChain)
|
||||||
|
@ -314,7 +310,7 @@ internal class DefaultSendService @AssistedInject constructor(@Assisted private
|
||||||
val redactEvent = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason).also {
|
val redactEvent = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason).also {
|
||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
}
|
}
|
||||||
val sendContentWorkerParams = RedactEventWorker.Params(credentials.userId, redactEvent.eventId!!, roomId, event.eventId, reason)
|
val sendContentWorkerParams = RedactEventWorker.Params(userId, redactEvent.eventId!!, roomId, event.eventId, reason)
|
||||||
val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
|
||||||
return TimelineSendEventWorkCommon.createWork<RedactEventWorker>(redactWorkData, true)
|
return TimelineSendEventWorkCommon.createWork<RedactEventWorker>(redactWorkData, true)
|
||||||
}
|
}
|
||||||
|
@ -323,7 +319,7 @@ internal class DefaultSendService @AssistedInject constructor(@Assisted private
|
||||||
attachment: ContentAttachmentData,
|
attachment: ContentAttachmentData,
|
||||||
isRoomEncrypted: Boolean,
|
isRoomEncrypted: Boolean,
|
||||||
startChain: Boolean): OneTimeWorkRequest {
|
startChain: Boolean): OneTimeWorkRequest {
|
||||||
val uploadMediaWorkerParams = UploadContentWorker.Params(credentials.userId, roomId, event, attachment, isRoomEncrypted)
|
val uploadMediaWorkerParams = UploadContentWorker.Params(userId, roomId, event, attachment, isRoomEncrypted)
|
||||||
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
|
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
|
||||||
|
|
||||||
return matrixOneTimeWorkRequestBuilder<UploadContentWorker>()
|
return matrixOneTimeWorkRequestBuilder<UploadContentWorker>()
|
||||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.session.room.send
|
||||||
import android.media.MediaMetadataRetriever
|
import android.media.MediaMetadataRetriever
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.R
|
import im.vector.matrix.android.R
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.api.permalinks.PermalinkFactory
|
import im.vector.matrix.android.api.permalinks.PermalinkFactory
|
||||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||||
import im.vector.matrix.android.api.session.events.model.*
|
import im.vector.matrix.android.api.session.events.model.*
|
||||||
|
@ -33,12 +32,13 @@ import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
||||||
import im.vector.matrix.android.internal.database.helper.addSendingEvent
|
import im.vector.matrix.android.internal.database.helper.addSendingEvent
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.content.ThumbnailExtractor
|
import im.vector.matrix.android.internal.session.content.ThumbnailExtractor
|
||||||
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.util.StringProvider
|
import im.vector.matrix.android.internal.util.StringProvider
|
||||||
import org.commonmark.parser.Parser
|
import org.commonmark.parser.Parser
|
||||||
import org.commonmark.renderer.html.HtmlRenderer
|
import org.commonmark.renderer.html.HtmlRenderer
|
||||||
import java.util.UUID
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +50,7 @@ import javax.inject.Inject
|
||||||
*
|
*
|
||||||
* The transactionID is used as loc
|
* The transactionID is used as loc
|
||||||
*/
|
*/
|
||||||
internal class LocalEchoEventFactory @Inject constructor(private val credentials: Credentials,
|
internal class LocalEchoEventFactory @Inject constructor(@UserId private val userId: String,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val roomSummaryUpdater: RoomSummaryUpdater) {
|
private val roomSummaryUpdater: RoomSummaryUpdater) {
|
||||||
// TODO Inject
|
// TODO Inject
|
||||||
|
@ -163,7 +163,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
return Event(
|
return Event(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
originServerTs = dummyOriginServerTs(),
|
originServerTs = dummyOriginServerTs(),
|
||||||
senderId = credentials.userId,
|
senderId = userId,
|
||||||
eventId = localId,
|
eventId = localId,
|
||||||
type = EventType.REACTION,
|
type = EventType.REACTION,
|
||||||
content = content.toContent(),
|
content = content.toContent(),
|
||||||
|
@ -255,7 +255,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
return Event(
|
return Event(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
originServerTs = dummyOriginServerTs(),
|
originServerTs = dummyOriginServerTs(),
|
||||||
senderId = credentials.userId,
|
senderId = userId,
|
||||||
eventId = localID,
|
eventId = localID,
|
||||||
type = EventType.MESSAGE,
|
type = EventType.MESSAGE,
|
||||||
content = content.toContent(),
|
content = content.toContent(),
|
||||||
|
@ -373,7 +373,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
return Event(
|
return Event(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
originServerTs = dummyOriginServerTs(),
|
originServerTs = dummyOriginServerTs(),
|
||||||
senderId = credentials.userId,
|
senderId = userId,
|
||||||
eventId = localID,
|
eventId = localID,
|
||||||
type = EventType.REDACTION,
|
type = EventType.REDACTION,
|
||||||
redacts = eventId,
|
redacts = eventId,
|
||||||
|
|
|
@ -106,7 +106,7 @@ internal class TimelineEventDecryptor(
|
||||||
Timber.v("Successfully decrypted event ${eventId}")
|
Timber.v("Successfully decrypted event ${eventId}")
|
||||||
eventEntity.setDecryptionResult(result)
|
eventEntity.setDecryptionResult(result)
|
||||||
} catch (e: MXCryptoError) {
|
} catch (e: MXCryptoError) {
|
||||||
Timber.v("Failed to decrypte event ${eventId} ${e}")
|
Timber.v("Failed to decrypt event ${eventId} ${e}")
|
||||||
if (e is MXCryptoError.Base && e.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) {
|
if (e is MXCryptoError.Base && e.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID) {
|
||||||
//Keep track of unknown sessions to automatically try to decrypt on new session
|
//Keep track of unknown sessions to automatically try to decrypt on new session
|
||||||
eventEntity.decryptionErrorCode = e.errorType.name
|
eventEntity.decryptionErrorCode = e.errorType.name
|
||||||
|
|
|
@ -17,15 +17,11 @@
|
||||||
package im.vector.matrix.android.internal.session.signout
|
package im.vector.matrix.android.internal.session.signout
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.internal.SessionManager
|
import im.vector.matrix.android.internal.SessionManager
|
||||||
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoModule
|
import im.vector.matrix.android.internal.crypto.CryptoModule
|
||||||
import im.vector.matrix.android.internal.database.RealmKeysUtils
|
import im.vector.matrix.android.internal.database.RealmKeysUtils
|
||||||
import im.vector.matrix.android.internal.di.CryptoDatabase
|
import im.vector.matrix.android.internal.di.*
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
|
||||||
import im.vector.matrix.android.internal.di.UserCacheDirectory
|
|
||||||
import im.vector.matrix.android.internal.di.UserMd5
|
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.session.SessionModule
|
import im.vector.matrix.android.internal.session.SessionModule
|
||||||
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
|
import im.vector.matrix.android.internal.session.cache.ClearCacheTask
|
||||||
|
@ -38,7 +34,7 @@ import javax.inject.Inject
|
||||||
internal interface SignOutTask : Task<Unit, Unit>
|
internal interface SignOutTask : Task<Unit, Unit>
|
||||||
|
|
||||||
internal class DefaultSignOutTask @Inject constructor(private val context: Context,
|
internal class DefaultSignOutTask @Inject constructor(private val context: Context,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val signOutAPI: SignOutAPI,
|
private val signOutAPI: SignOutAPI,
|
||||||
private val sessionManager: SessionManager,
|
private val sessionManager: SessionManager,
|
||||||
private val sessionParamsStore: SessionParamsStore,
|
private val sessionParamsStore: SessionParamsStore,
|
||||||
|
@ -55,13 +51,13 @@ internal class DefaultSignOutTask @Inject constructor(private val context: Conte
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.d("SignOut: release session...")
|
Timber.d("SignOut: release session...")
|
||||||
sessionManager.releaseSession(credentials.userId)
|
sessionManager.releaseSession(userId)
|
||||||
|
|
||||||
Timber.d("SignOut: cancel pending works...")
|
Timber.d("SignOut: cancel pending works...")
|
||||||
WorkManagerUtil.cancelAllWorks(context)
|
WorkManagerUtil.cancelAllWorks(context)
|
||||||
|
|
||||||
Timber.d("SignOut: delete session params...")
|
Timber.d("SignOut: delete session params...")
|
||||||
sessionParamsStore.delete(credentials.userId)
|
sessionParamsStore.delete(userId)
|
||||||
|
|
||||||
Timber.d("SignOut: clear session data...")
|
Timber.d("SignOut: clear session data...")
|
||||||
clearSessionDataTask.execute(Unit)
|
clearSessionDataTask.execute(Unit)
|
||||||
|
|
|
@ -64,12 +64,13 @@ internal class GroupSyncHandler @Inject constructor(private val monarchy: Monarc
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Note: [im.vector.matrix.android.internal.session.group.GroupSummaryUpdater] is observing changes */
|
||||||
realm.insertOrUpdate(groups)
|
realm.insertOrUpdate(groups)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleJoinedGroup(realm: Realm,
|
private fun handleJoinedGroup(realm: Realm,
|
||||||
groupId: String): GroupEntity {
|
groupId: String): GroupEntity {
|
||||||
|
|
||||||
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
||||||
groupEntity.membership = Membership.JOIN
|
groupEntity.membership = Membership.JOIN
|
||||||
return groupEntity
|
return groupEntity
|
||||||
|
@ -77,21 +78,16 @@ internal class GroupSyncHandler @Inject constructor(private val monarchy: Monarc
|
||||||
|
|
||||||
private fun handleInvitedGroup(realm: Realm,
|
private fun handleInvitedGroup(realm: Realm,
|
||||||
groupId: String): GroupEntity {
|
groupId: String): GroupEntity {
|
||||||
|
|
||||||
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
||||||
groupEntity.membership = Membership.INVITE
|
groupEntity.membership = Membership.INVITE
|
||||||
return groupEntity
|
return groupEntity
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : handle it
|
|
||||||
private fun handleLeftGroup(realm: Realm,
|
private fun handleLeftGroup(realm: Realm,
|
||||||
groupId: String): GroupEntity {
|
groupId: String): GroupEntity {
|
||||||
|
|
||||||
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
||||||
groupEntity.membership = Membership.LEAVE
|
groupEntity.membership = Membership.LEAVE
|
||||||
return groupEntity
|
return groupEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.R
|
import im.vector.matrix.android.R
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleScope
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
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
|
||||||
|
@ -87,11 +88,11 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
||||||
private fun checkPushRules(roomsSyncResponse: RoomsSyncResponse) {
|
private fun checkPushRules(roomsSyncResponse: RoomsSyncResponse) {
|
||||||
Timber.v("[PushRules] --> checkPushRules")
|
Timber.v("[PushRules] --> checkPushRules")
|
||||||
if (tokenStore.getLastToken() == null) {
|
if (tokenStore.getLastToken() == null) {
|
||||||
Timber.v("[PushRules] <-- No push tule check on initial sync")
|
Timber.v("[PushRules] <-- No push rule check on initial sync")
|
||||||
return
|
return
|
||||||
} //nothing on initial sync
|
} //nothing on initial sync
|
||||||
|
|
||||||
val rules = pushRuleService.getPushRules("global")
|
val rules = pushRuleService.getPushRules(RuleScope.GLOBAL)
|
||||||
processForPushTask.configureWith(ProcessEventForPushTask.Params(roomsSyncResponse, rules))
|
processForPushTask.configureWith(ProcessEventForPushTask.Params(roomsSyncResponse, rules))
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
Timber.v("[PushRules] <-- Push task scheduled")
|
Timber.v("[PushRules] <-- Push task scheduled")
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.session.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import arrow.core.Try
|
|
||||||
import im.vector.matrix.android.R
|
import im.vector.matrix.android.R
|
||||||
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||||
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
||||||
|
@ -33,73 +32,70 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
|
||||||
private val cryptoService: DefaultCryptoService,
|
private val cryptoService: DefaultCryptoService,
|
||||||
private val initialSyncProgressService: DefaultInitialSyncProgressService) {
|
private val initialSyncProgressService: DefaultInitialSyncProgressService) {
|
||||||
|
|
||||||
fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try<SyncResponse> {
|
suspend fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean) {
|
||||||
return Try {
|
val isInitialSync = fromToken == null
|
||||||
val isInitialSync = fromToken == null
|
Timber.v("Start handling sync, is InitialSync: $isInitialSync")
|
||||||
Timber.v("Start handling sync, is InitialSync: $isInitialSync")
|
val reporter = initialSyncProgressService.takeIf { isInitialSync }
|
||||||
val reporter = initialSyncProgressService.takeIf { isInitialSync }
|
|
||||||
|
|
||||||
|
measureTimeMillis {
|
||||||
|
if (!cryptoService.isStarted()) {
|
||||||
|
Timber.v("Should start cryptoService")
|
||||||
|
cryptoService.start(isInitialSync)
|
||||||
|
}
|
||||||
|
}.also {
|
||||||
|
Timber.v("Finish handling start cryptoService in $it ms")
|
||||||
|
}
|
||||||
|
val measure = measureTimeMillis {
|
||||||
|
// Handle the to device events before the room ones
|
||||||
|
// to ensure to decrypt them properly
|
||||||
measureTimeMillis {
|
measureTimeMillis {
|
||||||
if (!cryptoService.isStarted()) {
|
Timber.v("Handle toDevice")
|
||||||
Timber.v("Should start cryptoService")
|
reportSubtask(reporter, R.string.initial_sync_start_importing_account_crypto, 100, 0.1f) {
|
||||||
cryptoService.start(isInitialSync)
|
if (syncResponse.toDevice != null) {
|
||||||
|
cryptoSyncHandler.handleToDevice(syncResponse.toDevice, reporter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
Timber.v("Finish handling start cryptoService in $it ms")
|
Timber.v("Finish handling toDevice in $it ms")
|
||||||
}
|
}
|
||||||
val measure = measureTimeMillis {
|
|
||||||
// Handle the to device events before the room ones
|
measureTimeMillis {
|
||||||
// to ensure to decrypt them properly
|
Timber.v("Handle rooms")
|
||||||
measureTimeMillis {
|
|
||||||
Timber.v("Handle toDevice")
|
reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.7f) {
|
||||||
reportSubtask(reporter, R.string.initial_sync_start_importing_account_crypto, 100, 0.1f) {
|
if (syncResponse.rooms != null) {
|
||||||
if (syncResponse.toDevice != null) {
|
roomSyncHandler.handle(syncResponse.rooms, isInitialSync, reporter)
|
||||||
cryptoSyncHandler.handleToDevice(syncResponse.toDevice, reporter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.also {
|
|
||||||
Timber.v("Finish handling toDevice in $it ms")
|
|
||||||
}
|
}
|
||||||
|
}.also {
|
||||||
measureTimeMillis {
|
Timber.v("Finish handling rooms in $it ms")
|
||||||
Timber.v("Handle rooms")
|
|
||||||
|
|
||||||
reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.7f) {
|
|
||||||
if (syncResponse.rooms != null) {
|
|
||||||
roomSyncHandler.handle(syncResponse.rooms, isInitialSync, reporter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.also {
|
|
||||||
Timber.v("Finish handling rooms in $it ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
measureTimeMillis {
|
|
||||||
reportSubtask(reporter, R.string.initial_sync_start_importing_account_groups, 100, 0.1f) {
|
|
||||||
Timber.v("Handle groups")
|
|
||||||
if (syncResponse.groups != null) {
|
|
||||||
groupSyncHandler.handle(syncResponse.groups, reporter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.also {
|
|
||||||
Timber.v("Finish handling groups in $it ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
measureTimeMillis {
|
|
||||||
reportSubtask(reporter, R.string.initial_sync_start_importing_account_data, 100, 0.1f) {
|
|
||||||
Timber.v("Handle accountData")
|
|
||||||
userAccountDataSyncHandler.handle(syncResponse.accountData, syncResponse.rooms?.invite)
|
|
||||||
}
|
|
||||||
}.also {
|
|
||||||
Timber.v("Finish handling accountData in $it ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
Timber.v("On sync completed")
|
|
||||||
cryptoSyncHandler.onSyncCompleted(syncResponse)
|
|
||||||
}
|
}
|
||||||
Timber.v("Finish handling sync in $measure ms")
|
|
||||||
syncResponse
|
|
||||||
|
measureTimeMillis {
|
||||||
|
reportSubtask(reporter, R.string.initial_sync_start_importing_account_groups, 100, 0.1f) {
|
||||||
|
Timber.v("Handle groups")
|
||||||
|
if (syncResponse.groups != null) {
|
||||||
|
groupSyncHandler.handle(syncResponse.groups, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.also {
|
||||||
|
Timber.v("Finish handling groups in $it ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
measureTimeMillis {
|
||||||
|
reportSubtask(reporter, R.string.initial_sync_start_importing_account_data, 100, 0.1f) {
|
||||||
|
Timber.v("Handle accountData")
|
||||||
|
userAccountDataSyncHandler.handle(syncResponse.accountData, syncResponse.rooms?.invite)
|
||||||
|
}
|
||||||
|
}.also {
|
||||||
|
Timber.v("Finish handling accountData in $it ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
Timber.v("On sync completed")
|
||||||
|
cryptoSyncHandler.onSyncCompleted(syncResponse)
|
||||||
}
|
}
|
||||||
|
Timber.v("Finish handling sync in $measure ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,10 +18,10 @@ package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.R
|
import im.vector.matrix.android.R
|
||||||
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
|
||||||
import im.vector.matrix.android.api.failure.MatrixError
|
import im.vector.matrix.android.api.failure.MatrixError
|
||||||
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
||||||
import im.vector.matrix.android.internal.session.filter.FilterRepository
|
import im.vector.matrix.android.internal.session.filter.FilterRepository
|
||||||
|
@ -36,7 +36,7 @@ internal interface SyncTask : Task<SyncTask.Params, Unit> {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
|
internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val filterRepository: FilterRepository,
|
private val filterRepository: FilterRepository,
|
||||||
private val syncResponseHandler: SyncResponseHandler,
|
private val syncResponseHandler: SyncResponseHandler,
|
||||||
private val sessionParamsStore: SessionParamsStore,
|
private val sessionParamsStore: SessionParamsStore,
|
||||||
|
@ -70,7 +70,7 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
|
||||||
// Intercept 401
|
// Intercept 401
|
||||||
if (throwable is Failure.ServerError
|
if (throwable is Failure.ServerError
|
||||||
&& throwable.error.code == MatrixError.UNKNOWN_TOKEN) {
|
&& throwable.error.code == MatrixError.UNKNOWN_TOKEN) {
|
||||||
sessionParamsStore.delete(credentials.userId)
|
sessionParamsStore.delete(userId)
|
||||||
}
|
}
|
||||||
throw throwable
|
throw throwable
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,18 @@
|
||||||
package im.vector.matrix.android.internal.session.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
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.RoomMember
|
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||||
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.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.getDirectRooms
|
import im.vector.matrix.android.internal.database.query.getDirectRooms
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
|
import im.vector.matrix.android.internal.session.pushers.SavePushRulesTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages
|
||||||
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataPushRules
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataSync
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountDataSync
|
||||||
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper
|
||||||
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
|
@ -37,15 +39,17 @@ import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class UserAccountDataSyncHandler @Inject constructor(private val monarchy: Monarchy,
|
internal class UserAccountDataSyncHandler @Inject constructor(private val monarchy: Monarchy,
|
||||||
private val credentials: Credentials,
|
@UserId private val userId: String,
|
||||||
private val directChatsHelper: DirectChatsHelper,
|
private val directChatsHelper: DirectChatsHelper,
|
||||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||||
|
private val savePushRulesTask: SavePushRulesTask,
|
||||||
private val taskExecutor: TaskExecutor) {
|
private val taskExecutor: TaskExecutor) {
|
||||||
|
|
||||||
fun handle(accountData: UserAccountDataSync?, invites: Map<String, InvitedRoomSync>?) {
|
suspend fun handle(accountData: UserAccountDataSync?, invites: Map<String, InvitedRoomSync>?) {
|
||||||
accountData?.list?.forEach {
|
accountData?.list?.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is UserAccountDataDirectMessages -> handleDirectChatRooms(it)
|
is UserAccountDataDirectMessages -> handleDirectChatRooms(it)
|
||||||
|
is UserAccountDataPushRules -> handlePushRules(it)
|
||||||
else -> return@forEach
|
else -> return@forEach
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +58,10 @@ internal class UserAccountDataSyncHandler @Inject constructor(private val monarc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun handlePushRules(userAccountDataPushRules: UserAccountDataPushRules) {
|
||||||
|
savePushRulesTask.execute(SavePushRulesTask.Params(userAccountDataPushRules.content))
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleDirectChatRooms(directMessages: UserAccountDataDirectMessages) {
|
private fun handleDirectChatRooms(directMessages: UserAccountDataDirectMessages) {
|
||||||
monarchy.runTransactionSync { realm ->
|
monarchy.runTransactionSync { realm ->
|
||||||
val oldDirectRooms = RoomSummaryEntity.getDirectRooms(realm)
|
val oldDirectRooms = RoomSummaryEntity.getDirectRooms(realm)
|
||||||
|
@ -81,11 +89,11 @@ internal class UserAccountDataSyncHandler @Inject constructor(private val monarc
|
||||||
val directChats = directChatsHelper.getLocalUserAccount()
|
val directChats = directChatsHelper.getLocalUserAccount()
|
||||||
var hasUpdate = false
|
var hasUpdate = false
|
||||||
invites.forEach { (roomId, _) ->
|
invites.forEach { (roomId, _) ->
|
||||||
val myUserStateEvent = RoomMembers(realm, roomId).getStateEvent(credentials.userId)
|
val myUserStateEvent = RoomMembers(realm, roomId).getStateEvent(userId)
|
||||||
val inviterId = myUserStateEvent?.sender
|
val inviterId = myUserStateEvent?.sender
|
||||||
val myUserRoomMember: RoomMember? = myUserStateEvent?.let { it.asDomain().content?.toModel() }
|
val myUserRoomMember: RoomMember? = myUserStateEvent?.let { it.asDomain().content?.toModel() }
|
||||||
val isDirect = myUserRoomMember?.isDirect
|
val isDirect = myUserRoomMember?.isDirect
|
||||||
if (inviterId != null && inviterId != credentials.userId && isDirect == true) {
|
if (inviterId != null && inviterId != userId && isDirect == true) {
|
||||||
directChats
|
directChats
|
||||||
.getOrPut(inviterId, { arrayListOf() })
|
.getOrPut(inviterId, { arrayListOf() })
|
||||||
.apply {
|
.apply {
|
||||||
|
|
|
@ -30,7 +30,6 @@ import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.TaskThread
|
import im.vector.matrix.android.internal.task.TaskThread
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
||||||
import kotlinx.coroutines.CancellationException
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.net.SocketTimeoutException
|
import java.net.SocketTimeoutException
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
@ -140,7 +139,7 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
|
||||||
if (failure is Failure.NetworkConnection && failure.cause is SocketTimeoutException) {
|
if (failure is Failure.NetworkConnection && failure.cause is SocketTimeoutException) {
|
||||||
// Timeout are not critical
|
// Timeout are not critical
|
||||||
Timber.v("Timeout")
|
Timber.v("Timeout")
|
||||||
} else if (failure is Failure.Unknown && failure.throwable is CancellationException) {
|
} else if (failure is Failure.Cancelled) {
|
||||||
Timber.v("Cancelled")
|
Timber.v("Cancelled")
|
||||||
} else if (failure is Failure.ServerError
|
} else if (failure is Failure.ServerError
|
||||||
&& (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
|
&& (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
|
||||||
|
|
|
@ -23,5 +23,6 @@ internal interface UserAccountData {
|
||||||
const val TYPE_DIRECT_MESSAGES = "m.direct"
|
const val TYPE_DIRECT_MESSAGES = "m.direct"
|
||||||
const val TYPE_PREVIEW_URLS = "org.matrix.preview_urls"
|
const val TYPE_PREVIEW_URLS = "org.matrix.preview_urls"
|
||||||
const val TYPE_WIDGETS = "m.widgets"
|
const val TYPE_WIDGETS = "m.widgets"
|
||||||
|
const val TYPE_PUSH_RULES = "m.push_rules"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* 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 im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.api.pushrules.rest.GetPushRulesResponse
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class UserAccountDataPushRules(
|
||||||
|
@Json(name = "content") val content: GetPushRulesResponse
|
||||||
|
) : UserAccountData
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.session.user.accountdata
|
package im.vector.matrix.android.internal.session.user.accountdata
|
||||||
|
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.session.sync.model.UserAccountData
|
import im.vector.matrix.android.internal.session.sync.model.UserAccountData
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
@ -42,11 +42,11 @@ internal interface UpdateUserAccountDataTask : Task<UpdateUserAccountDataTask.Pa
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultUpdateUserAccountDataTask @Inject constructor(private val accountDataApi: AccountDataAPI,
|
internal class DefaultUpdateUserAccountDataTask @Inject constructor(private val accountDataApi: AccountDataAPI,
|
||||||
private val credentials: Credentials) : UpdateUserAccountDataTask {
|
@UserId private val userId: String) : UpdateUserAccountDataTask {
|
||||||
|
|
||||||
override suspend fun execute(params: UpdateUserAccountDataTask.Params) {
|
override suspend fun execute(params: UpdateUserAccountDataTask.Params) {
|
||||||
return executeRequest {
|
return executeRequest {
|
||||||
apiCall = accountDataApi.setAccountData(credentials.userId, params.type, params.getData())
|
apiCall = accountDataApi.setAccountData(userId, params.type, params.getData())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,13 @@ import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.toContent
|
import im.vector.matrix.android.api.session.events.model.toContent
|
||||||
import im.vector.matrix.android.api.session.room.Room
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
import im.vector.matrix.android.api.session.room.model.*
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
|
||||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||||
|
import im.vector.matrix.android.api.session.room.send.UserDraft
|
||||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||||
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.api.session.room.timeline.TimelineSettings
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -164,10 +163,29 @@ class PushrulesConditionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_notice_condition() {
|
||||||
|
val conditionEqual = EventMatchCondition("content.msgtype", "m.notice")
|
||||||
|
|
||||||
|
Event(
|
||||||
|
type = "m.room.message",
|
||||||
|
eventId = "mx0",
|
||||||
|
content = MessageTextContent("m.notice", "A").toContent(),
|
||||||
|
originServerTs = 0,
|
||||||
|
roomId = "2joined").also {
|
||||||
|
Assert.assertTrue("Notice", conditionEqual.isSatisfied(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class MockRoomService() : RoomService {
|
class MockRoomService() : RoomService {
|
||||||
|
|
||||||
override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>) {
|
override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>): Cancelable {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun joinRoom(roomId: String, viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRoom(roomId: String): Room? {
|
override fun getRoom(roomId: String): Room? {
|
||||||
|
@ -184,7 +202,54 @@ class PushrulesConditionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockRoom(override val roomId: String, val _numberOfJoinedMembers: Int) : Room {
|
class MockRoom(override val roomId: String, val _numberOfJoinedMembers: Int) : Room {
|
||||||
override fun getTimeLineEventLive(eventId: String): LiveData<TimelineEvent> {
|
override fun resendTextMessage(localEcho: TimelineEvent): Cancelable? {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resendMediaMessage(localEcho: TimelineEvent): Cancelable? {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deleteFailedEcho(localEcho: TimelineEvent) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearSendingQueue() {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resendAllFailedMessages() {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun saveDraft(draft: UserDraft) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deleteDraft() {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDraftsLive(): LiveData<List<UserDraft>> {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getEventReadReceiptsLive(eventId: String): LiveData<List<ReadReceipt>> {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStateEvent(eventType: String): Event? {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun editReply(replyToEdit: TimelineEvent, originalTimelineEvent: TimelineEvent, newBodyText: String, compatibilityBodyText: String): Cancelable {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fetchEditHistory(eventId: String, callback: MatrixCallback<List<Event>>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun liveTimeLineEvent(eventId: String): LiveData<TimelineEvent> {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +258,7 @@ class PushrulesConditionTest {
|
||||||
return _numberOfJoinedMembers
|
return _numberOfJoinedMembers
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRoomSummaryLive(): LiveData<RoomSummary> {
|
override fun liveRoomSummary(): LiveData<RoomSummary> {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +266,7 @@ class PushrulesConditionTest {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createTimeline(eventId: String?, allowedTypes: List<String>?): Timeline {
|
override fun createTimeline(eventId: String?, settings: TimelineSettings): Timeline {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +310,7 @@ class PushrulesConditionTest {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadRoomMembersIfNeeded(): Cancelable {
|
override fun loadRoomMembersIfNeeded(matrixCallback: MatrixCallback<Unit>): Cancelable {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,15 +322,15 @@ class PushrulesConditionTest {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invite(userId: String, callback: MatrixCallback<Unit>) {
|
override fun invite(userId: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun join(callback: MatrixCallback<Unit>) {
|
override fun join(viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun leave(callback: MatrixCallback<Unit>) {
|
override fun leave(callback: MatrixCallback<Unit>): Cancelable {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ androidExtensions {
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.versionMajor = 0
|
ext.versionMajor = 0
|
||||||
ext.versionMinor = 6
|
ext.versionMinor = 7
|
||||||
ext.versionPatch = 0
|
ext.versionPatch = 0
|
||||||
|
|
||||||
static def getGitTimestamp() {
|
static def getGitTimestamp() {
|
||||||
|
|
|
@ -21,11 +21,19 @@ import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.extensions.vectorComponent
|
||||||
import im.vector.riotx.features.notifications.NotificationUtils
|
import im.vector.riotx.features.notifications.NotificationUtils
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class VectorSyncService : SyncService() {
|
class VectorSyncService : SyncService() {
|
||||||
|
|
||||||
|
private lateinit var notificationUtils: NotificationUtils
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
notificationUtils = vectorComponent().notificationUtils()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
removeForegroundNotif()
|
removeForegroundNotif()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
@ -43,7 +51,7 @@ class VectorSyncService : SyncService() {
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Timber.v("VectorSyncService - onStartCommand ")
|
Timber.v("VectorSyncService - onStartCommand ")
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val notification = NotificationUtils.buildForegroundServiceNotification(applicationContext, R.string.notification_listening_for_events, false)
|
val notification = notificationUtils.buildForegroundServiceNotification(R.string.notification_listening_for_events, false)
|
||||||
startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification)
|
startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification)
|
||||||
}
|
}
|
||||||
return super.onStartCommand(intent, flags, startId)
|
return super.onStartCommand(intent, flags, startId)
|
||||||
|
|
|
@ -27,6 +27,7 @@ import im.vector.riotx.EmojiCompatFontProvider
|
||||||
import im.vector.riotx.EmojiCompatWrapper
|
import im.vector.riotx.EmojiCompatWrapper
|
||||||
import im.vector.riotx.VectorApplication
|
import im.vector.riotx.VectorApplication
|
||||||
import im.vector.riotx.core.pushers.PushersManager
|
import im.vector.riotx.core.pushers.PushersManager
|
||||||
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import im.vector.riotx.features.configuration.VectorConfiguration
|
import im.vector.riotx.features.configuration.VectorConfiguration
|
||||||
import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler
|
import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler
|
||||||
import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler
|
import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler
|
||||||
|
@ -63,6 +64,8 @@ interface VectorComponent {
|
||||||
|
|
||||||
fun resources(): Resources
|
fun resources(): Resources
|
||||||
|
|
||||||
|
fun dimensionUtils(): DimensionConverter
|
||||||
|
|
||||||
fun vectorConfiguration(): VectorConfiguration
|
fun vectorConfiguration(): VectorConfiguration
|
||||||
|
|
||||||
fun avatarRenderer(): AvatarRenderer
|
fun avatarRenderer(): AvatarRenderer
|
||||||
|
|
|
@ -32,7 +32,6 @@ fun Session.configureAndStart(pushRuleTriggerListener: PushRuleTriggerListener)
|
||||||
startSync(isAtLeastStarted)
|
startSync(isAtLeastStarted)
|
||||||
refreshPushers()
|
refreshPushers()
|
||||||
pushRuleTriggerListener.startWithSession(this)
|
pushRuleTriggerListener.startWithSession(this)
|
||||||
fetchPushRules()
|
|
||||||
|
|
||||||
// TODO P1 From HomeActivity
|
// TODO P1 From HomeActivity
|
||||||
// @Inject lateinit var incomingVerificationRequestHandler: IncomingVerificationRequestHandler
|
// @Inject lateinit var incomingVerificationRequestHandler: IncomingVerificationRequestHandler
|
||||||
|
|
|
@ -15,25 +15,26 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.riotx.core.utils
|
package im.vector.riotx.core.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.res.Resources
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
object DimensionUtils {
|
class DimensionConverter @Inject constructor(val resources: Resources) {
|
||||||
|
|
||||||
fun dpToPx(dp: Int, context: Context): Int {
|
fun dpToPx(dp: Int): Int {
|
||||||
return TypedValue.applyDimension(
|
return TypedValue.applyDimension(
|
||||||
TypedValue.COMPLEX_UNIT_DIP,
|
TypedValue.COMPLEX_UNIT_DIP,
|
||||||
dp.toFloat(),
|
dp.toFloat(),
|
||||||
context.resources.displayMetrics
|
resources.displayMetrics
|
||||||
).toInt()
|
).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun spToPx(sp: Int, context: Context): Int {
|
fun spToPx(sp: Int): Int {
|
||||||
return TypedValue.applyDimension(
|
return TypedValue.applyDimension(
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
sp.toFloat(),
|
sp.toFloat(),
|
||||||
context.resources.displayMetrics
|
resources.displayMetrics
|
||||||
).toInt()
|
).toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -204,7 +204,7 @@ class KeyRequestHandler @Inject constructor(private val context: Context)
|
||||||
Runnable {
|
Runnable {
|
||||||
alert.weakCurrentActivity?.get()?.let {
|
alert.weakCurrentActivity?.get()?.let {
|
||||||
val intent = SASVerificationActivity.outgoingIntent(it,
|
val intent = SASVerificationActivity.outgoingIntent(it,
|
||||||
session?.sessionParams?.credentials?.userId ?: "",
|
session?.myUserId ?: "",
|
||||||
userId, deviceId)
|
userId, deviceId)
|
||||||
it.startActivity(intent)
|
it.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ class IncomingVerificationRequestHandler @Inject constructor(private val context
|
||||||
.apply {
|
.apply {
|
||||||
contentAction = Runnable {
|
contentAction = Runnable {
|
||||||
val intent = SASVerificationActivity.incomingIntent(context,
|
val intent = SASVerificationActivity.incomingIntent(context,
|
||||||
session?.sessionParams?.credentials?.userId ?: "",
|
session?.myUserId ?: "",
|
||||||
tx.otherUserId,
|
tx.otherUserId,
|
||||||
tx.transactionId)
|
tx.transactionId)
|
||||||
weakCurrentActivity?.get()?.startActivity(intent)
|
weakCurrentActivity?.get()?.startActivity(intent)
|
||||||
|
@ -78,7 +78,7 @@ class IncomingVerificationRequestHandler @Inject constructor(private val context
|
||||||
context.getString(R.string.action_open),
|
context.getString(R.string.action_open),
|
||||||
Runnable {
|
Runnable {
|
||||||
val intent = SASVerificationActivity.incomingIntent(context,
|
val intent = SASVerificationActivity.incomingIntent(context,
|
||||||
session?.sessionParams?.credentials?.userId ?: "",
|
session?.myUserId ?: "",
|
||||||
tx.otherUserId,
|
tx.otherUserId,
|
||||||
tx.transactionId)
|
tx.transactionId)
|
||||||
weakCurrentActivity?.get()?.startActivity(intent)
|
weakCurrentActivity?.get()?.startActivity(intent)
|
||||||
|
|
|
@ -36,7 +36,7 @@ import im.vector.riotx.core.extensions.hideKeyboard
|
||||||
import im.vector.riotx.core.extensions.observeEvent
|
import im.vector.riotx.core.extensions.observeEvent
|
||||||
import im.vector.riotx.core.extensions.setupAsSearch
|
import im.vector.riotx.core.extensions.setupAsSearch
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||||
import im.vector.riotx.core.utils.DimensionUtils
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
import kotlinx.android.synthetic.main.fragment_create_direct_room.*
|
import kotlinx.android.synthetic.main.fragment_create_direct_room.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -51,6 +51,7 @@ class CreateDirectRoomKnownUsersFragment : VectorBaseFragment(), KnownUsersContr
|
||||||
|
|
||||||
@Inject lateinit var directRoomController: KnownUsersController
|
@Inject lateinit var directRoomController: KnownUsersController
|
||||||
@Inject lateinit var avatarRenderer: AvatarRenderer
|
@Inject lateinit var avatarRenderer: AvatarRenderer
|
||||||
|
@Inject lateinit var dimensionConverter: DimensionConverter
|
||||||
private lateinit var navigationViewModel: CreateDirectRoomNavigationViewModel
|
private lateinit var navigationViewModel: CreateDirectRoomNavigationViewModel
|
||||||
|
|
||||||
override fun injectWith(injector: ScreenComponent) {
|
override fun injectWith(injector: ScreenComponent) {
|
||||||
|
@ -156,7 +157,7 @@ class CreateDirectRoomKnownUsersFragment : VectorBaseFragment(), KnownUsersContr
|
||||||
private fun addChipToGroup(user: User, chipGroup: ChipGroup) {
|
private fun addChipToGroup(user: User, chipGroup: ChipGroup) {
|
||||||
val chip = Chip(requireContext())
|
val chip = Chip(requireContext())
|
||||||
chip.setChipBackgroundColorResource(android.R.color.transparent)
|
chip.setChipBackgroundColorResource(android.R.color.transparent)
|
||||||
chip.chipStrokeWidth = DimensionUtils.dpToPx(1, requireContext()).toFloat()
|
chip.chipStrokeWidth = dimensionConverter.dpToPx(1).toFloat()
|
||||||
chip.text = if (user.displayName.isNullOrBlank()) user.userId else user.displayName
|
chip.text = if (user.displayName.isNullOrBlank()) user.userId else user.displayName
|
||||||
chip.isClickable = true
|
chip.isClickable = true
|
||||||
chip.isCheckable = false
|
chip.isCheckable = false
|
||||||
|
|
|
@ -26,6 +26,7 @@ import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.extensions.postLiveEvent
|
import im.vector.riotx.core.extensions.postLiveEvent
|
||||||
|
@ -93,20 +94,20 @@ class GroupListViewModel @AssistedInject constructor(@Assisted initialState: Gro
|
||||||
session
|
session
|
||||||
.rx()
|
.rx()
|
||||||
.liveGroupSummaries()
|
.liveGroupSummaries()
|
||||||
|
// Keep only joined groups. Group invitations will be managed later
|
||||||
|
.map { it.filter { groupSummary -> groupSummary.membership == Membership.JOIN } }
|
||||||
.map {
|
.map {
|
||||||
val myUser = session.getUser(session.myUserId)
|
val myUser = session.getUser(session.myUserId)
|
||||||
val allCommunityGroup = GroupSummary(
|
val allCommunityGroup = GroupSummary(
|
||||||
groupId = ALL_COMMUNITIES_GROUP_ID,
|
groupId = ALL_COMMUNITIES_GROUP_ID,
|
||||||
|
membership = Membership.JOIN,
|
||||||
displayName = stringProvider.getString(R.string.group_all_communities),
|
displayName = stringProvider.getString(R.string.group_all_communities),
|
||||||
avatarUrl = myUser?.avatarUrl ?: "")
|
avatarUrl = myUser?.avatarUrl ?: "")
|
||||||
listOf(allCommunityGroup) + it
|
listOf(allCommunityGroup) + it
|
||||||
}
|
}
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
// TODO Phase2 Handle the case where the selected group is deleted on another client
|
|
||||||
val newSelectedGroup = selectedGroup ?: async()?.firstOrNull()
|
val newSelectedGroup = selectedGroup ?: async()?.firstOrNull()
|
||||||
copy(asyncGroups = async, selectedGroup = newSelectedGroup)
|
copy(asyncGroups = async, selectedGroup = newSelectedGroup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* 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 im.vector.riotx.features.home.room.detail.timeline.factory
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
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.room.timeline.TimelineEvent
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent
|
||||||
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
|
import im.vector.riotx.features.home.AvatarRenderer
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.helper.senderAvatar
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.helper.senderName
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem
|
||||||
|
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class EncryptionItemFactory @Inject constructor(private val stringProvider: StringProvider,
|
||||||
|
private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val avatarSizeProvider: AvatarSizeProvider) {
|
||||||
|
|
||||||
|
fun create(event: TimelineEvent,
|
||||||
|
highlight: Boolean,
|
||||||
|
callback: TimelineEventController.Callback?): NoticeItem? {
|
||||||
|
|
||||||
|
val text = buildNoticeText(event.root, event.senderName) ?: return null
|
||||||
|
val informationData = MessageInformationData(
|
||||||
|
eventId = event.root.eventId ?: "?",
|
||||||
|
senderId = event.root.senderId ?: "",
|
||||||
|
sendState = event.root.sendState,
|
||||||
|
avatarUrl = event.senderAvatar(),
|
||||||
|
memberName = event.senderName(),
|
||||||
|
showInformation = false
|
||||||
|
)
|
||||||
|
val attributes = NoticeItem.Attributes(
|
||||||
|
avatarRenderer = avatarRenderer,
|
||||||
|
informationData = informationData,
|
||||||
|
noticeText = text,
|
||||||
|
itemLongClickListener = View.OnLongClickListener { view ->
|
||||||
|
callback?.onEventLongClicked(informationData, null, view) ?: false
|
||||||
|
},
|
||||||
|
readReceiptsCallback = callback
|
||||||
|
)
|
||||||
|
return NoticeItem_()
|
||||||
|
.leftGuideline(avatarSizeProvider.leftGuideline)
|
||||||
|
.highlighted(highlight)
|
||||||
|
.attributes(attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildNoticeText(event: Event, senderName: String?): CharSequence? {
|
||||||
|
return when {
|
||||||
|
EventType.ENCRYPTION == event.getClearType() -> {
|
||||||
|
val content = event.content.toModel<EncryptionEventContent>() ?: return null
|
||||||
|
stringProvider.getString(R.string.notice_end_to_end, senderName, content.algorithm)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -27,12 +27,10 @@ import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_
|
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class NoticeItemFactory @Inject constructor(
|
class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEventFormatter,
|
||||||
private val eventFormatter: NoticeEventFormatter,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
private val avatarRenderer: AvatarRenderer,
|
private val informationDataFactory: MessageInformationDataFactory,
|
||||||
private val informationDataFactory: MessageInformationDataFactory,
|
private val avatarSizeProvider: AvatarSizeProvider) {
|
||||||
private val avatarSizeProvider: AvatarSizeProvider
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
|
|
|
@ -16,20 +16,19 @@
|
||||||
|
|
||||||
package im.vector.riotx.features.home.room.detail.timeline.helper
|
package im.vector.riotx.features.home.room.detail.timeline.helper
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import im.vector.riotx.core.utils.DimensionUtils.dpToPx
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AvatarSizeProvider @Inject constructor(private val context: AppCompatActivity) {
|
class AvatarSizeProvider @Inject constructor(private val dimensionConverter: DimensionConverter) {
|
||||||
|
|
||||||
private val avatarStyle = AvatarStyle.SMALL
|
private val avatarStyle = AvatarStyle.SMALL
|
||||||
|
|
||||||
val leftGuideline: Int by lazy {
|
val leftGuideline: Int by lazy {
|
||||||
dpToPx(avatarStyle.avatarSizeDP + 8, context)
|
dimensionConverter.dpToPx(avatarStyle.avatarSizeDP + 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
val avatarSize: Int by lazy {
|
val avatarSize: Int by lazy {
|
||||||
dpToPx(avatarStyle.avatarSizeDP, context)
|
dimensionConverter.dpToPx(avatarStyle.avatarSizeDP)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -26,8 +26,7 @@ import im.vector.riotx.core.epoxy.VectorEpoxyModel
|
||||||
import im.vector.riotx.core.platform.CheckableView
|
import im.vector.riotx.core.platform.CheckableView
|
||||||
import im.vector.riotx.core.ui.views.ReadMarkerView
|
import im.vector.riotx.core.ui.views.ReadMarkerView
|
||||||
import im.vector.riotx.core.ui.views.ReadReceiptsView
|
import im.vector.riotx.core.ui.views.ReadReceiptsView
|
||||||
import im.vector.riotx.core.utils.DimensionUtils.dpToPx
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import org.w3c.dom.Attr
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Children must override getViewType()
|
* Children must override getViewType()
|
||||||
|
@ -40,6 +39,9 @@ abstract class BaseEventItem<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
open var leftGuideline: Int = 0
|
open var leftGuideline: Int = 0
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var dimensionConverter: DimensionConverter
|
||||||
|
|
||||||
override fun bind(holder: H) {
|
override fun bind(holder: H) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.leftGuideline.setGuidelineBegin(leftGuideline)
|
holder.leftGuideline.setGuidelineBegin(leftGuideline)
|
||||||
|
|
|
@ -24,7 +24,6 @@ import androidx.core.widget.TextViewCompat
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.utils.containsOnlyEmojis
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.riotx.features.html.PillImageSpan
|
import im.vector.riotx.features.html.PillImageSpan
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -39,6 +38,8 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var message: CharSequence? = null
|
var message: CharSequence? = null
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
|
var useBigFont: Boolean = false
|
||||||
|
@EpoxyAttribute
|
||||||
var urlClickCallback: TimelineEventController.UrlClickCallback? = null
|
var urlClickCallback: TimelineEventController.UrlClickCallback? = null
|
||||||
|
|
||||||
// Better link movement methods fixes the issue when
|
// Better link movement methods fixes the issue when
|
||||||
|
@ -65,9 +66,7 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.messageView.movementMethod = mvmtMethod
|
holder.messageView.movementMethod = mvmtMethod
|
||||||
|
|
||||||
|
if (useBigFont) {
|
||||||
val msg = message ?: ""
|
|
||||||
if (msg.length <= 4 && containsOnlyEmojis(msg.toString())) {
|
|
||||||
holder.messageView.textSize = 44F
|
holder.messageView.textSize = 44F
|
||||||
} else {
|
} else {
|
||||||
holder.messageView.textSize = 14F
|
holder.messageView.textSize = 14F
|
||||||
|
|
|
@ -63,6 +63,18 @@ class FabMenuView @JvmOverloads constructor(context: Context, attrs: AttributeSe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun transitionToEnd() {
|
||||||
|
super.transitionToEnd()
|
||||||
|
|
||||||
|
createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_close)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transitionToStart() {
|
||||||
|
super.transitionToStart()
|
||||||
|
|
||||||
|
createRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_open)
|
||||||
|
}
|
||||||
|
|
||||||
fun show() {
|
fun show() {
|
||||||
isVisible = true
|
isVisible = true
|
||||||
createRoomButton.show()
|
createRoomButton.show()
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.login
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.transition.TransitionManager
|
import androidx.transition.TransitionManager
|
||||||
|
@ -68,12 +69,19 @@ class LoginFragment : VectorBaseFragment() {
|
||||||
homeServerField.focusChanges()
|
homeServerField.focusChanges()
|
||||||
.subscribe {
|
.subscribe {
|
||||||
if (!it) {
|
if (!it) {
|
||||||
// TODO Also when clicking on button?
|
|
||||||
viewModel.handle(LoginActions.UpdateHomeServer(homeServerField.text.toString()))
|
viewModel.handle(LoginActions.UpdateHomeServer(homeServerField.text.toString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disposeOnDestroy()
|
.disposeOnDestroy()
|
||||||
|
|
||||||
|
homeServerField.setOnEditorActionListener { _, actionId, _ ->
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||||
|
viewModel.handle(LoginActions.UpdateHomeServer(homeServerField.text.toString()))
|
||||||
|
return@setOnEditorActionListener true
|
||||||
|
}
|
||||||
|
return@setOnEditorActionListener false
|
||||||
|
}
|
||||||
|
|
||||||
val initHsUrl = viewModel.getInitialHomeServerUrl()
|
val initHsUrl = viewModel.getInitialHomeServerUrl()
|
||||||
if (initHsUrl != null) {
|
if (initHsUrl != null) {
|
||||||
homeServerField.setText(initHsUrl)
|
homeServerField.setText(initHsUrl)
|
||||||
|
@ -170,6 +178,10 @@ class LoginFragment : VectorBaseFragment() {
|
||||||
passwordContainer.isVisible = true
|
passwordContainer.isVisible = true
|
||||||
authenticateButton.isVisible = true
|
authenticateButton.isVisible = true
|
||||||
authenticateButtonSso.isVisible = false
|
authenticateButtonSso.isVisible = false
|
||||||
|
if (loginField.text.isNullOrBlank() && passwordField.text.isNullOrBlank()) {
|
||||||
|
//Jump focus to login
|
||||||
|
loginField.requestFocus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LoginMode.Sso -> {
|
LoginMode.Sso -> {
|
||||||
loginField.isVisible = false
|
loginField.isVisible = false
|
||||||
|
|
|
@ -137,16 +137,23 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun handleUpdateHomeserver(action: LoginActions.UpdateHomeServer) {
|
private fun handleUpdateHomeserver(action: LoginActions.UpdateHomeServer) = withState { state ->
|
||||||
currentTask?.cancel()
|
|
||||||
|
|
||||||
|
var newConfig : HomeServerConnectionConfig? = null
|
||||||
Try {
|
Try {
|
||||||
val homeServerUri = action.homeServerUrl
|
val homeServerUri = action.homeServerUrl
|
||||||
homeServerConnectionConfig = HomeServerConnectionConfig.Builder()
|
newConfig = HomeServerConnectionConfig.Builder()
|
||||||
.withHomeServerUri(homeServerUri)
|
.withHomeServerUri(homeServerUri)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Do not retry if we already have flows for this config -> causes infinite focus loop
|
||||||
|
if (newConfig?.homeServerUri?.toString() == homeServerConnectionConfig?.homeServerUri?.toString()
|
||||||
|
&& state.asyncHomeServerLoginFlowRequest is Success) return@withState
|
||||||
|
|
||||||
|
currentTask?.cancel()
|
||||||
|
homeServerConnectionConfig = newConfig
|
||||||
|
|
||||||
val homeServerConnectionConfigFinal = homeServerConnectionConfig
|
val homeServerConnectionConfigFinal = homeServerConnectionConfig
|
||||||
|
|
||||||
if (homeServerConnectionConfigFinal == null) {
|
if (homeServerConnectionConfigFinal == null) {
|
||||||
|
|
|
@ -32,13 +32,14 @@ import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
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.GlideRequest
|
import im.vector.riotx.core.glide.GlideRequest
|
||||||
import im.vector.riotx.core.utils.DimensionUtils.dpToPx
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ImageContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) {
|
class ImageContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
||||||
|
private val dimensionConverter: DimensionConverter) {
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Data(
|
data class Data(
|
||||||
|
@ -67,10 +68,12 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder:
|
||||||
val (width, height) = processSize(data, mode)
|
val (width, height) = processSize(data, mode)
|
||||||
imageView.layoutParams.height = height
|
imageView.layoutParams.height = height
|
||||||
imageView.layoutParams.width = width
|
imageView.layoutParams.width = width
|
||||||
|
// a11y
|
||||||
|
imageView.contentDescription = data.filename
|
||||||
|
|
||||||
createGlideRequest(data, mode, imageView, width, height)
|
createGlideRequest(data, mode, imageView, width, height)
|
||||||
.dontAnimate()
|
.dontAnimate()
|
||||||
.transform(RoundedCorners(dpToPx(8, imageView.context)))
|
.transform(RoundedCorners(dimensionConverter.dpToPx(8)))
|
||||||
.thumbnail(0.3f)
|
.thumbnail(0.3f)
|
||||||
.into(imageView)
|
.into(imageView)
|
||||||
|
|
||||||
|
@ -79,6 +82,9 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder:
|
||||||
fun renderFitTarget(data: Data, mode: Mode, imageView: ImageView, callback: ((Boolean) -> Unit)? = null) {
|
fun renderFitTarget(data: Data, mode: Mode, imageView: ImageView, callback: ((Boolean) -> Unit)? = null) {
|
||||||
val (width, height) = processSize(data, mode)
|
val (width, height) = processSize(data, mode)
|
||||||
|
|
||||||
|
// a11y
|
||||||
|
imageView.contentDescription = data.filename
|
||||||
|
|
||||||
createGlideRequest(data, mode, imageView, width, height)
|
createGlideRequest(data, mode, imageView, width, height)
|
||||||
.listener(object : RequestListener<Drawable> {
|
.listener(object : RequestListener<Drawable> {
|
||||||
override fun onLoadFailed(e: GlideException?,
|
override fun onLoadFailed(e: GlideException?,
|
||||||
|
@ -126,6 +132,9 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder:
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(data: Data, imageView: BigImageView) {
|
fun render(data: Data, imageView: BigImageView) {
|
||||||
|
// a11y
|
||||||
|
imageView.contentDescription = data.filename
|
||||||
|
|
||||||
val (width, height) = processSize(data, Mode.THUMBNAIL)
|
val (width, height) = processSize(data, Mode.THUMBNAIL)
|
||||||
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
|
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
|
||||||
val fullSize = contentUrlResolver.resolveFullSize(data.url)
|
val fullSize = contentUrlResolver.resolveFullSize(data.url)
|
||||||
|
|
|
@ -19,23 +19,21 @@ import im.vector.matrix.android.api.pushrules.Action
|
||||||
|
|
||||||
data class NotificationAction(
|
data class NotificationAction(
|
||||||
val shouldNotify: Boolean,
|
val shouldNotify: Boolean,
|
||||||
val highlight: Boolean = false,
|
val highlight: Boolean,
|
||||||
val soundName: String? = null
|
val soundName: String?
|
||||||
) {
|
)
|
||||||
companion object {
|
|
||||||
fun extractFrom(ruleActions: List<Action>): NotificationAction {
|
fun List<Action>.toNotificationAction(): NotificationAction {
|
||||||
var shouldNotify = false
|
var shouldNotify = false
|
||||||
var highlight = false
|
var highlight = false
|
||||||
var sound: String? = null
|
var sound: String? = null
|
||||||
ruleActions.forEach {
|
forEach { action ->
|
||||||
if (it.type == Action.Type.NOTIFY) shouldNotify = true
|
when (action) {
|
||||||
if (it.type == Action.Type.DONT_NOTIFY) shouldNotify = false
|
is Action.Notify -> shouldNotify = true
|
||||||
if (it.type == Action.Type.SET_TWEAK) {
|
is Action.DoNotNotify -> shouldNotify = false
|
||||||
if (it.tweak_action == "highlight") highlight = it.boolValue ?: false
|
is Action.Highlight -> highlight = action.highlight
|
||||||
if (it.tweak_action == "sound") sound = it.stringValue
|
is Action.Sound -> sound = action.sound
|
||||||
}
|
|
||||||
}
|
|
||||||
return NotificationAction(shouldNotify, highlight, sound)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return NotificationAction(shouldNotify, highlight, sound)
|
||||||
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class PushRuleTriggerListener @Inject constructor(
|
||||||
Timber.e("Called without active session")
|
Timber.e("Called without active session")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val notificationAction = NotificationAction.extractFrom(actions)
|
val notificationAction = actions.toNotificationAction()
|
||||||
if (notificationAction.shouldNotify) {
|
if (notificationAction.shouldNotify) {
|
||||||
val notifiableEvent = resolver.resolveEvent(event, session!!)
|
val notifiableEvent = resolver.resolveEvent(event, session!!)
|
||||||
if (notifiableEvent == null) {
|
if (notifiableEvent == null) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import androidx.preference.Preference
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.pushrules.RuleIds
|
import im.vector.matrix.android.api.pushrules.RuleIds
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleKind
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.di.ScreenComponent
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
|
@ -45,12 +46,13 @@ class VectorSettingsNotificationPreferenceFragment : VectorSettingsBaseFragment(
|
||||||
.find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL }
|
.find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL }
|
||||||
|
|
||||||
if (mRuleMaster == null) {
|
if (mRuleMaster == null) {
|
||||||
|
// The home server does not support RULE_ID_DISABLE_ALL, so hide the preference
|
||||||
pref.isVisible = false
|
pref.isVisible = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val areNotifEnabledAtAccountLevelt = !mRuleMaster.enabled
|
val areNotifEnabledAtAccountLevel = !mRuleMaster.enabled
|
||||||
(pref as SwitchPreference).isChecked = areNotifEnabledAtAccountLevelt
|
(pref as SwitchPreference).isChecked = areNotifEnabledAtAccountLevel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,19 +116,21 @@ class VectorSettingsNotificationPreferenceFragment : VectorSettingsBaseFragment(
|
||||||
.find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL }
|
.find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL }
|
||||||
?.let {
|
?.let {
|
||||||
//Trick, we must enable this room to disable notifications
|
//Trick, we must enable this room to disable notifications
|
||||||
pushRuleService.updatePushRuleEnableStatus("override", it, !switchPref.isChecked,
|
pushRuleService.updatePushRuleEnableStatus(RuleKind.OVERRIDE,
|
||||||
object : MatrixCallback<Unit> {
|
it,
|
||||||
|
!switchPref.isChecked,
|
||||||
|
object : MatrixCallback<Unit> {
|
||||||
|
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
pushRuleService.fetchPushRules()
|
// Push rules will be updated form the sync
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
override fun onFailure(failure: Throwable) {
|
||||||
//revert the check box
|
//revert the check box
|
||||||
switchPref.isChecked = !switchPref.isChecked
|
switchPref.isChecked = !switchPref.isChecked
|
||||||
Toast.makeText(activity, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,11 @@ import androidx.core.view.isVisible
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import com.airbnb.epoxy.EpoxyModelWithHolder
|
import com.airbnb.epoxy.EpoxyModelWithHolder
|
||||||
import im.vector.matrix.android.api.pushrules.Action
|
import im.vector.matrix.android.api.pushrules.getActions
|
||||||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
import im.vector.riotx.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.riotx.features.notifications.NotificationAction
|
import im.vector.riotx.features.notifications.toNotificationAction
|
||||||
|
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_pushrule_raw)
|
@EpoxyModelClass(layout = R.layout.item_pushrule_raw)
|
||||||
|
@ -50,12 +50,12 @@ abstract class PushRuleItem : EpoxyModelWithHolder<PushRuleItem.Holder>() {
|
||||||
holder.view.setBackgroundColor(ContextCompat.getColor(context, R.color.vector_silver_color))
|
holder.view.setBackgroundColor(ContextCompat.getColor(context, R.color.vector_silver_color))
|
||||||
holder.ruleId.text = "[Disabled] ${pushRule.ruleId}"
|
holder.ruleId.text = "[Disabled] ${pushRule.ruleId}"
|
||||||
}
|
}
|
||||||
val actions = Action.mapFrom(pushRule)
|
val actions = pushRule.getActions()
|
||||||
if (actions.isNullOrEmpty()) {
|
if (actions.isEmpty()) {
|
||||||
holder.actionIcon.isInvisible = true
|
holder.actionIcon.isInvisible = true
|
||||||
} else {
|
} else {
|
||||||
holder.actionIcon.isVisible = true
|
holder.actionIcon.isVisible = true
|
||||||
val notifAction = NotificationAction.extractFrom(actions)
|
val notifAction = actions.toNotificationAction()
|
||||||
|
|
||||||
if (notifAction.shouldNotify && !notifAction.soundName.isNullOrBlank()) {
|
if (notifAction.shouldNotify && !notifAction.soundName.isNullOrBlank()) {
|
||||||
holder.actionIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_notify_noisy))
|
holder.actionIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_notify_noisy))
|
||||||
|
|
|
@ -17,6 +17,7 @@ package im.vector.riotx.features.settings.troubleshoot
|
||||||
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.pushrules.RuleIds
|
import im.vector.matrix.android.api.pushrules.RuleIds
|
||||||
|
import im.vector.matrix.android.api.pushrules.RuleKind
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
|
@ -45,8 +46,7 @@ class TestAccountSettings @Inject constructor(private val stringProvider: String
|
||||||
override fun doFix() {
|
override fun doFix() {
|
||||||
if (manager?.diagStatus == TestStatus.RUNNING) return //wait before all is finished
|
if (manager?.diagStatus == TestStatus.RUNNING) return //wait before all is finished
|
||||||
|
|
||||||
// TODO Use constant for kind
|
session.updatePushRuleEnableStatus(RuleKind.OVERRIDE, defaultRule, !defaultRule.enabled,
|
||||||
session.updatePushRuleEnableStatus("override", defaultRule, !defaultRule.enabled,
|
|
||||||
object : MatrixCallback<Unit> {
|
object : MatrixCallback<Unit> {
|
||||||
|
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package im.vector.riotx.features.settings.troubleshoot
|
package im.vector.riotx.features.settings.troubleshoot
|
||||||
|
|
||||||
import im.vector.matrix.android.api.pushrules.Action
|
|
||||||
import im.vector.matrix.android.api.pushrules.RuleIds
|
import im.vector.matrix.android.api.pushrules.RuleIds
|
||||||
|
import im.vector.matrix.android.api.pushrules.getActions
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import im.vector.riotx.features.notifications.NotificationAction
|
import im.vector.riotx.features.notifications.toNotificationAction
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class TestBingRulesSettings @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
class TestBingRulesSettings @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
||||||
|
@ -29,15 +29,15 @@ class TestBingRulesSettings @Inject constructor(private val activeSessionHolder:
|
||||||
|
|
||||||
private val testedRules =
|
private val testedRules =
|
||||||
listOf(RuleIds.RULE_ID_CONTAIN_DISPLAY_NAME,
|
listOf(RuleIds.RULE_ID_CONTAIN_DISPLAY_NAME,
|
||||||
RuleIds.RULE_ID_CONTAIN_USER_NAME,
|
RuleIds.RULE_ID_CONTAIN_USER_NAME,
|
||||||
RuleIds.RULE_ID_ONE_TO_ONE_ROOM,
|
RuleIds.RULE_ID_ONE_TO_ONE_ROOM,
|
||||||
RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS)
|
RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS)
|
||||||
|
|
||||||
|
|
||||||
val ruleSettingsName = arrayOf(R.string.settings_containing_my_display_name,
|
val ruleSettingsName = arrayOf(R.string.settings_containing_my_display_name,
|
||||||
R.string.settings_containing_my_user_name,
|
R.string.settings_containing_my_user_name,
|
||||||
R.string.settings_messages_in_one_to_one,
|
R.string.settings_messages_in_one_to_one,
|
||||||
R.string.settings_messages_in_group_chat)
|
R.string.settings_messages_in_group_chat)
|
||||||
|
|
||||||
override fun perform() {
|
override fun perform() {
|
||||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||||
|
@ -50,8 +50,8 @@ class TestBingRulesSettings @Inject constructor(private val activeSessionHolder:
|
||||||
var oneOrMoreRuleAreSilent = false
|
var oneOrMoreRuleAreSilent = false
|
||||||
for ((index, ruleId) in testedRules.withIndex()) {
|
for ((index, ruleId) in testedRules.withIndex()) {
|
||||||
pushRules.find { it.ruleId == ruleId }?.let { rule ->
|
pushRules.find { it.ruleId == ruleId }?.let { rule ->
|
||||||
val actions = Action.mapFrom(rule) ?: return@let
|
val actions = rule.getActions()
|
||||||
val notifAction = NotificationAction.extractFrom(actions)
|
val notifAction = actions.toNotificationAction()
|
||||||
if (!rule.enabled || !notifAction.shouldNotify) {
|
if (!rule.enabled || !notifAction.shouldNotify) {
|
||||||
//off
|
//off
|
||||||
oneOrMoreRuleIsOff = true
|
oneOrMoreRuleIsOff = true
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
android:id="@+id/groupToolbarAvatarImageView"
|
android:id="@+id/groupToolbarAvatarImageView"
|
||||||
android:layout_width="32dp"
|
android:layout_width="32dp"
|
||||||
android:layout_height="32dp"
|
android:layout_height="32dp"
|
||||||
|
android:contentDescription="@string/a11y_open_drawer"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
|
@ -104,6 +104,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textUri"
|
android:inputType="textUri"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
android:maxLines="1" />
|
android:maxLines="1" />
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
|
android:accessibilityTraversalBefore="@+id/roomListEpoxyRecyclerView"
|
||||||
|
android:contentDescription="@string/a11y_create_direct_message"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/ic_fab_add_chat"
|
android:src="@drawable/ic_fab_add_chat"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
@ -45,6 +47,8 @@
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
|
android:accessibilityTraversalBefore="@+id/roomListEpoxyRecyclerView"
|
||||||
|
android:contentDescription="@string/a11y_create_room"
|
||||||
android:src="@drawable/ic_fab_add_room"
|
android:src="@drawable/ic_fab_add_room"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:maxImageSize="32dp"
|
app:maxImageSize="32dp"
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
android:layout_width="22dp"
|
android:layout_width="22dp"
|
||||||
android:layout_height="22dp"
|
android:layout_height="22dp"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:contentDescription="@string/action_close"
|
||||||
android:src="@drawable/ic_close_round"
|
android:src="@drawable/ic_close_round"
|
||||||
android:tint="@color/riotx_notice"
|
android:tint="@color/riotx_notice"
|
||||||
tools:ignore="MissingConstraints" />
|
tools:ignore="MissingConstraints" />
|
||||||
|
@ -88,6 +89,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:contentDescription="@string/send_attachment"
|
||||||
android:src="@drawable/ic_attachment"
|
android:src="@drawable/ic_attachment"
|
||||||
android:tint="?attr/colorAccent"
|
android:tint="?attr/colorAccent"
|
||||||
tools:ignore="MissingConstraints" />
|
tools:ignore="MissingConstraints" />
|
||||||
|
@ -107,6 +109,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:contentDescription="@string/send"
|
||||||
android:src="@drawable/ic_send"
|
android:src="@drawable/ic_send"
|
||||||
android:tint="?attr/colorAccent"
|
android:tint="?attr/colorAccent"
|
||||||
tools:ignore="MissingConstraints" />
|
tools:ignore="MissingConstraints" />
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
android:id="@+id/createRoomTouchGuard"
|
android:id="@+id/createRoomTouchGuard"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?riotx_touch_guard_bg" />
|
android:background="?riotx_touch_guard_bg"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="@string/a11y_create_menu_close"
|
||||||
|
android:focusable="true" />
|
||||||
|
|
||||||
<!-- Sub menu item 2 -->
|
<!-- Sub menu item 2 -->
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
@ -21,6 +24,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
|
android:accessibilityTraversalBefore="@+id/roomListEpoxyRecyclerView"
|
||||||
|
android:contentDescription="@string/a11y_create_room"
|
||||||
android:src="@drawable/ic_fab_add_room"
|
android:src="@drawable/ic_fab_add_room"
|
||||||
app:backgroundTint="#FFFFFF"
|
app:backgroundTint="#FFFFFF"
|
||||||
app:fabCustomSize="48dp"
|
app:fabCustomSize="48dp"
|
||||||
|
@ -35,6 +40,7 @@
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
android:text="@string/fab_menu_create_room" />
|
android:text="@string/fab_menu_create_room" />
|
||||||
|
|
||||||
<!-- Sub menu item 1 -->
|
<!-- Sub menu item 1 -->
|
||||||
|
@ -43,6 +49,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
|
android:accessibilityTraversalBefore="@+id/createRoomItemGroup"
|
||||||
|
android:contentDescription="@string/a11y_create_direct_message"
|
||||||
android:src="@drawable/ic_fab_add_chat"
|
android:src="@drawable/ic_fab_add_chat"
|
||||||
app:backgroundTint="#FFFFFF"
|
app:backgroundTint="#FFFFFF"
|
||||||
app:fabCustomSize="48dp"
|
app:fabCustomSize="48dp"
|
||||||
|
@ -57,6 +65,7 @@
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
android:text="@string/fab_menu_create_chat" />
|
android:text="@string/fab_menu_create_chat" />
|
||||||
|
|
||||||
<!-- Menu -->
|
<!-- Menu -->
|
||||||
|
@ -64,6 +73,8 @@
|
||||||
android:id="@+id/createRoomButton"
|
android:id="@+id/createRoomButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:accessibilityTraversalBefore="@+id/createRoomItemChat"
|
||||||
|
android:contentDescription="@string/a11y_create_menu_open"
|
||||||
android:src="@drawable/ic_fab_add"
|
android:src="@drawable/ic_fab_add"
|
||||||
app:maxImageSize="14dp" />
|
app:maxImageSize="14dp" />
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
|
android:contentDescription="@string/a11y_close_keys_backup_banner"
|
||||||
android:src="@drawable/ic_small_close"
|
android:src="@drawable/ic_small_close"
|
||||||
app:layout_constraintEnd_toEndOf="@id/view_keys_backup_banner_close"
|
app:layout_constraintEnd_toEndOf="@id/view_keys_backup_banner_close"
|
||||||
app:layout_constraintStart_toStartOf="@id/view_keys_backup_banner_close"
|
app:layout_constraintStart_toStartOf="@id/view_keys_backup_banner_close"
|
||||||
|
|
|
@ -3,23 +3,20 @@
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/bottom_action_home"
|
android:id="@+id/bottom_action_home"
|
||||||
android:contentDescription="@string/bottom_action_home"
|
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:icon="@drawable/ic_home_bottom_catchup"
|
android:icon="@drawable/ic_home_bottom_catchup"
|
||||||
android:title="" />
|
android:title="@string/bottom_action_home" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/bottom_action_people"
|
android:id="@+id/bottom_action_people"
|
||||||
android:contentDescription="@string/bottom_action_people_x"
|
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:icon="@drawable/ic_home_bottom_chat"
|
android:icon="@drawable/ic_home_bottom_chat"
|
||||||
android:title="" />
|
android:title="@string/bottom_action_people_x" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/bottom_action_rooms"
|
android:id="@+id/bottom_action_rooms"
|
||||||
android:contentDescription="@string/bottom_action_rooms"
|
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:icon="@drawable/ic_home_bottom_group"
|
android:icon="@drawable/ic_home_bottom_group"
|
||||||
android:title="" />
|
android:title="@string/bottom_action_rooms" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -13,4 +13,13 @@
|
||||||
|
|
||||||
<string name="error_network_timeout">Looks like the server is taking to long to respond, this can be caused by either poor connectivity or an error with our servers. Please try again in a while.</string>
|
<string name="error_network_timeout">Looks like the server is taking to long to respond, this can be caused by either poor connectivity or an error with our servers. Please try again in a while.</string>
|
||||||
|
|
||||||
|
<string name="send_attachment">Send attachment</string>
|
||||||
|
|
||||||
|
<string name="a11y_open_drawer">Open the navigation drawer</string>
|
||||||
|
<string name="a11y_create_menu_open">Open the create room menu</string>
|
||||||
|
<string name="a11y_create_menu_close">Close the create room menu…</string>
|
||||||
|
<string name="a11y_create_direct_message">Create a new direct conversation</string>
|
||||||
|
<string name="a11y_create_room">Create a new room</string>
|
||||||
|
<string name="a11y_close_keys_backup_banner">Close keys backup banner</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue