Realm: convert ContentScannerDatabase to realm-kotlin
This commit is contained in:
parent
c5883b3e7c
commit
af5bbe12f5
@ -16,7 +16,7 @@
|
||||
|
||||
package org.matrix.android.sdk.api.session.contentscanner
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
||||
@ -24,12 +24,14 @@ interface ContentScannerService {
|
||||
|
||||
val serverPublicKey: String?
|
||||
|
||||
//TODO: suspend
|
||||
fun getContentScannerServer(): String?
|
||||
fun setScannerUrl(url: String?)
|
||||
fun enableScanner(enabled: Boolean)
|
||||
suspend fun setScannerUrl(url: String?)
|
||||
suspend fun enableScanner(enabled: Boolean)
|
||||
//TODO: suspend
|
||||
fun isScannerEnabled(): Boolean
|
||||
fun getLiveStatusForFile(mxcUrl: String, fetchIfNeeded: Boolean = true, fileInfo: ElementToDecrypt? = null): LiveData<Optional<ScanStatusInfo>>
|
||||
fun getCachedScanResultForFile(mxcUrl: String): ScanStatusInfo?
|
||||
fun getLiveStatusForFile(mxcUrl: String, fetchIfNeeded: Boolean = true, fileInfo: ElementToDecrypt? = null): Flow<Optional<ScanStatusInfo>>
|
||||
suspend fun getCachedScanResultForFile(mxcUrl: String): ScanStatusInfo?
|
||||
|
||||
/**
|
||||
* Get the current public curve25519 key that the AV server is advertising.
|
||||
|
@ -90,7 +90,6 @@ internal class DefaultSession @Inject constructor(
|
||||
override val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
@SessionDatabase private val realmConfiguration: RealmConfiguration,
|
||||
@CryptoDatabase private val realmConfigurationCrypto: RealmConfiguration,
|
||||
@ContentScannerDatabase private val realmConfigurationContentScanner: RealmConfiguration,
|
||||
private val lifecycleObservers: Set<@JvmSuppressWildcards SessionLifecycleObserver>,
|
||||
private val sessionListeners: SessionListeners,
|
||||
private val roomService: Lazy<RoomService>,
|
||||
@ -266,7 +265,7 @@ internal class DefaultSession @Inject constructor(
|
||||
RealmDebugTools(realmConfiguration).logInfo("Session")
|
||||
RealmDebugTools(realmConfigurationCrypto).logInfo("Crypto")
|
||||
//RealmDebugTools(realmConfigurationIdentity).logInfo("Identity")
|
||||
RealmDebugTools(realmConfigurationContentScanner).logInfo("ContentScanner")
|
||||
//RealmDebugTools(realmConfigurationContentScanner).logInfo("ContentScanner")
|
||||
}
|
||||
|
||||
override fun getRealmConfigurations(): List<RealmConfiguration> {
|
||||
@ -274,7 +273,7 @@ internal class DefaultSession @Inject constructor(
|
||||
realmConfiguration,
|
||||
realmConfigurationCrypto,
|
||||
//realmConfigurationIdentity,
|
||||
realmConfigurationContentScanner,
|
||||
//realmConfigurationContentScanner,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -19,16 +19,20 @@ package org.matrix.android.sdk.internal.session.contentscanner
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.realm.RealmConfiguration
|
||||
import io.realm.kotlin.RealmConfiguration
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ContentScannerService
|
||||
import org.matrix.android.sdk.internal.database.RealmInstance
|
||||
import org.matrix.android.sdk.internal.database.RealmKeysUtils
|
||||
import org.matrix.android.sdk.internal.di.ContentScannerDatabase
|
||||
import org.matrix.android.sdk.internal.di.MatrixCoroutineScope
|
||||
import org.matrix.android.sdk.internal.di.SessionFilesDirectory
|
||||
import org.matrix.android.sdk.internal.di.UserMd5
|
||||
import org.matrix.android.sdk.internal.session.SessionModule
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import org.matrix.android.sdk.internal.session.contentscanner.data.ContentScannerStore
|
||||
import org.matrix.android.sdk.internal.session.contentscanner.db.ContentScannerRealmModule
|
||||
import org.matrix.android.sdk.internal.session.contentscanner.db.CONTENT_SCANNER_REALM_SCHEMA
|
||||
import org.matrix.android.sdk.internal.session.contentscanner.db.RealmContentScannerStore
|
||||
import org.matrix.android.sdk.internal.session.contentscanner.tasks.DefaultDownloadEncryptedTask
|
||||
import org.matrix.android.sdk.internal.session.contentscanner.tasks.DefaultGetServerPublicKeyTask
|
||||
@ -48,22 +52,35 @@ internal abstract class ContentScannerModule {
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@ContentScannerDatabase
|
||||
@SessionScope
|
||||
fun providesContentScannerRealmConfiguration(
|
||||
fun providesRealmConfiguration(
|
||||
realmKeysUtils: RealmKeysUtils,
|
||||
@SessionFilesDirectory directory: File,
|
||||
@UserMd5 userMd5: String
|
||||
): RealmConfiguration {
|
||||
return RealmConfiguration.Builder()
|
||||
.directory(directory)
|
||||
.name("matrix-sdk-content-scanning.realm")
|
||||
return RealmConfiguration.Builder(CONTENT_SCANNER_REALM_SCHEMA)
|
||||
.directory(directory.path)
|
||||
.apply {
|
||||
realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5))
|
||||
}
|
||||
.allowWritesOnUiThread(true)
|
||||
.modules(ContentScannerRealmModule())
|
||||
.name("matrix-sdk-content-scanning.realm")
|
||||
.build()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@ContentScannerDatabase
|
||||
@SessionScope
|
||||
fun providesRealmInstance(
|
||||
@ContentScannerDatabase realmConfiguration: RealmConfiguration,
|
||||
@MatrixCoroutineScope matrixCoroutineScope: CoroutineScope,
|
||||
matrixCoroutineDispatchers: MatrixCoroutineDispatchers
|
||||
): RealmInstance {
|
||||
return RealmInstance(
|
||||
coroutineScope = matrixCoroutineScope,
|
||||
realmConfiguration = realmConfiguration,
|
||||
coroutineDispatcher = matrixCoroutineDispatchers.io
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Binds
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.contentscanner
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import dagger.Lazy
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.OkHttpClient
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ContentScannerService
|
||||
@ -91,7 +91,7 @@ internal class DefaultContentScannerService @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
override fun setScannerUrl(url: String?) = contentScannerStore.setScannerUrl(url).also {
|
||||
override suspend fun setScannerUrl(url: String?) = contentScannerStore.setScannerUrl(url).also {
|
||||
if (url == null) {
|
||||
contentScannerApiProvider.contentScannerApi = null
|
||||
serverPublicKey = null
|
||||
@ -111,18 +111,17 @@ internal class DefaultContentScannerService @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun enableScanner(enabled: Boolean) = contentScannerStore.enableScanner(enabled)
|
||||
override suspend fun enableScanner(enabled: Boolean) = contentScannerStore.enableScanner(enabled)
|
||||
|
||||
override fun isScannerEnabled(): Boolean = contentScannerStore.isScanEnabled()
|
||||
|
||||
override fun getCachedScanResultForFile(mxcUrl: String): ScanStatusInfo? {
|
||||
override suspend fun getCachedScanResultForFile(mxcUrl: String): ScanStatusInfo? {
|
||||
return contentScannerStore.getScanResult(mxcUrl)
|
||||
}
|
||||
|
||||
override fun getLiveStatusForFile(mxcUrl: String, fetchIfNeeded: Boolean, fileInfo: ElementToDecrypt?): LiveData<Optional<ScanStatusInfo>> {
|
||||
val data = contentScannerStore.getLiveScanResult(mxcUrl)
|
||||
if (fetchIfNeeded && !contentScannerStore.isScanResultKnownOrInProgress(mxcUrl, getContentScannerServer())) {
|
||||
override fun getLiveStatusForFile(mxcUrl: String, fetchIfNeeded: Boolean, fileInfo: ElementToDecrypt?): Flow<Optional<ScanStatusInfo>> {
|
||||
taskExecutor.executorScope.launch {
|
||||
if (fetchIfNeeded && !contentScannerStore.isScanResultKnownOrInProgress(mxcUrl, getContentScannerServer())) {
|
||||
try {
|
||||
getScanResultForAttachment(mxcUrl, fileInfo)
|
||||
} catch (failure: Throwable) {
|
||||
@ -130,6 +129,6 @@ internal class DefaultContentScannerService @Inject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
return contentScannerStore.getLiveScanResult(mxcUrl)
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.session.contentscanner
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ContentScannerService
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ScanStatusInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
|
||||
@ -46,21 +48,21 @@ internal class DisabledContentScannerService @Inject constructor() : ContentScan
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setScannerUrl(url: String?) {
|
||||
override suspend fun setScannerUrl(url: String?) {
|
||||
}
|
||||
|
||||
override fun enableScanner(enabled: Boolean) {
|
||||
override suspend fun enableScanner(enabled: Boolean) {
|
||||
}
|
||||
|
||||
override fun isScannerEnabled(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getLiveStatusForFile(mxcUrl: String, fetchIfNeeded: Boolean, fileInfo: ElementToDecrypt?): LiveData<Optional<ScanStatusInfo>> {
|
||||
return MutableLiveData()
|
||||
override fun getLiveStatusForFile(mxcUrl: String, fetchIfNeeded: Boolean, fileInfo: ElementToDecrypt?): Flow<Optional<ScanStatusInfo>> {
|
||||
return emptyFlow()
|
||||
}
|
||||
|
||||
override fun getCachedScanResultForFile(mxcUrl: String): ScanStatusInfo? {
|
||||
override suspend fun getCachedScanResultForFile(mxcUrl: String): ScanStatusInfo? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.contentscanner.data
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ScanState
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ScanStatusInfo
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
@ -25,16 +25,16 @@ internal interface ContentScannerStore {
|
||||
|
||||
fun getScannerUrl(): String?
|
||||
|
||||
fun setScannerUrl(url: String?)
|
||||
suspend fun setScannerUrl(url: String?)
|
||||
|
||||
fun enableScanner(enabled: Boolean)
|
||||
suspend fun enableScanner(enabled: Boolean)
|
||||
|
||||
fun isScanEnabled(): Boolean
|
||||
|
||||
fun getScanResult(mxcUrl: String): ScanStatusInfo?
|
||||
fun getLiveScanResult(mxcUrl: String): LiveData<Optional<ScanStatusInfo>>
|
||||
fun isScanResultKnownOrInProgress(mxcUrl: String, scannerUrl: String?): Boolean
|
||||
suspend fun getScanResult(mxcUrl: String): ScanStatusInfo?
|
||||
fun getLiveScanResult(mxcUrl: String): Flow<Optional<ScanStatusInfo>>
|
||||
suspend fun isScanResultKnownOrInProgress(mxcUrl: String, scannerUrl: String?): Boolean
|
||||
|
||||
fun updateStateForContent(mxcUrl: String, state: ScanState, scannerUrl: String?)
|
||||
fun updateScanResultForContent(mxcUrl: String, scannerUrl: String?, state: ScanState, humanReadable: String)
|
||||
suspend fun updateStateForContent(mxcUrl: String, state: ScanState, scannerUrl: String?)
|
||||
suspend fun updateScanResultForContent(mxcUrl: String, scannerUrl: String?, state: ScanState, humanReadable: String)
|
||||
}
|
||||
|
@ -16,22 +16,19 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.contentscanner.db
|
||||
|
||||
import io.realm.RealmModel
|
||||
import io.realm.annotations.Index
|
||||
import io.realm.annotations.RealmClass
|
||||
import io.realm.kotlin.types.RealmObject
|
||||
import io.realm.kotlin.types.annotations.Index
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ScanState
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ScanStatusInfo
|
||||
|
||||
@RealmClass
|
||||
internal open class ContentScanResultEntity(
|
||||
internal class ContentScanResultEntity : RealmObject {
|
||||
@Index
|
||||
var mediaUrl: String? = null,
|
||||
var scanStatusString: String? = null,
|
||||
var humanReadableMessage: String? = null,
|
||||
var scanDateTimestamp: Long? = null,
|
||||
var mediaUrl: String? = null
|
||||
var scanStatusString: String? = null
|
||||
var humanReadableMessage: String? = null
|
||||
var scanDateTimestamp: Long? = null
|
||||
var scannerUrl: String? = null
|
||||
) : RealmModel {
|
||||
|
||||
var scanResult: ScanState
|
||||
get() {
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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.session.contentscanner.db
|
||||
|
||||
import io.realm.Realm
|
||||
import io.realm.kotlin.createObject
|
||||
import io.realm.kotlin.where
|
||||
|
||||
internal fun ContentScanResultEntity.Companion.get(realm: Realm, attachmentUrl: String, contentScannerUrl: String?): ContentScanResultEntity? {
|
||||
return realm.where<ContentScanResultEntity>()
|
||||
.equalTo(ContentScanResultEntityFields.MEDIA_URL, attachmentUrl)
|
||||
.apply {
|
||||
contentScannerUrl?.let {
|
||||
equalTo(ContentScanResultEntityFields.SCANNER_URL, it)
|
||||
}
|
||||
}
|
||||
.findFirst()
|
||||
}
|
||||
|
||||
internal fun ContentScanResultEntity.Companion.getOrCreate(
|
||||
realm: Realm,
|
||||
attachmentUrl: String,
|
||||
contentScannerUrl: String?,
|
||||
currentTimeMillis: Long
|
||||
): ContentScanResultEntity {
|
||||
return ContentScanResultEntity.get(realm, attachmentUrl, contentScannerUrl)
|
||||
?: realm.createObject<ContentScanResultEntity>().also {
|
||||
it.mediaUrl = attachmentUrl
|
||||
it.scanDateTimestamp = currentTimeMillis
|
||||
it.scannerUrl = contentScannerUrl
|
||||
}
|
||||
}
|
@ -16,14 +16,12 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.contentscanner.db
|
||||
|
||||
import io.realm.RealmModel
|
||||
import io.realm.annotations.RealmClass
|
||||
import io.realm.kotlin.types.RealmObject
|
||||
|
||||
@RealmClass
|
||||
internal open class ContentScannerInfoEntity(
|
||||
var serverUrl: String? = null,
|
||||
internal open class ContentScannerInfoEntity : RealmObject {
|
||||
var serverUrl: String? = null
|
||||
var enabled: Boolean? = null
|
||||
) : RealmModel {
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
|
@ -16,16 +16,7 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.contentscanner.db
|
||||
|
||||
import io.realm.annotations.RealmModule
|
||||
|
||||
/**
|
||||
* Realm module for content scanner classes.
|
||||
*/
|
||||
@RealmModule(
|
||||
library = true,
|
||||
classes = [
|
||||
internal val CONTENT_SCANNER_REALM_SCHEMA = setOf(
|
||||
ContentScannerInfoEntity::class,
|
||||
ContentScanResultEntity::class
|
||||
]
|
||||
)
|
||||
internal class ContentScannerRealmModule
|
||||
|
@ -16,18 +16,18 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.contentscanner.db
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import io.realm.kotlin.createObject
|
||||
import io.realm.kotlin.where
|
||||
import io.realm.kotlin.TypedRealm
|
||||
import io.realm.kotlin.query.RealmQuery
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapConcat
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ScanState
|
||||
import org.matrix.android.sdk.api.session.contentscanner.ScanStatusInfo
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.api.util.toOptional
|
||||
import org.matrix.android.sdk.internal.database.RealmInstance
|
||||
import org.matrix.android.sdk.internal.database.await
|
||||
import org.matrix.android.sdk.internal.di.ContentScannerDatabase
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import org.matrix.android.sdk.internal.session.contentscanner.data.ContentScannerStore
|
||||
@ -38,108 +38,124 @@ import javax.inject.Inject
|
||||
@SessionScope
|
||||
internal class RealmContentScannerStore @Inject constructor(
|
||||
@ContentScannerDatabase
|
||||
private val realmConfiguration: RealmConfiguration,
|
||||
private val realmInstance: RealmInstance,
|
||||
private val clock: Clock,
|
||||
) : ContentScannerStore {
|
||||
|
||||
private val monarchy = Monarchy.Builder()
|
||||
.setRealmConfiguration(realmConfiguration)
|
||||
.build()
|
||||
|
||||
override fun getScannerUrl(): String? {
|
||||
return monarchy.fetchAllMappedSync(
|
||||
{ realm ->
|
||||
realm.where<ContentScannerInfoEntity>()
|
||||
}, {
|
||||
it.serverUrl
|
||||
}
|
||||
).firstOrNull()
|
||||
return realmInstance.getBlockingRealm()
|
||||
.queryContentScannerInfoEntity()
|
||||
.first()
|
||||
.find()
|
||||
?.serverUrl
|
||||
}
|
||||
|
||||
override fun setScannerUrl(url: String?) {
|
||||
monarchy.runTransactionSync { realm ->
|
||||
val info = realm.where<ContentScannerInfoEntity>().findFirst()
|
||||
?: realm.createObject()
|
||||
info.serverUrl = url
|
||||
}
|
||||
override suspend fun setScannerUrl(url: String?) = upsertContentScannerInfoEntity {
|
||||
it.serverUrl = url
|
||||
}
|
||||
|
||||
override fun enableScanner(enabled: Boolean) {
|
||||
monarchy.runTransactionSync { realm ->
|
||||
val info = realm.where<ContentScannerInfoEntity>().findFirst()
|
||||
?: realm.createObject()
|
||||
info.enabled = enabled
|
||||
override suspend fun enableScanner(enabled: Boolean) = upsertContentScannerInfoEntity {
|
||||
it.enabled = enabled
|
||||
}
|
||||
|
||||
private suspend fun upsertContentScannerInfoEntity(operation: (ContentScannerInfoEntity) -> Unit) {
|
||||
realmInstance.write {
|
||||
val contentScannerInfoEntity = queryContentScannerInfoEntity().first().find()
|
||||
if (contentScannerInfoEntity != null) {
|
||||
operation(contentScannerInfoEntity)
|
||||
} else {
|
||||
val newContentScannerInfoEntity = ContentScannerInfoEntity().apply {
|
||||
operation(this)
|
||||
}
|
||||
copyToRealm(newContentScannerInfoEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isScanEnabled(): Boolean {
|
||||
return monarchy.fetchAllMappedSync(
|
||||
{ realm ->
|
||||
realm.where<ContentScannerInfoEntity>()
|
||||
}, {
|
||||
it.enabled.orFalse() && it.serverUrl?.isValidUrl().orFalse()
|
||||
}
|
||||
).firstOrNull().orFalse()
|
||||
val contentScannerInfoEntity = realmInstance.getBlockingRealm()
|
||||
.queryContentScannerInfoEntity()
|
||||
.first()
|
||||
.find() ?: return false
|
||||
|
||||
return contentScannerInfoEntity.enabled.orFalse() && contentScannerInfoEntity.serverUrl?.isValidUrl().orFalse()
|
||||
}
|
||||
|
||||
override fun updateStateForContent(mxcUrl: String, state: ScanState, scannerUrl: String?) {
|
||||
monarchy.runTransactionSync {
|
||||
ContentScanResultEntity.getOrCreate(it, mxcUrl, scannerUrl, clock.epochMillis()).scanResult = state
|
||||
}
|
||||
override suspend fun updateStateForContent(mxcUrl: String, state: ScanState, scannerUrl: String?) = upsertContentScanResultEntity(mxcUrl, scannerUrl) {
|
||||
it.scanResult = state
|
||||
}
|
||||
|
||||
override fun updateScanResultForContent(mxcUrl: String, scannerUrl: String?, state: ScanState, humanReadable: String) {
|
||||
monarchy.runTransactionSync {
|
||||
ContentScanResultEntity.getOrCreate(it, mxcUrl, scannerUrl, clock.epochMillis()).apply {
|
||||
scanResult = state
|
||||
scanDateTimestamp = clock.epochMillis()
|
||||
humanReadableMessage = humanReadable
|
||||
override suspend fun updateScanResultForContent(mxcUrl: String, scannerUrl: String?, state: ScanState, humanReadable: String) = upsertContentScanResultEntity(
|
||||
mxcUrl,
|
||||
scannerUrl
|
||||
) {
|
||||
it.scanResult = state
|
||||
it.scanDateTimestamp = clock.epochMillis()
|
||||
it.humanReadableMessage = humanReadable
|
||||
}
|
||||
|
||||
private suspend fun upsertContentScanResultEntity(mxcUrl: String, scannerUrl: String?, operation: (ContentScanResultEntity) -> Unit) {
|
||||
realmInstance.write {
|
||||
val contentScanResultEntity = queryContentScanResultEntity(mxcUrl, scannerUrl).first().find()
|
||||
if (contentScanResultEntity != null) {
|
||||
operation(contentScanResultEntity)
|
||||
} else {
|
||||
val newContentScanResultEntity = ContentScanResultEntity().apply {
|
||||
operation(this)
|
||||
}
|
||||
copyToRealm(newContentScanResultEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isScanResultKnownOrInProgress(mxcUrl: String, scannerUrl: String?): Boolean {
|
||||
var isKnown = false
|
||||
monarchy.runTransactionSync {
|
||||
val info = ContentScanResultEntity.get(it, mxcUrl, scannerUrl)?.scanResult
|
||||
isKnown = when (info) {
|
||||
override suspend fun isScanResultKnownOrInProgress(mxcUrl: String, scannerUrl: String?): Boolean {
|
||||
val info = realmInstance.getRealm()
|
||||
.queryContentScanResultEntity(mxcUrl, scannerUrl)
|
||||
.first()
|
||||
.await()
|
||||
?.scanResult
|
||||
|
||||
return when (info) {
|
||||
ScanState.IN_PROGRESS,
|
||||
ScanState.TRUSTED,
|
||||
ScanState.INFECTED -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
return isKnown
|
||||
|
||||
override suspend fun getScanResult(mxcUrl: String): ScanStatusInfo? {
|
||||
val scannerUrl = getScannerUrl()
|
||||
return realmInstance.getRealm()
|
||||
.queryContentScanResultEntity(mxcUrl, scannerUrl)
|
||||
.first()
|
||||
.await()
|
||||
?.toModel()
|
||||
}
|
||||
|
||||
override fun getScanResult(mxcUrl: String): ScanStatusInfo? {
|
||||
return monarchy.fetchAllMappedSync({ realm ->
|
||||
realm.where<ContentScanResultEntity>()
|
||||
.equalTo(ContentScanResultEntityFields.MEDIA_URL, mxcUrl)
|
||||
override fun getLiveScanResult(mxcUrl: String): Flow<Optional<ScanStatusInfo>> {
|
||||
return realmInstance.getRealmFlow()
|
||||
.flatMapConcat { realm ->
|
||||
val scannerUrl = getScannerUrl()
|
||||
realm
|
||||
.queryContentScanResultEntity(mxcUrl, scannerUrl)
|
||||
.first()
|
||||
.asFlow()
|
||||
}.map {
|
||||
val scanStatusInfo = it.obj?.toModel()
|
||||
Optional.from(scanStatusInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TypedRealm.queryContentScanResultEntity(mxcUrl: String, scannerUrl: String?): RealmQuery<ContentScanResultEntity> {
|
||||
return query(ContentScanResultEntity::class, "mediaUrl == $0", mxcUrl)
|
||||
.apply {
|
||||
getScannerUrl()?.let {
|
||||
equalTo(ContentScanResultEntityFields.SCANNER_URL, it)
|
||||
if (scannerUrl != null) {
|
||||
query("scannerUrl == $0", scannerUrl)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
it.toModel()
|
||||
})
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
override fun getLiveScanResult(mxcUrl: String): LiveData<Optional<ScanStatusInfo>> {
|
||||
val liveData = monarchy.findAllMappedWithChanges(
|
||||
{ realm: Realm ->
|
||||
realm.where<ContentScanResultEntity>()
|
||||
.equalTo(ContentScanResultEntityFields.MEDIA_URL, mxcUrl)
|
||||
.equalTo(ContentScanResultEntityFields.SCANNER_URL, getScannerUrl())
|
||||
},
|
||||
{ entity ->
|
||||
entity.toModel()
|
||||
}
|
||||
)
|
||||
return Transformations.map(liveData) {
|
||||
it.firstOrNull().toOptional()
|
||||
}
|
||||
private fun TypedRealm.queryContentScannerInfoEntity(): RealmQuery<ContentScannerInfoEntity> {
|
||||
return query(ContentScannerInfoEntity::class)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user