Merge branch 'develop' into feature/bma/jitsi_in_timeline
This commit is contained in:
commit
fade21de57
|
@ -1,4 +1,4 @@
|
||||||
Changes in Element 1.X.X (2020-XX-XX)
|
Changes in Element 1.0.17 (2020-XX-XX)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features ✨:
|
Features ✨:
|
||||||
|
@ -6,11 +6,15 @@ Features ✨:
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
- Create a WidgetItemFactory and use it for better rendering of Jitsi widget change (video conference)
|
- Create a WidgetItemFactory and use it for better rendering of Jitsi widget change (video conference)
|
||||||
|
- Open image from URL Preview (#2705)
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
- Bug in WidgetContent.computeURL() (#2767)
|
- Bug in WidgetContent.computeURL() (#2767)
|
||||||
- Duplicate thumbs | Mobile reactions for 👍 and 👎 are not the same as web (#2776)
|
- Duplicate thumbs | Mobile reactions for 👍 and 👎 are not the same as web (#2776)
|
||||||
- Join room by alias other federation error (#2778)
|
- Join room by alias other federation error (#2778)
|
||||||
|
- HTML unescaping for URL preview (#2766)
|
||||||
|
- URL preview on reply fallback (#2756)
|
||||||
|
- RTL: some arrows should be rotated in RTL (#2757)
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
@ -25,7 +29,7 @@ Test:
|
||||||
-
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
- Change app name from "Element (Riot.im)" to "Element"
|
||||||
|
|
||||||
Changes in Element 1.0.16 (2020-02-04)
|
Changes in Element 1.0.16 (2020-02-04)
|
||||||
===================================================
|
===================================================
|
||||||
|
@ -53,6 +57,7 @@ Bugfix 🐛:
|
||||||
- Widgets: Support $matrix_widget_id parameter (#2748)
|
- Widgets: Support $matrix_widget_id parameter (#2748)
|
||||||
- Data for Worker overload (#2721)
|
- Data for Worker overload (#2721)
|
||||||
- Fix multiple tasks
|
- Fix multiple tasks
|
||||||
|
- Object deletion in database is not complete (#2759)
|
||||||
|
|
||||||
SDK API changes ⚠️:
|
SDK API changes ⚠️:
|
||||||
- Increase targetSdkVersion to 30 (#2600)
|
- Increase targetSdkVersion to 30 (#2600)
|
||||||
|
|
|
@ -20,7 +20,7 @@ object ContentUtils {
|
||||||
val lines = repliedBody.lines()
|
val lines = repliedBody.lines()
|
||||||
var wellFormed = repliedBody.startsWith(">")
|
var wellFormed = repliedBody.startsWith(">")
|
||||||
var endOfPreviousFound = false
|
var endOfPreviousFound = false
|
||||||
val usefullines = ArrayList<String>()
|
val usefulLines = ArrayList<String>()
|
||||||
lines.forEach {
|
lines.forEach {
|
||||||
if (it == "") {
|
if (it == "") {
|
||||||
endOfPreviousFound = true
|
endOfPreviousFound = true
|
||||||
|
@ -29,10 +29,10 @@ object ContentUtils {
|
||||||
if (!endOfPreviousFound) {
|
if (!endOfPreviousFound) {
|
||||||
wellFormed = wellFormed && it.startsWith(">")
|
wellFormed = wellFormed && it.startsWith(">")
|
||||||
} else {
|
} else {
|
||||||
usefullines.add(it)
|
usefulLines.add(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return usefullines.joinToString("\n").takeIf { wellFormed } ?: repliedBody
|
return usefulLines.joinToString("\n").takeIf { wellFormed } ?: repliedBody
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractUsefulTextFromHtmlReply(repliedBody: String): String {
|
fun extractUsefulTextFromHtmlReply(repliedBody: String): String {
|
||||||
|
|
|
@ -21,11 +21,11 @@ import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
fun CryptoDeviceInfo.canonicalSignable(): String {
|
internal fun CryptoDeviceInfo.canonicalSignable(): String {
|
||||||
return JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableJSONDictionary())
|
return JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableJSONDictionary())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CryptoCrossSigningKey.canonicalSignable(): String {
|
internal fun CryptoCrossSigningKey.canonicalSignable(): String {
|
||||||
return JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableJSONDictionary())
|
return JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableJSONDictionary())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ fun String.fromBase64(): ByteArray {
|
||||||
/**
|
/**
|
||||||
* Decode the base 64. Return null in case of bad format. Should be used when parsing received data from external source
|
* Decode the base 64. Return null in case of bad format. Should be used when parsing received data from external source
|
||||||
*/
|
*/
|
||||||
fun String.fromBase64Safe(): ByteArray? {
|
internal fun String.fromBase64Safe(): ByteArray? {
|
||||||
return try {
|
return try {
|
||||||
Base64.decode(this, Base64.DEFAULT)
|
Base64.decode(this, Base64.DEFAULT)
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ data class CryptoCrossSigningKey(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Builder(
|
internal data class Builder(
|
||||||
val userId: String,
|
val userId: String,
|
||||||
val usage: KeyUsage,
|
val usage: KeyUsage,
|
||||||
private var base64Pkey: String? = null,
|
private var base64Pkey: String? = null,
|
||||||
|
@ -97,7 +97,7 @@ data class CryptoCrossSigningKey(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class KeyUsage(val value: String) {
|
internal enum class KeyUsage(val value: String) {
|
||||||
MASTER("master"),
|
MASTER("master"),
|
||||||
SELF_SIGNING("self_signing"),
|
SELF_SIGNING("self_signing"),
|
||||||
USER_SIGNING("user_signing")
|
USER_SIGNING("user_signing")
|
||||||
|
|
|
@ -83,6 +83,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
|
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntity
|
import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntity
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.model.createPrimaryKey
|
import org.matrix.android.sdk.internal.crypto.store.db.model.createPrimaryKey
|
||||||
|
import org.matrix.android.sdk.internal.crypto.store.db.model.deleteOnCascade
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.query.create
|
import org.matrix.android.sdk.internal.crypto.store.db.query.create
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.query.delete
|
import org.matrix.android.sdk.internal.crypto.store.db.query.delete
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.query.get
|
import org.matrix.android.sdk.internal.crypto.store.db.query.get
|
||||||
|
@ -94,6 +95,7 @@ import org.matrix.android.sdk.internal.di.CryptoDatabase
|
||||||
import org.matrix.android.sdk.internal.di.DeviceId
|
import org.matrix.android.sdk.internal.di.DeviceId
|
||||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
|
import org.matrix.android.sdk.internal.extensions.clearWith
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
import org.matrix.olm.OlmAccount
|
import org.matrix.olm.OlmAccount
|
||||||
import org.matrix.olm.OlmException
|
import org.matrix.olm.OlmException
|
||||||
|
@ -293,7 +295,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
realm.insertOrUpdate(entity)
|
realm.insertOrUpdate(entity)
|
||||||
}
|
}
|
||||||
// Ensure all other devices are deleted
|
// Ensure all other devices are deleted
|
||||||
u.devices.deleteAllFromRealm()
|
u.devices.clearWith { it.deleteOnCascade() }
|
||||||
u.devices.addAll(new)
|
u.devices.addAll(new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,7 +311,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
.let { userEntity ->
|
.let { userEntity ->
|
||||||
if (masterKey == null || selfSigningKey == null) {
|
if (masterKey == null || selfSigningKey == null) {
|
||||||
// The user has disabled cross signing?
|
// The user has disabled cross signing?
|
||||||
userEntity.crossSigningInfoEntity?.deleteFromRealm()
|
userEntity.crossSigningInfoEntity?.deleteOnCascade()
|
||||||
userEntity.crossSigningInfoEntity = null
|
userEntity.crossSigningInfoEntity = null
|
||||||
} else {
|
} else {
|
||||||
var shouldResetMyDevicesLocalTrust = false
|
var shouldResetMyDevicesLocalTrust = false
|
||||||
|
@ -1633,7 +1635,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
} else {
|
} else {
|
||||||
// Just override existing, caller should check and untrust id needed
|
// Just override existing, caller should check and untrust id needed
|
||||||
val existing = CrossSigningInfoEntity.getOrCreate(realm, userId)
|
val existing = CrossSigningInfoEntity.getOrCreate(realm, userId)
|
||||||
existing.crossSigningKeys.deleteAllFromRealm()
|
existing.crossSigningKeys.clearWith { it.deleteOnCascade() }
|
||||||
existing.crossSigningKeys.addAll(
|
existing.crossSigningKeys.addAll(
|
||||||
info.crossSigningKeys.map {
|
info.crossSigningKeys.map {
|
||||||
crossSigningKeysMapper.map(it)
|
crossSigningKeysMapper.map(it)
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto.store.db.model
|
package org.matrix.android.sdk.internal.crypto.store.db.model
|
||||||
|
|
||||||
import org.matrix.android.sdk.internal.crypto.model.KeyUsage
|
|
||||||
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
|
||||||
|
import org.matrix.android.sdk.internal.crypto.model.KeyUsage
|
||||||
|
import org.matrix.android.sdk.internal.extensions.clearWith
|
||||||
|
|
||||||
internal open class CrossSigningInfoEntity(
|
internal open class CrossSigningInfoEntity(
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
|
@ -56,3 +57,8 @@ internal open class CrossSigningInfoEntity(
|
||||||
info?.let { crossSigningKeys.add(it) }
|
info?.let { crossSigningKeys.add(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun CrossSigningInfoEntity.deleteOnCascade() {
|
||||||
|
crossSigningKeys.clearWith { it.deleteOnCascade() }
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -47,3 +47,8 @@ internal open class DeviceInfoEntity(
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun DeviceInfoEntity.deleteOnCascade() {
|
||||||
|
trustLevelEntity?.deleteFromRealm()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -30,3 +30,8 @@ internal open class KeyInfoEntity(
|
||||||
var signatures: String? = null,
|
var signatures: String? = null,
|
||||||
var trustLevelEntity: TrustLevelEntity? = null
|
var trustLevelEntity: TrustLevelEntity? = null
|
||||||
) : RealmObject()
|
) : RealmObject()
|
||||||
|
|
||||||
|
internal fun KeyInfoEntity.deleteOnCascade() {
|
||||||
|
trustLevelEntity?.deleteFromRealm()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -19,13 +19,20 @@ package org.matrix.android.sdk.internal.crypto.store.db.model
|
||||||
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
|
||||||
|
import org.matrix.android.sdk.internal.extensions.clearWith
|
||||||
|
|
||||||
internal open class UserEntity(
|
internal open class UserEntity(
|
||||||
@PrimaryKey var userId: String? = null,
|
@PrimaryKey var userId: String? = null,
|
||||||
var devices: RealmList<DeviceInfoEntity> = RealmList(),
|
var devices: RealmList<DeviceInfoEntity> = RealmList(),
|
||||||
var crossSigningInfoEntity: CrossSigningInfoEntity? = null,
|
var crossSigningInfoEntity: CrossSigningInfoEntity? = null,
|
||||||
var deviceTrackingStatus: Int = 0)
|
var deviceTrackingStatus: Int = 0
|
||||||
: RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun UserEntity.deleteOnCascade() {
|
||||||
|
devices.clearWith { it.deleteOnCascade() }
|
||||||
|
crossSigningInfoEntity?.deleteOnCascade()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -16,11 +16,12 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto.store.db.query
|
package org.matrix.android.sdk.internal.crypto.store.db.query
|
||||||
|
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity
|
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
|
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.kotlin.createObject
|
import io.realm.kotlin.createObject
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
|
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity
|
||||||
|
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
|
||||||
|
import org.matrix.android.sdk.internal.crypto.store.db.model.deleteOnCascade
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or create a user
|
* Get or create a user
|
||||||
|
@ -39,5 +40,5 @@ internal fun UserEntity.Companion.delete(realm: Realm, userId: String) {
|
||||||
realm.where<UserEntity>()
|
realm.where<UserEntity>()
|
||||||
.equalTo(UserEntityFields.USER_ID, userId)
|
.equalTo(UserEntityFields.USER_ID, userId)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
?.deleteFromRealm()
|
?.deleteOnCascade()
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import org.matrix.olm.OlmPkEncryption
|
||||||
import org.matrix.olm.OlmPkSigning
|
import org.matrix.olm.OlmPkSigning
|
||||||
import org.matrix.olm.OlmUtility
|
import org.matrix.olm.OlmUtility
|
||||||
|
|
||||||
fun <T> withOlmEncryption(block: (OlmPkEncryption) -> T): T {
|
internal fun <T> withOlmEncryption(block: (OlmPkEncryption) -> T): T {
|
||||||
val olmPkEncryption = OlmPkEncryption()
|
val olmPkEncryption = OlmPkEncryption()
|
||||||
try {
|
try {
|
||||||
return block(olmPkEncryption)
|
return block(olmPkEncryption)
|
||||||
|
@ -30,7 +30,7 @@ fun <T> withOlmEncryption(block: (OlmPkEncryption) -> T): T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> withOlmDecryption(block: (OlmPkDecryption) -> T): T {
|
internal fun <T> withOlmDecryption(block: (OlmPkDecryption) -> T): T {
|
||||||
val olmPkDecryption = OlmPkDecryption()
|
val olmPkDecryption = OlmPkDecryption()
|
||||||
try {
|
try {
|
||||||
return block(olmPkDecryption)
|
return block(olmPkDecryption)
|
||||||
|
@ -39,7 +39,7 @@ fun <T> withOlmDecryption(block: (OlmPkDecryption) -> T): T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> withOlmSigning(block: (OlmPkSigning) -> T): T {
|
internal fun <T> withOlmSigning(block: (OlmPkSigning) -> T): T {
|
||||||
val olmPkSigning = OlmPkSigning()
|
val olmPkSigning = OlmPkSigning()
|
||||||
try {
|
try {
|
||||||
return block(olmPkSigning)
|
return block(olmPkSigning)
|
||||||
|
@ -48,7 +48,7 @@ fun <T> withOlmSigning(block: (OlmPkSigning) -> T): T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> withOlmUtility(block: (OlmUtility) -> T): T {
|
internal fun <T> withOlmUtility(block: (OlmUtility) -> T): T {
|
||||||
val olmUtility = OlmUtility()
|
val olmUtility = OlmUtility()
|
||||||
try {
|
try {
|
||||||
return block(olmUtility)
|
return block(olmUtility)
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.database
|
package org.matrix.android.sdk.internal.database
|
||||||
|
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.internal.database.helper.nextDisplayIndex
|
import org.matrix.android.sdk.internal.database.helper.nextDisplayIndex
|
||||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.ChunkEntityFields
|
import org.matrix.android.sdk.internal.database.model.ChunkEntityFields
|
||||||
|
@ -23,14 +27,11 @@ import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
|
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
|
||||||
|
import org.matrix.android.sdk.internal.database.model.deleteOnCascade
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.session.SessionLifecycleObserver
|
import org.matrix.android.sdk.internal.session.SessionLifecycleObserver
|
||||||
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
|
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||||
import io.realm.Realm
|
|
||||||
import io.realm.RealmConfiguration
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ internal class DatabaseCleaner @Inject constructor(@SessionDatabase private val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun cleanUp(realm: Realm, threshold: Long) {
|
private fun cleanUp(realm: Realm, threshold: Long) {
|
||||||
val numberOfEvents = realm.where(EventEntity::class.java).findAll().size
|
val numberOfEvents = realm.where(EventEntity::class.java).findAll().size
|
||||||
val numberOfTimelineEvents = realm.where(TimelineEventEntity::class.java).findAll().size
|
val numberOfTimelineEvents = realm.where(TimelineEventEntity::class.java).findAll().size
|
||||||
Timber.v("Number of events in db: $numberOfEvents | Number of timeline events in db: $numberOfTimelineEvents")
|
Timber.v("Number of events in db: $numberOfEvents | Number of timeline events in db: $numberOfTimelineEvents")
|
||||||
|
@ -76,20 +77,7 @@ internal class DatabaseCleaner @Inject constructor(@SessionDatabase private val
|
||||||
chunk.numberOfTimelineEvents = chunk.numberOfTimelineEvents - eventsToRemove.size
|
chunk.numberOfTimelineEvents = chunk.numberOfTimelineEvents - eventsToRemove.size
|
||||||
eventsToRemove.forEach {
|
eventsToRemove.forEach {
|
||||||
val canDeleteRoot = it.root?.stateKey == null
|
val canDeleteRoot = it.root?.stateKey == null
|
||||||
if (canDeleteRoot) {
|
it.deleteOnCascade(canDeleteRoot)
|
||||||
it.root?.deleteFromRealm()
|
|
||||||
}
|
|
||||||
it.readReceipts?.readReceipts?.deleteAllFromRealm()
|
|
||||||
it.readReceipts?.deleteFromRealm()
|
|
||||||
it.annotations?.apply {
|
|
||||||
editSummary?.deleteFromRealm()
|
|
||||||
pollResponseSummary?.deleteFromRealm()
|
|
||||||
referencesSummaryEntity?.deleteFromRealm()
|
|
||||||
reactionsSummary.deleteAllFromRealm()
|
|
||||||
}
|
|
||||||
it.annotations?.deleteFromRealm()
|
|
||||||
it.readReceipts?.deleteFromRealm()
|
|
||||||
it.deleteFromRealm()
|
|
||||||
}
|
}
|
||||||
// We reset the prevToken so we will need to fetch again.
|
// We reset the prevToken so we will need to fetch again.
|
||||||
chunk.prevToken = null
|
chunk.prevToken = null
|
||||||
|
|
|
@ -38,12 +38,6 @@ import io.realm.Sort
|
||||||
import io.realm.kotlin.createObject
|
import io.realm.kotlin.createObject
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
internal fun ChunkEntity.deleteOnCascade() {
|
|
||||||
assertIsManaged()
|
|
||||||
this.timelineEvents.deleteAllFromRealm()
|
|
||||||
this.deleteFromRealm()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun ChunkEntity.merge(roomId: String, chunkToMerge: ChunkEntity, direction: PaginationDirection) {
|
internal fun ChunkEntity.merge(roomId: String, chunkToMerge: ChunkEntity, direction: PaginationDirection) {
|
||||||
assertIsManaged()
|
assertIsManaged()
|
||||||
val localRealm = this.realm
|
val localRealm = this.realm
|
||||||
|
|
|
@ -19,12 +19,7 @@ package org.matrix.android.sdk.internal.database.helper
|
||||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
||||||
|
|
||||||
internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
|
internal fun RoomEntity.addIfNecessary(chunkEntity: ChunkEntity) {
|
||||||
chunks.remove(chunkEntity)
|
|
||||||
chunkEntity.deleteOnCascade()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun RoomEntity.addOrUpdate(chunkEntity: ChunkEntity) {
|
|
||||||
if (!chunks.contains(chunkEntity)) {
|
if (!chunks.contains(chunkEntity)) {
|
||||||
chunks.add(chunkEntity)
|
chunks.add(chunkEntity)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.database.helper
|
||||||
|
|
||||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
|
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
|
||||||
import org.matrix.android.sdk.internal.extensions.assertIsManaged
|
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
|
||||||
internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long {
|
internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long {
|
||||||
|
@ -29,11 +28,3 @@ internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long {
|
||||||
currentIdNum.toLong() + 1
|
currentIdNum.toLong() + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun TimelineEventEntity.deleteOnCascade() {
|
|
||||||
assertIsManaged()
|
|
||||||
root?.deleteFromRealm()
|
|
||||||
annotations?.deleteFromRealm()
|
|
||||||
readReceipts?.deleteFromRealm()
|
|
||||||
deleteFromRealm()
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ import io.realm.RealmObject
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import io.realm.annotations.Index
|
import io.realm.annotations.Index
|
||||||
import io.realm.annotations.LinkingObjects
|
import io.realm.annotations.LinkingObjects
|
||||||
|
import org.matrix.android.sdk.internal.extensions.assertIsManaged
|
||||||
|
import org.matrix.android.sdk.internal.extensions.clearWith
|
||||||
|
|
||||||
internal open class ChunkEntity(@Index var prevToken: String? = null,
|
internal open class ChunkEntity(@Index var prevToken: String? = null,
|
||||||
// Because of gaps we can have several chunks with nextToken == null
|
// Because of gaps we can have several chunks with nextToken == null
|
||||||
|
@ -43,3 +45,12 @@ internal open class ChunkEntity(@Index var prevToken: String? = null,
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun ChunkEntity.deleteOnCascade(deleteStateEvents: Boolean, canDeleteRoot: Boolean) {
|
||||||
|
assertIsManaged()
|
||||||
|
if (deleteStateEvents) {
|
||||||
|
stateEvents.deleteAllFromRealm()
|
||||||
|
}
|
||||||
|
timelineEvents.clearWith { it.deleteOnCascade(canDeleteRoot) }
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -31,3 +31,11 @@ internal open class EventAnnotationsSummaryEntity(
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun EventAnnotationsSummaryEntity.deleteOnCascade() {
|
||||||
|
reactionsSummary.deleteAllFromRealm()
|
||||||
|
editSummary?.deleteFromRealm()
|
||||||
|
referencesSummaryEntity?.deleteFromRealm()
|
||||||
|
pollResponseSummary?.deleteFromRealm()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -40,3 +40,8 @@ internal open class PushRuleEntity(
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun PushRuleEntity.deleteOnCascade() {
|
||||||
|
conditions?.deleteAllFromRealm()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.database.model
|
||||||
import org.matrix.android.sdk.api.pushrules.RuleKind
|
import org.matrix.android.sdk.api.pushrules.RuleKind
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
|
import org.matrix.android.sdk.internal.extensions.clearWith
|
||||||
|
|
||||||
internal open class PushRulesEntity(
|
internal open class PushRulesEntity(
|
||||||
var scope: String = "",
|
var scope: String = "",
|
||||||
|
@ -35,3 +36,8 @@ internal open class PushRulesEntity(
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun PushRulesEntity.deleteOnCascade() {
|
||||||
|
pushRules.clearWith { it.deleteOnCascade() }
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.matrix.android.sdk.internal.database.model
|
package org.matrix.android.sdk.internal.database.model
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.session.pushers.PusherState
|
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
|
import org.matrix.android.sdk.api.session.pushers.PusherState
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// at java.lang.Thread.run(Thread.java:764)
|
// at java.lang.Thread.run(Thread.java:764)
|
||||||
|
@ -54,3 +54,8 @@ internal open class PusherEntity(
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun PusherEntity.deleteOnCascade() {
|
||||||
|
data?.deleteFromRealm()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -34,3 +34,8 @@ internal open class ReadReceiptsSummaryEntity(
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun ReadReceiptsSummaryEntity.deleteOnCascade() {
|
||||||
|
readReceipts.deleteAllFromRealm()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import io.realm.RealmObject
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import io.realm.annotations.Index
|
import io.realm.annotations.Index
|
||||||
import io.realm.annotations.LinkingObjects
|
import io.realm.annotations.LinkingObjects
|
||||||
|
import org.matrix.android.sdk.internal.extensions.assertIsManaged
|
||||||
|
|
||||||
internal open class TimelineEventEntity(var localId: Long = 0,
|
internal open class TimelineEventEntity(var localId: Long = 0,
|
||||||
@Index var eventId: String = "",
|
@Index var eventId: String = "",
|
||||||
|
@ -39,3 +40,13 @@ internal open class TimelineEventEntity(var localId: Long = 0,
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun TimelineEventEntity.deleteOnCascade(canDeleteRoot: Boolean) {
|
||||||
|
assertIsManaged()
|
||||||
|
if (canDeleteRoot) {
|
||||||
|
root?.deleteFromRealm()
|
||||||
|
}
|
||||||
|
annotations?.deleteOnCascade()
|
||||||
|
readReceipts?.deleteOnCascade()
|
||||||
|
deleteFromRealm()
|
||||||
|
}
|
||||||
|
|
|
@ -16,8 +16,18 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.extensions
|
package org.matrix.android.sdk.internal.extensions
|
||||||
|
|
||||||
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
|
|
||||||
internal fun RealmObject.assertIsManaged() {
|
internal fun RealmObject.assertIsManaged() {
|
||||||
check(isManaged) { "${javaClass.simpleName} entity should be managed to use this function" }
|
check(isManaged) { "${javaClass.simpleName} entity should be managed to use this function" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a RealmList by deleting all its items calling the provided lambda
|
||||||
|
*/
|
||||||
|
internal fun <T> RealmList<T>.clearWith(delete: (T) -> Unit) {
|
||||||
|
while (!isEmpty()) {
|
||||||
|
first()?.let { delete.invoke(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||||
import org.matrix.android.sdk.internal.network.executeRequest
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||||
|
import org.matrix.android.sdk.internal.util.unescapeHtml
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -73,9 +74,9 @@ internal class DefaultGetPreviewUrlTask @Inject constructor(
|
||||||
private fun JsonDict.toPreviewUrlData(url: String): PreviewUrlData {
|
private fun JsonDict.toPreviewUrlData(url: String): PreviewUrlData {
|
||||||
return PreviewUrlData(
|
return PreviewUrlData(
|
||||||
url = (get("og:url") as? String) ?: url,
|
url = (get("og:url") as? String) ?: url,
|
||||||
siteName = get("og:site_name") as? String,
|
siteName = (get("og:site_name") as? String)?.unescapeHtml(),
|
||||||
title = get("og:title") as? String,
|
title = (get("og:title") as? String)?.unescapeHtml(),
|
||||||
description = get("og:description") as? String,
|
description = (get("og:description") as? String)?.unescapeHtml(),
|
||||||
mxcUrl = get("og:image") as? String
|
mxcUrl = get("og:image") as? String
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.timeline.isReply
|
||||||
|
import org.matrix.android.sdk.api.util.ContentUtils
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class UrlsExtractor @Inject constructor() {
|
internal class UrlsExtractor @Inject constructor() {
|
||||||
|
@ -35,7 +37,14 @@ internal class UrlsExtractor @Inject constructor() {
|
||||||
|| it.msgType == MessageType.MSGTYPE_NOTICE
|
|| it.msgType == MessageType.MSGTYPE_NOTICE
|
||||||
|| it.msgType == MessageType.MSGTYPE_EMOTE
|
|| it.msgType == MessageType.MSGTYPE_EMOTE
|
||||||
}
|
}
|
||||||
?.body
|
?.let { messageContent ->
|
||||||
|
if (event.isReply()) {
|
||||||
|
// This is a reply, strip the reply fallback
|
||||||
|
ContentUtils.extractUsefulTextFromReply(messageContent.body)
|
||||||
|
} else {
|
||||||
|
messageContent.body
|
||||||
|
}
|
||||||
|
}
|
||||||
?.let { urlRegex.findAll(it) }
|
?.let { urlRegex.findAll(it) }
|
||||||
?.map { it.value }
|
?.map { it.value }
|
||||||
?.filter { it.startsWith("https://") || it.startsWith("http://") }
|
?.filter { it.startsWith("https://") || it.startsWith("http://") }
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.zhuinden.monarchy.Monarchy
|
||||||
import org.matrix.android.sdk.api.session.pushers.PusherState
|
import org.matrix.android.sdk.api.session.pushers.PusherState
|
||||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.PusherEntity
|
import org.matrix.android.sdk.internal.database.model.PusherEntity
|
||||||
|
import org.matrix.android.sdk.internal.database.model.deleteOnCascade
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||||
import org.matrix.android.sdk.internal.network.executeRequest
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
@ -41,7 +42,8 @@ internal class DefaultGetPushersTask @Inject constructor(
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
// clear existings?
|
// clear existings?
|
||||||
realm.where(PusherEntity::class.java)
|
realm.where(PusherEntity::class.java)
|
||||||
.findAll().deleteAllFromRealm()
|
.findAll()
|
||||||
|
.forEach { it.deleteOnCascade() }
|
||||||
response.pushers?.forEach { jsonPusher ->
|
response.pushers?.forEach { jsonPusher ->
|
||||||
jsonPusher.toEntity().also {
|
jsonPusher.toEntity().also {
|
||||||
it.state = PusherState.REGISTERED
|
it.state = PusherState.REGISTERED
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.pushrules.RuleSetKey
|
||||||
import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse
|
import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse
|
||||||
import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper
|
import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper
|
||||||
import org.matrix.android.sdk.internal.database.model.PushRulesEntity
|
import org.matrix.android.sdk.internal.database.model.PushRulesEntity
|
||||||
|
import org.matrix.android.sdk.internal.database.model.deleteOnCascade
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||||
|
@ -40,7 +41,7 @@ internal class DefaultSavePushRulesTask @Inject constructor(@SessionDatabase pri
|
||||||
// clear current push rules
|
// clear current push rules
|
||||||
realm.where(PushRulesEntity::class.java)
|
realm.where(PushRulesEntity::class.java)
|
||||||
.findAll()
|
.findAll()
|
||||||
.deleteAllFromRealm()
|
.forEach { it.deleteOnCascade() }
|
||||||
|
|
||||||
// Save only global rules for the moment
|
// Save only global rules for the moment
|
||||||
val globalRules = params.pushRules.global
|
val globalRules = params.pushRules.global
|
||||||
|
|
|
@ -22,16 +22,16 @@ import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||||
import org.matrix.android.sdk.internal.database.helper.addOrUpdate
|
import org.matrix.android.sdk.internal.database.helper.addIfNecessary
|
||||||
import org.matrix.android.sdk.internal.database.helper.addStateEvent
|
import org.matrix.android.sdk.internal.database.helper.addStateEvent
|
||||||
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
||||||
import org.matrix.android.sdk.internal.database.helper.deleteOnCascade
|
|
||||||
import org.matrix.android.sdk.internal.database.helper.merge
|
import org.matrix.android.sdk.internal.database.helper.merge
|
||||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||||
|
import org.matrix.android.sdk.internal.database.model.deleteOnCascade
|
||||||
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
||||||
import org.matrix.android.sdk.internal.database.query.create
|
import org.matrix.android.sdk.internal.database.query.create
|
||||||
import org.matrix.android.sdk.internal.database.query.find
|
import org.matrix.android.sdk.internal.database.query.find
|
||||||
|
@ -172,7 +172,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri
|
||||||
val currentLastForwardChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId)
|
val currentLastForwardChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId)
|
||||||
if (currentChunk != currentLastForwardChunk) {
|
if (currentChunk != currentLastForwardChunk) {
|
||||||
currentChunk.isLastForward = true
|
currentChunk.isLastForward = true
|
||||||
currentLastForwardChunk?.deleteOnCascade()
|
currentLastForwardChunk?.deleteOnCascade(deleteStateEvents = false, canDeleteRoot = false)
|
||||||
RoomSummaryEntity.where(realm, roomId).findFirst()?.apply {
|
RoomSummaryEntity.where(realm, roomId).findFirst()?.apply {
|
||||||
latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunksToDelete.forEach {
|
chunksToDelete.forEach {
|
||||||
it.deleteOnCascade()
|
it.deleteOnCascade(deleteStateEvents = false, canDeleteRoot = false)
|
||||||
}
|
}
|
||||||
val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId)
|
val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId)
|
||||||
val shouldUpdateSummary = roomSummaryEntity.latestPreviewableEvent == null
|
val shouldUpdateSummary = roomSummaryEntity.latestPreviewableEvent == null
|
||||||
|
@ -244,7 +244,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri
|
||||||
roomSummaryEntity.latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
roomSummaryEntity.latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
||||||
}
|
}
|
||||||
if (currentChunk.isValid) {
|
if (currentChunk.isValid) {
|
||||||
RoomEntity.where(realm, roomId).findFirst()?.addOrUpdate(currentChunk)
|
RoomEntity.where(realm, roomId).findFirst()?.addIfNecessary(currentChunk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,8 @@ import org.matrix.android.sdk.api.session.room.send.SendState
|
||||||
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
|
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
|
||||||
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||||
import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
|
import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
|
||||||
import org.matrix.android.sdk.internal.database.helper.addOrUpdate
|
import org.matrix.android.sdk.internal.database.helper.addIfNecessary
|
||||||
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
||||||
import org.matrix.android.sdk.internal.database.helper.deleteOnCascade
|
|
||||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||||
|
@ -40,6 +39,7 @@ import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity
|
||||||
|
import org.matrix.android.sdk.internal.database.model.deleteOnCascade
|
||||||
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
||||||
import org.matrix.android.sdk.internal.database.query.find
|
import org.matrix.android.sdk.internal.database.query.find
|
||||||
import org.matrix.android.sdk.internal.database.query.findLastForwardChunkOfRoom
|
import org.matrix.android.sdk.internal.database.query.findLastForwardChunkOfRoom
|
||||||
|
@ -48,6 +48,7 @@ import org.matrix.android.sdk.internal.database.query.getOrNull
|
||||||
import org.matrix.android.sdk.internal.database.query.where
|
import org.matrix.android.sdk.internal.database.query.where
|
||||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
|
import org.matrix.android.sdk.internal.extensions.clearWith
|
||||||
import org.matrix.android.sdk.internal.session.DefaultInitialSyncProgressService
|
import org.matrix.android.sdk.internal.session.DefaultInitialSyncProgressService
|
||||||
import org.matrix.android.sdk.internal.session.mapWithProgress
|
import org.matrix.android.sdk.internal.session.mapWithProgress
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
||||||
|
@ -175,7 +176,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||||
syncLocalTimestampMillis,
|
syncLocalTimestampMillis,
|
||||||
isInitialSync
|
isInitialSync
|
||||||
)
|
)
|
||||||
roomEntity.addOrUpdate(chunkEntity)
|
roomEntity.addIfNecessary(chunkEntity)
|
||||||
}
|
}
|
||||||
val hasRoomMember = roomSync.state?.events?.firstOrNull {
|
val hasRoomMember = roomSync.state?.events?.firstOrNull {
|
||||||
it.type == EventType.STATE_ROOM_MEMBER
|
it.type == EventType.STATE_ROOM_MEMBER
|
||||||
|
@ -263,7 +264,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||||
val leftMember = RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()
|
val leftMember = RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()
|
||||||
val membership = leftMember?.membership ?: Membership.LEAVE
|
val membership = leftMember?.membership ?: Membership.LEAVE
|
||||||
roomEntity.membership = membership
|
roomEntity.membership = membership
|
||||||
roomEntity.chunks.deleteAllFromRealm()
|
roomEntity.chunks.clearWith { it.deleteOnCascade(deleteStateEvents = true, canDeleteRoot = true) }
|
||||||
roomTypingUsersHandler.handle(realm, roomId, null)
|
roomTypingUsersHandler.handle(realm, roomId, null)
|
||||||
roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.LEAVE)
|
roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.LEAVE)
|
||||||
roomSummaryUpdater.update(realm, roomId, membership, roomSync.summary, roomSync.unreadNotifications)
|
roomSummaryUpdater.update(realm, roomId, membership, roomSync.summary, roomSync.unreadNotifications)
|
||||||
|
@ -340,7 +341,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Finally delete the local echo
|
// Finally delete the local echo
|
||||||
sendingEventEntity.deleteOnCascade()
|
sendingEventEntity.deleteOnCascade(true)
|
||||||
} else {
|
} else {
|
||||||
Timber.v("Can't find corresponding local echo for tx:$it")
|
Timber.v("Can't find corresponding local echo for tx:$it")
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,10 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.sync
|
package org.matrix.android.sdk.internal.session.sync
|
||||||
|
|
||||||
import com.squareup.moshi.Moshi
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmList
|
||||||
|
import io.realm.kotlin.where
|
||||||
import org.matrix.android.sdk.api.pushrules.RuleScope
|
import org.matrix.android.sdk.api.pushrules.RuleScope
|
||||||
import org.matrix.android.sdk.api.pushrules.RuleSetKey
|
import org.matrix.android.sdk.api.pushrules.RuleSetKey
|
||||||
import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse
|
import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse
|
||||||
|
@ -37,6 +39,7 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity
|
import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.UserAccountDataEntityFields
|
import org.matrix.android.sdk.internal.database.model.UserAccountDataEntityFields
|
||||||
|
import org.matrix.android.sdk.internal.database.model.deleteOnCascade
|
||||||
import org.matrix.android.sdk.internal.database.query.getDirectRooms
|
import org.matrix.android.sdk.internal.database.query.getDirectRooms
|
||||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||||
import org.matrix.android.sdk.internal.database.query.where
|
import org.matrix.android.sdk.internal.database.query.where
|
||||||
|
@ -50,9 +53,6 @@ import org.matrix.android.sdk.internal.session.sync.model.accountdata.IgnoredUse
|
||||||
import org.matrix.android.sdk.internal.session.sync.model.accountdata.UserAccountDataSync
|
import org.matrix.android.sdk.internal.session.sync.model.accountdata.UserAccountDataSync
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
|
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||||
import io.realm.Realm
|
|
||||||
import io.realm.RealmList
|
|
||||||
import io.realm.kotlin.where
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ internal class UserAccountDataSyncHandler @Inject constructor(
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
@UserId private val userId: String,
|
@UserId private val userId: String,
|
||||||
private val directChatsHelper: DirectChatsHelper,
|
private val directChatsHelper: DirectChatsHelper,
|
||||||
private val moshi: Moshi,
|
|
||||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask) {
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask) {
|
||||||
|
|
||||||
fun handle(realm: Realm, accountData: UserAccountDataSync?) {
|
fun handle(realm: Realm, accountData: UserAccountDataSync?) {
|
||||||
|
@ -113,7 +112,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
|
||||||
val pushRules = event.content.toModel<GetPushRulesResponse>() ?: return
|
val pushRules = event.content.toModel<GetPushRulesResponse>() ?: return
|
||||||
realm.where(PushRulesEntity::class.java)
|
realm.where(PushRulesEntity::class.java)
|
||||||
.findAll()
|
.findAll()
|
||||||
.deleteAllFromRealm()
|
.forEach { it.deleteOnCascade() }
|
||||||
|
|
||||||
// Save only global rules for the moment
|
// Save only global rules for the moment
|
||||||
val globalRules = pushRules.global
|
val globalRules = pushRules.global
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.util
|
||||||
|
|
||||||
|
import androidx.core.text.HtmlCompat
|
||||||
|
|
||||||
|
internal fun String.unescapeHtml(): String {
|
||||||
|
return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY).toString()
|
||||||
|
}
|
|
@ -210,7 +210,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
release {
|
release {
|
||||||
resValue "string", "app_name", "Element (Riot.im)"
|
resValue "string", "app_name", "Element"
|
||||||
|
|
||||||
resValue "bool", "debug_mode", "false"
|
resValue "bool", "debug_mode", "false"
|
||||||
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
|
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
|
||||||
|
|
|
@ -1687,6 +1687,10 @@ class RoomDetailFragment @Inject constructor(
|
||||||
roomDetailViewModel.handle(RoomDetailAction.DoNotShowPreviewUrlFor(eventId, url))
|
roomDetailViewModel.handle(RoomDetailAction.DoNotShowPreviewUrlFor(eventId, url))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPreviewUrlImageClicked(sharedView: View?, mxcUrl: String?, title: String?) {
|
||||||
|
navigator.openBigImageViewer(requireActivity(), sharedView, mxcUrl, title)
|
||||||
|
}
|
||||||
|
|
||||||
private fun onShareActionClicked(action: EventSharedAction.Share) {
|
private fun onShareActionClicked(action: EventSharedAction.Share) {
|
||||||
if (action.messageContent is MessageTextContent) {
|
if (action.messageContent is MessageTextContent) {
|
||||||
shareText(requireContext(), action.messageContent.body)
|
shareText(requireContext(), action.messageContent.body)
|
||||||
|
|
|
@ -87,12 +87,12 @@ import org.matrix.android.sdk.api.session.room.read.ReadService
|
||||||
import org.matrix.android.sdk.api.session.room.send.UserDraft
|
import org.matrix.android.sdk.api.session.room.send.UserDraft
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
|
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.getTextEditableContent
|
import org.matrix.android.sdk.api.session.room.timeline.getTextEditableContent
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||||
import org.matrix.android.sdk.api.util.appendParamToUrl
|
import org.matrix.android.sdk.api.util.appendParamToUrl
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
|
|
||||||
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
|
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
|
||||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
|
@ -754,8 +754,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
is SendMode.EDIT -> {
|
is SendMode.EDIT -> {
|
||||||
// is original event a reply?
|
// is original event a reply?
|
||||||
val inReplyTo = state.sendMode.timelineEvent.root.getClearContent().toModel<MessageContent>()?.relatesTo?.inReplyTo?.eventId
|
val inReplyTo = state.sendMode.timelineEvent.getRelationContent()?.inReplyTo?.eventId
|
||||||
?: state.sendMode.timelineEvent.root.content.toModel<EncryptedEventContent>()?.relatesTo?.inReplyTo?.eventId
|
|
||||||
if (inReplyTo != null) {
|
if (inReplyTo != null) {
|
||||||
// TODO check if same content?
|
// TODO check if same content?
|
||||||
room.getTimeLineEvent(inReplyTo)?.let {
|
room.getTimeLineEvent(inReplyTo)?.let {
|
||||||
|
|
|
@ -130,6 +130,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||||
interface PreviewUrlCallback {
|
interface PreviewUrlCallback {
|
||||||
fun onPreviewUrlClicked(url: String)
|
fun onPreviewUrlClicked(url: String)
|
||||||
fun onPreviewUrlCloseClicked(eventId: String, url: String)
|
fun onPreviewUrlCloseClicked(eventId: String, url: String)
|
||||||
|
fun onPreviewUrlImageClicked(sharedView: View?, mxcUrl: String?, title: String?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map eventId to adapter position
|
// Map eventId to adapter position
|
||||||
|
|
|
@ -23,7 +23,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.setTextOrHide
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
import im.vector.app.databinding.UrlPreviewBinding
|
import im.vector.app.databinding.ViewUrlPreviewBinding
|
||||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.app.features.media.ImageContentRenderer
|
import im.vector.app.features.media.ImageContentRenderer
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ class PreviewUrlView @JvmOverloads constructor(
|
||||||
defStyleAttr: Int = 0
|
defStyleAttr: Int = 0
|
||||||
) : ConstraintLayout(context, attrs, defStyleAttr), View.OnClickListener {
|
) : ConstraintLayout(context, attrs, defStyleAttr), View.OnClickListener {
|
||||||
|
|
||||||
private lateinit var views: UrlPreviewBinding
|
private lateinit var views: ViewUrlPreviewBinding
|
||||||
|
|
||||||
var delegate: TimelineEventController.PreviewUrlCallback? = null
|
var delegate: TimelineEventController.PreviewUrlCallback? = null
|
||||||
|
|
||||||
|
@ -80,6 +80,19 @@ class PreviewUrlView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onImageClick() {
|
||||||
|
when (val finalState = state) {
|
||||||
|
is PreviewUrlUiState.Data -> {
|
||||||
|
delegate?.onPreviewUrlImageClicked(
|
||||||
|
sharedView = views.urlPreviewImage,
|
||||||
|
mxcUrl = finalState.previewUrlData.mxcUrl,
|
||||||
|
title = finalState.previewUrlData.title
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onCloseClick() {
|
private fun onCloseClick() {
|
||||||
when (val finalState = state) {
|
when (val finalState = state) {
|
||||||
is PreviewUrlUiState.Data -> delegate?.onPreviewUrlCloseClicked(finalState.eventId, finalState.url)
|
is PreviewUrlUiState.Data -> delegate?.onPreviewUrlCloseClicked(finalState.eventId, finalState.url)
|
||||||
|
@ -90,10 +103,11 @@ class PreviewUrlView @JvmOverloads constructor(
|
||||||
// PRIVATE METHODS ****************************************************************************************************************************************
|
// PRIVATE METHODS ****************************************************************************************************************************************
|
||||||
|
|
||||||
private fun setupView() {
|
private fun setupView() {
|
||||||
inflate(context, R.layout.url_preview, this)
|
inflate(context, R.layout.view_url_preview, this)
|
||||||
views = UrlPreviewBinding.bind(this)
|
views = ViewUrlPreviewBinding.bind(this)
|
||||||
|
|
||||||
setOnClickListener(this)
|
setOnClickListener(this)
|
||||||
|
views.urlPreviewImage.setOnClickListener { onImageClick() }
|
||||||
views.urlPreviewClose.setOnClickListener { onCloseClick() }
|
views.urlPreviewClose.setOnClickListener { onCloseClick() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ import org.matrix.android.sdk.api.session.room.model.thirdparty.RoomDirectoryDat
|
||||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -256,14 +255,13 @@ class DefaultNavigator @Inject constructor(
|
||||||
context.startActivity(RoomProfileActivity.newIntent(context, roomId, directAccess))
|
context.startActivity(RoomProfileActivity.newIntent(context, roomId, directAccess))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openBigImageViewer(activity: Activity, sharedElement: View?, matrixItem: MatrixItem) {
|
override fun openBigImageViewer(activity: Activity, sharedElement: View?, mxcUrl: String?, title: String?) {
|
||||||
matrixItem.avatarUrl
|
mxcUrl
|
||||||
?.takeIf { it.isNotBlank() }
|
?.takeIf { it.isNotBlank() }
|
||||||
?.let { avatarUrl ->
|
?.let { avatarUrl ->
|
||||||
val intent = BigImageViewerActivity.newIntent(activity, matrixItem.getBestName(), avatarUrl)
|
val intent = BigImageViewerActivity.newIntent(activity, title, avatarUrl)
|
||||||
val options = sharedElement?.let {
|
val options = sharedElement?.let {
|
||||||
ActivityOptionsCompat.makeSceneTransitionAnimation(activity, it, ViewCompat.getTransitionName(it)
|
ActivityOptionsCompat.makeSceneTransitionAnimation(activity, it, ViewCompat.getTransitionName(it) ?: "")
|
||||||
?: "")
|
|
||||||
}
|
}
|
||||||
activity.startActivity(intent, options?.toBundle())
|
activity.startActivity(intent, options?.toBundle())
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,11 @@ interface Navigator {
|
||||||
|
|
||||||
fun openRoomProfile(context: Context, roomId: String, directAccess: Int? = null)
|
fun openRoomProfile(context: Context, roomId: String, directAccess: Int? = null)
|
||||||
|
|
||||||
fun openBigImageViewer(activity: Activity, sharedElement: View?, matrixItem: MatrixItem)
|
fun openBigImageViewer(activity: Activity, sharedElement: View?, matrixItem: MatrixItem) {
|
||||||
|
openBigImageViewer(activity, sharedElement, matrixItem.avatarUrl, matrixItem.getBestName())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openBigImageViewer(activity: Activity, sharedElement: View?, mxcUrl: String?, title: String?)
|
||||||
|
|
||||||
fun openPinCode(context: Context,
|
fun openPinCode(context: Context,
|
||||||
activityResultLauncher: ActivityResultLauncher<Intent>,
|
activityResultLauncher: ActivityResultLauncher<Intent>,
|
||||||
|
|
|
@ -25,9 +25,7 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.app.ActivityOptionsCompat
|
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.airbnb.mvrx.args
|
import com.airbnb.mvrx.args
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
|
@ -52,7 +50,6 @@ import im.vector.app.features.home.room.list.actions.RoomListActionsArgs
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||||
import im.vector.app.features.media.BigImageViewerActivity
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
@ -289,13 +286,7 @@ class RoomProfileFragment @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onAvatarClicked(view: View, matrixItem: MatrixItem.RoomItem) = withState(roomProfileViewModel) {
|
private fun onAvatarClicked(view: View, matrixItem: MatrixItem.RoomItem) {
|
||||||
matrixItem.avatarUrl
|
navigator.openBigImageViewer(requireActivity(), view, matrixItem)
|
||||||
?.takeIf { it.isNotEmpty() }
|
|
||||||
?.let { avatarUrl ->
|
|
||||||
val intent = BigImageViewerActivity.newIntent(requireContext(), matrixItem.getBestName(), avatarUrl)
|
|
||||||
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(requireActivity(), view, ViewCompat.getTransitionName(view) ?: "")
|
|
||||||
startActivity(intent, options.toBundle())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:width="7dp"
|
||||||
|
android:height="12dp"
|
||||||
|
android:viewportWidth="7"
|
||||||
|
android:viewportHeight="12">
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:pathData="M6,11l-5,-5 5,-5"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:strokeColor="#2E2F32"
|
||||||
|
android:strokeLineCap="round"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
tools:strokeColor="#FFAF0F" />
|
||||||
|
</vector>
|
|
@ -1,14 +1,16 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:width="7dp"
|
android:width="7dp"
|
||||||
android:height="12dp"
|
android:height="12dp"
|
||||||
android:viewportWidth="7"
|
android:viewportWidth="7"
|
||||||
android:viewportHeight="12">
|
android:viewportHeight="12">
|
||||||
<path
|
<path
|
||||||
android:pathData="M1,11l5,-5 -5,-5"
|
|
||||||
android:strokeLineJoin="round"
|
|
||||||
android:strokeWidth="2"
|
|
||||||
android:fillColor="#00000000"
|
android:fillColor="#00000000"
|
||||||
android:fillType="evenOdd"
|
android:fillType="evenOdd"
|
||||||
|
android:pathData="M1,11l5,-5 -5,-5"
|
||||||
|
android:strokeWidth="2"
|
||||||
android:strokeColor="#2E2F32"
|
android:strokeColor="#2E2F32"
|
||||||
android:strokeLineCap="round"/>
|
android:strokeLineCap="round"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
tools:strokeColor="#FFAF0F" />
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
android:insetRight="0dp"
|
android:insetRight="0dp"
|
||||||
android:insetBottom="0dp"
|
android:insetBottom="0dp"
|
||||||
android:padding="0dp"
|
android:padding="0dp"
|
||||||
|
android:rotationY="@integer/rtl_mirror_flip"
|
||||||
app:cornerRadius="17dp"
|
app:cornerRadius="17dp"
|
||||||
app:icon="@drawable/ic_qr_code_add"
|
app:icon="@drawable/ic_qr_code_add"
|
||||||
app:iconGravity="textStart"
|
app:iconGravity="textStart"
|
||||||
|
|
Loading…
Reference in New Issue