diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index d4c39de2..a2a0d2fa 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt b/app/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt index 2314be29..e3acb888 100644 --- a/app/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt +++ b/app/src/main/java/im/vector/riotredesign/features/login/LoginActivity.kt @@ -6,7 +6,6 @@ import android.widget.Toast import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig -import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.session.Session import im.vector.riotredesign.R import im.vector.riotredesign.core.platform.RiotActivity @@ -43,7 +42,7 @@ class LoginActivity : RiotActivity() { goToHome() } - override fun onFailure(failure: Failure) { + override fun onFailure(failure: Throwable) { progressBar.visibility = View.GONE Toast.makeText(this@LoginActivity, "Authenticate failure: $failure", Toast.LENGTH_LONG).show() } diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index f619b79c..5b5d5c7a 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -41,13 +41,14 @@ android { dependencies { - def arrow_version = "0.7.3" + def arrow_version = "0.8.0" def support_version = '28.0.0' def moshi_version = '1.7.0' def lifecycle_version = "1.1.1" implementation fileTree(dir: 'libs', include: ['*.aar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0' implementation "com.android.support:appcompat-v7:$support_version" implementation "com.android.support:recyclerview-v7:$support_version" @@ -59,7 +60,6 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-moshi:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' - implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' implementation 'com.squareup.okio:okio:1.15.0' @@ -77,6 +77,10 @@ dependencies { // FP implementation "io.arrow-kt:arrow-core:$arrow_version" + implementation "io.arrow-kt:arrow-instances-core:$arrow_version" + implementation "io.arrow-kt:arrow-effects:$arrow_version" + implementation "io.arrow-kt:arrow-effects-instances:$arrow_version" + implementation "io.arrow-kt:arrow-integration-retrofit-adapter:$arrow_version" // DI implementation "org.koin:koin-core:$koin_version" diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixCallback.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixCallback.kt index db85de5c..ee4a2ac6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixCallback.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixCallback.kt @@ -1,14 +1,12 @@ package im.vector.matrix.android.api -import im.vector.matrix.android.api.failure.Failure - interface MatrixCallback { fun onSuccess(data: T) { //no-op } - fun onFailure(failure: Failure){ + fun onFailure(failure: Throwable) { //no-op } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/group/model/GroupSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/group/model/GroupSummary.kt index 115dbb07..2ae1d2fe 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/group/model/GroupSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/group/model/GroupSummary.kt @@ -4,5 +4,6 @@ data class GroupSummary( val groupId: String, val displayName: String = "", val shortDescription: String = "", - val avatarUrl: String = "" + val avatarUrl: String = "", + val roomIds: List = emptyList() ) \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthAPI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthAPI.kt index 3e4b1139..0a66afb5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthAPI.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/AuthAPI.kt @@ -3,8 +3,7 @@ package im.vector.matrix.android.internal.auth import im.vector.matrix.android.internal.auth.data.Credentials import im.vector.matrix.android.internal.auth.data.PasswordLoginParams import im.vector.matrix.android.internal.network.NetworkConstants -import kotlinx.coroutines.Deferred -import retrofit2.Response +import retrofit2.Call import retrofit2.http.Body import retrofit2.http.POST @@ -19,6 +18,6 @@ interface AuthAPI { * @param loginParams the login parameters */ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login") - fun login(@Body loginParams: PasswordLoginParams): Deferred> + fun login(@Body loginParams: PasswordLoginParams): Call } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt index 21ddbe3c..2dd7f6e3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt @@ -1,12 +1,9 @@ package im.vector.matrix.android.internal.auth import android.util.Patterns -import arrow.core.Either -import arrow.core.leftIfNull import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.Authenticator import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig -import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.auth.data.Credentials @@ -44,7 +41,7 @@ class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder, val job = GlobalScope.launch(coroutineDispatchers.main) { val sessionOrFailure = authenticate(homeServerConnectionConfig, login, password) - sessionOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) }) + sessionOrFailure.fold({ callback.onFailure(it) }, { callback.onSuccess(it) }) } return CancelableCoroutine(job) @@ -52,7 +49,7 @@ class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder, private suspend fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig, login: String, - password: String): Either = withContext(coroutineDispatchers.io) { + password: String) = withContext(coroutineDispatchers.io) { val authAPI = buildAuthAPI(homeServerConnectionConfig) val loginParams = if (Patterns.EMAIL_ADDRESS.matcher(login).matches()) { @@ -62,8 +59,6 @@ class DefaultAuthenticator(private val retrofitBuilder: Retrofit.Builder, } executeRequest { apiCall = authAPI.login(loginParams) - }.leftIfNull { - Failure.Unknown(IllegalArgumentException("Credentials shouldn't not be null")) }.map { val sessionParams = SessionParams(it, homeServerConnectionConfig) sessionParamsStore.save(sessionParams) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt index 0108dea5..e8c60549 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt @@ -1,11 +1,12 @@ package im.vector.matrix.android.internal.auth +import arrow.core.Try import im.vector.matrix.android.internal.auth.data.SessionParams interface SessionParamsStore { fun get(): SessionParams? - fun save(sessionParams: SessionParams) + fun save(sessionParams: SessionParams): Try } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt index 6c3241c0..0adceee4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt @@ -1,5 +1,6 @@ package im.vector.matrix.android.internal.auth.db +import arrow.core.Try import im.vector.matrix.android.internal.auth.SessionParamsStore import im.vector.matrix.android.internal.auth.data.SessionParams import io.realm.Realm @@ -8,14 +9,17 @@ import io.realm.RealmConfiguration class RealmSessionParamsStore(private val mapper: SessionParamsMapper, private val realmConfiguration: RealmConfiguration) : SessionParamsStore { - override fun save(sessionParams: SessionParams) { - val entity = mapper.map(sessionParams) - if (entity != null) { - val realm = Realm.getInstance(realmConfiguration) - realm.executeTransaction { - it.insert(entity) + override fun save(sessionParams: SessionParams): Try { + return Try { + val entity = mapper.map(sessionParams) + if (entity != null) { + val realm = Realm.getInstance(realmConfiguration) + realm.executeTransaction { + it.insert(entity) + } + realm.close() } - realm.close() + sessionParams } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/GroupSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/GroupSummaryMapper.kt index 46241950..0daa9415 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/GroupSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/GroupSummaryMapper.kt @@ -11,7 +11,8 @@ object GroupSummaryMapper { roomSummaryEntity.groupId, roomSummaryEntity.displayName, roomSummaryEntity.shortDescription, - roomSummaryEntity.avatarUrl + roomSummaryEntity.avatarUrl, + roomSummaryEntity.roomIds.toList() ) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/GroupSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/GroupSummaryEntity.kt index 45eb0e1c..4c69616d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/GroupSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/GroupSummaryEntity.kt @@ -1,12 +1,14 @@ package im.vector.matrix.android.internal.database.model +import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.PrimaryKey open class GroupSummaryEntity(@PrimaryKey var groupId: String = "", var displayName: String = "", var shortDescription: String = "", - var avatarUrl: String = "" + var avatarUrl: String = "", + var roomIds: RealmList = RealmList() ) : RealmObject() { companion object diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt index cee73a5e..d5dfd618 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt @@ -5,7 +5,6 @@ import im.vector.matrix.android.api.thread.MainThreadExecutor import im.vector.matrix.android.internal.util.BackgroundDetectionObserver import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.IO import kotlinx.coroutines.asCoroutineDispatcher import org.koin.dsl.context.ModuleDefinition import org.koin.dsl.module.Module diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt index 04a97ea0..69f2c68f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/NetworkModule.kt @@ -1,6 +1,5 @@ package im.vector.matrix.android.internal.di -import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory import im.vector.matrix.android.internal.network.AccessTokenInterceptor import im.vector.matrix.android.internal.network.NetworkConnectivityChecker import okhttp3.OkHttpClient @@ -8,7 +7,6 @@ import okhttp3.logging.HttpLoggingInterceptor import org.koin.dsl.context.ModuleDefinition import org.koin.dsl.module.Module import org.koin.dsl.module.module -import retrofit2.CallAdapter import retrofit2.Converter import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory @@ -48,10 +46,6 @@ class NetworkModule : Module { MoshiConverterFactory.create(get()) as Converter.Factory } - single { - CoroutineCallAdapterFactory() as CallAdapter.Factory - } - single { NetworkConnectivityChecker(get()) } @@ -60,7 +54,6 @@ class NetworkModule : Module { Retrofit.Builder() .client(get()) .addConverterFactory(get()) - .addCallAdapterFactory(get()) } }.invoke() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/Request.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/Request.kt index f34d3601..eaeaff52 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/Request.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/Request.kt @@ -1,54 +1,50 @@ package im.vector.matrix.android.internal.network -import arrow.core.Either +import arrow.core.Try +import arrow.core.failure +import arrow.core.recoverWith +import arrow.effects.IO +import arrow.effects.fix +import arrow.effects.instances.io.async.async +import arrow.integrations.retrofit.adapter.runAsync import com.squareup.moshi.Moshi import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.failure.MatrixError import im.vector.matrix.android.internal.di.MoshiProvider -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.coroutineScope import okhttp3.ResponseBody -import retrofit2.Response +import retrofit2.Call import java.io.IOException -suspend inline fun executeRequest(block: Request.() -> Unit) = Request().apply(block).execute() +inline fun executeRequest(block: Request.() -> Unit) = Request().apply(block).execute() class Request { var moshi: Moshi = MoshiProvider.providesMoshi() - lateinit var apiCall: Deferred> + lateinit var apiCall: Call - suspend fun execute(): Either = coroutineScope { - try { - val response = apiCall.await() + fun execute(): Try { + return Try { + val response = apiCall.runAsync(IO.async()).fix().unsafeRunSync() if (response.isSuccessful) { - val result = response.body() - Either.Right(result) + response.body() ?: throw IllegalStateException("The request returned a null body") } else { - val failure = manageFailure(response.errorBody()) - Either.Left(failure) - } - - } catch (e: Exception) { - when (e) { - is IOException -> Either.Left(Failure.NetworkConnection(e)) - else -> Either.Left(Failure.Unknown(e)) + throw manageFailure(response.errorBody()) } + }.recoverWith { + when (it) { + is IOException -> Failure.NetworkConnection(it) + is Failure.ServerError -> it + else -> Failure.Unknown(it) + }.failure() } } - private fun manageFailure(errorBody: ResponseBody?): Failure { - return try { - val matrixError = errorBody?.let { - val matrixErrorAdapter = moshi.adapter(MatrixError::class.java) - matrixErrorAdapter.fromJson(errorBody.source()) - } ?: throw RuntimeException("Matrix error should not be null") - - Failure.ServerError(matrixError) - - } catch (e: Exception) { - Failure.Unknown(e) - } + private fun manageFailure(errorBody: ResponseBody?): Throwable { + val matrixError = errorBody?.let { + val matrixErrorAdapter = moshi.adapter(MatrixError::class.java) + matrixErrorAdapter.fromJson(errorBody.source()) + } ?: return RuntimeException("Matrix error should not be null") + return Failure.ServerError(matrixError) } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataRequest.kt new file mode 100644 index 00000000..8651b309 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupDataRequest.kt @@ -0,0 +1,70 @@ +package im.vector.matrix.android.internal.session.group + +import arrow.core.Try +import arrow.core.fix +import arrow.instances.`try`.monad.monad +import arrow.typeclasses.binding +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.util.Cancelable +import im.vector.matrix.android.internal.database.model.GroupSummaryEntity +import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.group.model.GroupRooms +import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse +import im.vector.matrix.android.internal.util.CancelableCoroutine +import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import im.vector.matrix.android.internal.util.tryTransactionSync +import io.realm.kotlin.createObject +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class GetGroupDataRequest( + private val groupAPI: GroupAPI, + private val monarchy: Monarchy, + private val coroutineDispatchers: MatrixCoroutineDispatchers +) { + + fun execute(groupId: String, + callback: MatrixCallback + ): Cancelable { + val job = GlobalScope.launch(coroutineDispatchers.main) { + val groupOrFailure = execute(groupId) + groupOrFailure.fold({ callback.onFailure(it) }, { callback.onSuccess(true) }) + } + return CancelableCoroutine(job) + } + + private suspend fun execute(groupId: String) = withContext(coroutineDispatchers.io) { + Try.monad().binding { + val groupSummary = executeRequest { + apiCall = groupAPI.getSummary(groupId) + }.bind() + + val groupRooms = executeRequest { + apiCall = groupAPI.getRooms(groupId) + }.bind() + insertInDb(groupSummary, groupRooms, groupId).bind() + }.fix() + } + + private fun insertInDb(groupSummary: GroupSummaryResponse, groupRooms: GroupRooms, groupId: String): Try { + return monarchy + .tryTransactionSync { realm -> + val groupSummaryEntity = GroupSummaryEntity.where(realm, groupId).findFirst() + ?: realm.createObject(groupId) + + groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: "" + val name = groupSummary.profile?.name + groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else name + groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription ?: "" + + val roomIds = groupRooms.rooms.mapNotNull { it.roomId } + groupSummaryEntity.roomIds.clear() + groupSummaryEntity.roomIds.addAll(roomIds) + } + } + + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupSummaryRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupSummaryRequest.kt deleted file mode 100644 index 4d73e733..00000000 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GetGroupSummaryRequest.kt +++ /dev/null @@ -1,68 +0,0 @@ -package im.vector.matrix.android.internal.session.group - -import arrow.core.Either -import arrow.core.flatMap -import arrow.core.leftIfNull -import com.zhuinden.monarchy.Monarchy -import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.failure.Failure -import im.vector.matrix.android.api.util.Cancelable -import im.vector.matrix.android.internal.database.model.GroupSummaryEntity -import im.vector.matrix.android.internal.database.query.where -import im.vector.matrix.android.internal.network.executeRequest -import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse -import im.vector.matrix.android.internal.util.CancelableCoroutine -import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers -import io.realm.kotlin.createObject -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -class GetGroupSummaryRequest( - private val groupAPI: GroupAPI, - private val monarchy: Monarchy, - private val coroutineDispatchers: MatrixCoroutineDispatchers -) { - - fun execute(groupId: String, - callback: MatrixCallback - ): Cancelable { - val job = GlobalScope.launch(coroutineDispatchers.main) { - val groupOrFailure = execute(groupId) - groupOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) }) - } - return CancelableCoroutine(job) - } - - private suspend fun execute(groupId: String) = withContext(coroutineDispatchers.io) { - - return@withContext executeRequest { - apiCall = groupAPI.getSummary(groupId) - }.leftIfNull { - Failure.Unknown(RuntimeException("GroupSummary shouldn't be null")) - }.flatMap { groupSummary -> - try { - insertInDb(groupSummary, groupId) - Either.right(groupSummary) - } catch (exception: Exception) { - Either.Left(Failure.Unknown(exception)) - } - } - } - - private fun insertInDb(groupSummary: GroupSummaryResponse, groupId: String) { - monarchy.runTransactionSync { realm -> - val groupSummaryEntity = GroupSummaryEntity.where(realm, groupId).findFirst() - ?: realm.createObject(groupId) - - groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: "" - val name = groupSummary.profile?.name - groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else name - groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription ?: "" - - - } - } - - -} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupAPI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupAPI.kt index 1fe5bc45..a3a6978f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupAPI.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupAPI.kt @@ -1,9 +1,9 @@ package im.vector.matrix.android.internal.session.group import im.vector.matrix.android.internal.network.NetworkConstants +import im.vector.matrix.android.internal.session.group.model.GroupRooms import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse -import kotlinx.coroutines.Deferred -import retrofit2.Response +import retrofit2.Call import retrofit2.http.GET import retrofit2.http.Path @@ -15,7 +15,15 @@ interface GroupAPI { * @param groupId the group id */ @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/summary") - fun getSummary(@Path("groupId") groupId: String): Deferred> + fun getSummary(@Path("groupId") groupId: String): Call + + /** + * Request the rooms list. + * + * @param groupId the group id + */ + @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/rooms") + fun getRooms(@Path("groupId") groupId: String): Call } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt index 9334a267..1f8bf99c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupModule.kt @@ -16,7 +16,7 @@ class GroupModule : Module { } scope(DefaultSession.SCOPE) { - GetGroupSummaryRequest(get(), get(), get()) + GetGroupDataRequest(get(), get(), get()) } }.invoke() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt index 74b0bb5e..8f256be4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt @@ -7,12 +7,11 @@ import im.vector.matrix.android.api.session.group.Group import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.GroupEntity import im.vector.matrix.android.internal.database.query.where -import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean internal class GroupSummaryUpdater(private val monarchy: Monarchy, - private val getGroupSummaryRequest: GetGroupSummaryRequest + private val getGroupDataRequest: GetGroupDataRequest ) : Observer> { private var isStarted = AtomicBoolean(false) @@ -57,7 +56,7 @@ internal class GroupSummaryUpdater(private val monarchy: Monarchy, if (group == null) { return } - getGroupSummaryRequest.execute(group.groupId, object : MatrixCallback {}) + getGroupDataRequest.execute(group.groupId, object : MatrixCallback {}) } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/model/GroupRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/model/GroupRoom.kt new file mode 100644 index 00000000..fd3590b2 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/model/GroupRoom.kt @@ -0,0 +1,19 @@ +package im.vector.matrix.android.internal.session.group.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class GroupRoom( + + @Json(name = "aliases") val aliases: List? = null, + @Json(name = "canonical_alias") val canonicalAlias: String? = null, + @Json(name = "name") val name: String? = null, + @Json(name = "num_joined_members") val numJoinedMembers: Int = 0, + @Json(name = "room_id") val roomId: String? = null, + @Json(name = "topic") val topic: String? = null, + @Json(name = "world_readable") val worldReadable: Boolean = false, + @Json(name = "guest_can_join") val guestCanJoin: Boolean = false, + @Json(name = "avatar_url") val avatarUrl: String? = null + +) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/model/GroupRooms.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/model/GroupRooms.kt new file mode 100644 index 00000000..b3b2ffdc --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/model/GroupRooms.kt @@ -0,0 +1,12 @@ +package im.vector.matrix.android.internal.session.group.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class GroupRooms( + + @Json(name = "total_room_count_estimate") val totalRoomCountEstimate: Int? = null, + @Json(name = "chunk") val rooms: List = emptyList() + +) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt index 9909db71..d2c3ca86 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt @@ -4,6 +4,7 @@ import im.vector.matrix.android.internal.network.NetworkConstants import im.vector.matrix.android.internal.session.room.members.RoomMembersResponse import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEvent import kotlinx.coroutines.Deferred +import retrofit2.Call import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Path @@ -26,7 +27,7 @@ interface RoomAPI { @Query("dir") dir: String, @Query("limit") limit: Int, @Query("filter") filter: String? - ): Deferred> + ): Call /** @@ -42,7 +43,7 @@ interface RoomAPI { @Query("at") syncToken: String?, @Query("membership") membership: String?, @Query("not_membership") notMembership: String? - ): Deferred> + ): Call } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt index 0a84c25c..18147810 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt @@ -1,11 +1,8 @@ package im.vector.matrix.android.internal.session.room.members -import arrow.core.Either -import arrow.core.flatMap -import arrow.core.leftIfNull +import arrow.core.Try import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.database.model.RoomEntity @@ -15,6 +12,7 @@ import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.session.sync.StateEventsChunkHandler import im.vector.matrix.android.internal.util.CancelableCoroutine import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import im.vector.matrix.android.internal.util.tryTransactionSync import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -31,7 +29,7 @@ internal class LoadRoomMembersRequest(private val roomAPI: RoomAPI, ): Cancelable { val job = GlobalScope.launch(coroutineDispatchers.main) { val responseOrFailure = execute(roomId, streamToken, excludeMembership) - responseOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(true) }) + responseOrFailure.fold({ callback.onFailure(it) }, { callback.onSuccess(true) }) } return CancelableCoroutine(job) } @@ -41,35 +39,30 @@ internal class LoadRoomMembersRequest(private val roomAPI: RoomAPI, streamToken: String?, excludeMembership: Membership?) = withContext(coroutineDispatchers.io) { - return@withContext executeRequest { + executeRequest { apiCall = roomAPI.getMembers(roomId, null, null, excludeMembership?.value) - }.leftIfNull { - Failure.Unknown(RuntimeException("RoomMembersResponse shouldn't be null")) }.flatMap { response -> - try { - insertInDb(response, roomId) - Either.right(response) - } catch (exception: Exception) { - Either.Left(Failure.Unknown(exception)) - } + insertInDb(response, roomId) } } - private fun insertInDb(response: RoomMembersResponse, roomId: String) { - monarchy.runTransactionSync { realm -> - // We ignore all the already known members - val roomEntity = RoomEntity.where(realm, roomId).findFirst() - ?: throw IllegalStateException("You shouldn't use this method without a room") + private fun insertInDb(response: RoomMembersResponse, roomId: String): Try { + return monarchy + .tryTransactionSync { realm -> + // We ignore all the already known members + val roomEntity = RoomEntity.where(realm, roomId).findFirst() + ?: throw IllegalStateException("You shouldn't use this method without a room") - val roomMembers = RoomMembers(realm, roomId).getLoaded() - val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) } + val roomMembers = RoomMembers(realm, roomId).getLoaded() + val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) } - val chunk = stateEventsChunkHandler.handle(realm, roomId, eventsToInsert) - if (!roomEntity.chunks.contains(chunk)) { - roomEntity.chunks.add(chunk) - } - roomEntity.areAllMembersLoaded = true - } + val chunk = stateEventsChunkHandler.handle(realm, roomId, eventsToInsert) + if (!roomEntity.chunks.contains(chunk)) { + roomEntity.chunks.add(chunk) + } + roomEntity.areAllMembersLoaded = true + } + .map { response } } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt index 2451a4ed..742e93f5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt @@ -1,11 +1,9 @@ package im.vector.matrix.android.internal.session.room.timeline -import arrow.core.Either -import arrow.core.flatMap -import arrow.core.leftIfNull +import arrow.core.Try +import arrow.core.failure import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.database.helper.addManagedToChunk import im.vector.matrix.android.internal.database.model.ChunkEntity @@ -21,6 +19,7 @@ import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.session.sync.StateEventsChunkHandler import im.vector.matrix.android.internal.util.CancelableCoroutine import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import im.vector.matrix.android.internal.util.tryTransactionSync import io.realm.kotlin.createObject import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -40,7 +39,7 @@ class PaginationRequest(private val roomAPI: RoomAPI, val job = GlobalScope.launch(coroutineDispatchers.main) { val filter = FilterUtil.createRoomEventFilter(true)?.toJSONString() val chunkOrFailure = execute(roomId, from, direction, limit, filter) - chunkOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) }) + chunkOrFailure.fold({ callback.onFailure(it) }, { callback.onSuccess(it) }) } return CancelableCoroutine(job) } @@ -52,66 +51,59 @@ class PaginationRequest(private val roomAPI: RoomAPI, filter: String?) = withContext(coroutineDispatchers.io) { if (from == null) { - return@withContext Either.left( - Failure.Unknown(RuntimeException("From token shouldn't be null")) - ) + return@withContext RuntimeException("From token shouldn't be null").failure() } - return@withContext executeRequest { + executeRequest { apiCall = roomAPI.getRoomMessagesFrom(roomId, from, direction.value, limit, filter) - }.leftIfNull { - Failure.Unknown(RuntimeException("TokenChunkEvent shouldn't be null")) }.flatMap { chunk -> - try { - insertInDb(chunk, roomId) - Either.right(chunk) - } catch (exception: Exception) { - Either.Left(Failure.Unknown(exception)) - } + insertInDb(chunk, roomId) } } - private fun insertInDb(receivedChunk: TokenChunkEvent, roomId: String) { - monarchy.runTransactionSync { realm -> - val roomEntity = RoomEntity.where(realm, roomId).findFirst() - ?: throw IllegalStateException("You shouldn't use this method without a room") + private fun insertInDb(receivedChunk: TokenChunkEvent, roomId: String): Try { + return monarchy + .tryTransactionSync { realm -> + val roomEntity = RoomEntity.where(realm, roomId).findFirst() + ?: throw IllegalStateException("You shouldn't use this method without a room") - val currentChunk = ChunkEntity.findWithPrevToken(realm, roomId, receivedChunk.nextToken) - ?: realm.createObject() + val currentChunk = ChunkEntity.findWithPrevToken(realm, roomId, receivedChunk.nextToken) + ?: realm.createObject() - currentChunk.prevToken = receivedChunk.prevToken + currentChunk.prevToken = receivedChunk.prevToken - val prevChunk = ChunkEntity.findWithNextToken(realm, roomId, receivedChunk.prevToken) + val prevChunk = ChunkEntity.findWithNextToken(realm, roomId, receivedChunk.prevToken) - val eventIds = receivedChunk.events.filter { it.eventId != null }.map { it.eventId!! } - val chunksOverlapped = ChunkEntity.findAllIncludingEvents(realm, eventIds) - val hasOverlapped = chunksOverlapped.isNotEmpty() + val eventIds = receivedChunk.events.filter { it.eventId != null }.map { it.eventId!! } + val chunksOverlapped = ChunkEntity.findAllIncludingEvents(realm, eventIds) + val hasOverlapped = chunksOverlapped.isNotEmpty() - val stateEventsChunk = stateEventsChunkHandler.handle(realm, roomId, receivedChunk.stateEvents) - if (!roomEntity.chunks.contains(stateEventsChunk)) { - roomEntity.chunks.add(stateEventsChunk) - } + val stateEventsChunk = stateEventsChunkHandler.handle(realm, roomId, receivedChunk.stateEvents) + if (!roomEntity.chunks.contains(stateEventsChunk)) { + roomEntity.chunks.add(stateEventsChunk) + } - receivedChunk.events.addManagedToChunk(currentChunk) + receivedChunk.events.addManagedToChunk(currentChunk) - if (prevChunk != null) { - currentChunk.events.addAll(prevChunk.events) - roomEntity.chunks.remove(prevChunk) + if (prevChunk != null) { + currentChunk.events.addAll(prevChunk.events) + roomEntity.chunks.remove(prevChunk) - } else if (hasOverlapped) { - chunksOverlapped.forEach { overlapped -> - overlapped.events.forEach { event -> - if (!currentChunk.events.fastContains(event)) { - currentChunk.events.add(event) + } else if (hasOverlapped) { + chunksOverlapped.forEach { overlapped -> + overlapped.events.forEach { event -> + if (!currentChunk.events.fastContains(event)) { + currentChunk.events.add(event) + } + } + currentChunk.prevToken = overlapped.prevToken + roomEntity.chunks.remove(overlapped) } } - currentChunk.prevToken = overlapped.prevToken - roomEntity.chunks.remove(overlapped) + if (!roomEntity.chunks.contains(currentChunk)) { + roomEntity.chunks.add(currentChunk) + } } - } - if (!roomEntity.chunks.contains(currentChunk)) { - roomEntity.chunks.add(currentChunk) - } - } + .map { receivedChunk } } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt index c8d76d7d..2f943220 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt @@ -3,7 +3,6 @@ package im.vector.matrix.android.internal.session.room.timeline import android.arch.paging.PagedList import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.session.events.model.EnrichedEvent import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.query.findAllIncludingEvents @@ -54,7 +53,7 @@ class TimelineBoundaryCallback(private val roomId: String, pagingRequestCallback.recordSuccess() } - override fun onFailure(failure: Failure) { + override fun onFailure(failure: Throwable) { pagingRequestCallback.recordFailure(failure) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncAPI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncAPI.kt index 66526489..b5aa0981 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncAPI.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncAPI.kt @@ -1,15 +1,14 @@ package im.vector.matrix.android.internal.session.sync -import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.network.NetworkConstants -import kotlinx.coroutines.Deferred -import retrofit2.Response +import im.vector.matrix.android.internal.session.sync.model.SyncResponse +import retrofit2.Call import retrofit2.http.GET import retrofit2.http.QueryMap interface SyncAPI { @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "sync") - fun sync(@QueryMap params: Map): Deferred> + fun sync(@QueryMap params: Map): Call } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncRequest.kt index db5aafb1..6f4c5d3e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncRequest.kt @@ -1,10 +1,6 @@ package im.vector.matrix.android.internal.session.sync -import arrow.core.Either -import arrow.core.flatMap -import arrow.core.leftIfNull import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterBody import im.vector.matrix.android.internal.legacy.util.FilterUtil @@ -24,7 +20,7 @@ internal class SyncRequest(private val syncAPI: SyncAPI, fun execute(token: String?, callback: MatrixCallback): Cancelable { val job = GlobalScope.launch { val syncOrFailure = execute(token) - syncOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) }) + syncOrFailure.fold({ callback.onFailure(it) }, { callback.onSuccess(it) }) } return CancelableCoroutine(job) } @@ -42,15 +38,8 @@ internal class SyncRequest(private val syncAPI: SyncAPI, params["filter"] = filterBody.toJSONString() executeRequest { apiCall = syncAPI.sync(params) - }.leftIfNull { - Failure.Unknown(RuntimeException("Sync response shouln't be null")) - }.flatMap { - try { - syncResponseHandler.handleResponse(it, token, false) - Either.right(it) - } catch (exception: Exception) { - Either.Left(Failure.Unknown(exception)) - } + }.flatMap { syncResponse -> + syncResponseHandler.handleResponse(syncResponse, token, false) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt index a41ec41f..e427d297 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt @@ -1,5 +1,6 @@ package im.vector.matrix.android.internal.session.sync +import arrow.core.Try import im.vector.matrix.android.internal.session.sync.model.SyncResponse import timber.log.Timber @@ -7,21 +8,20 @@ internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler, private val userAccountDataSyncHandler: UserAccountDataSyncHandler, private val groupSyncHandler: GroupSyncHandler) { - fun handleResponse(syncResponse: SyncResponse?, fromToken: String?, isCatchingUp: Boolean) { - if (syncResponse == null) { - return - } - Timber.v("Handle sync response") - if (syncResponse.rooms != null) { - roomSyncHandler.handle(syncResponse.rooms) - } - if (syncResponse.groups != null) { - groupSyncHandler.handle(syncResponse.groups) - } - if (syncResponse.accountData != null) { - userAccountDataSyncHandler.handle(syncResponse.accountData) + fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try { + return Try { + Timber.v("Handle sync response") + if (syncResponse.rooms != null) { + roomSyncHandler.handle(syncResponse.rooms) + } + if (syncResponse.groups != null) { + groupSyncHandler.handle(syncResponse.groups) + } + if (syncResponse.accountData != null) { + userAccountDataSyncHandler.handle(syncResponse.accountData) + } + syncResponse } } - } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt index dc11202e..67617bfb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncThread.kt @@ -84,7 +84,7 @@ internal class SyncThread(private val syncRequest: SyncRequest, latch.countDown() } - override fun onFailure(failure: Failure) { + override fun onFailure(failure: Throwable) { if (failure !is Failure.NetworkConnection) { // Wait 10s before retrying sleep(RETRY_WAIT_TIME_MS) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/Monarchy.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/Monarchy.kt new file mode 100644 index 00000000..5f80a083 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/Monarchy.kt @@ -0,0 +1,17 @@ +package im.vector.matrix.android.internal.util + +import arrow.core.Try +import com.zhuinden.monarchy.Monarchy +import io.realm.Realm + +fun Monarchy.tryTransactionSync(transaction: (realm: Realm) -> Unit): Try { + return Try { + this.runTransactionSync(transaction) + } +} + +fun Monarchy.tryTransactionAsync(transaction: (realm: Realm) -> Unit): Try { + return Try { + this.writeAsync(transaction) + } +} \ No newline at end of file