porting settings module to chat engine

This commit is contained in:
Adam Brown 2022-10-09 17:44:18 +01:00
parent 492d7df9ac
commit d2e8a29af8
11 changed files with 65 additions and 22 deletions

View File

@ -192,10 +192,9 @@ internal class FeatureModules internal constructor(
val homeModule by unsafeLazy { HomeModule(matrixModules.engine, storeModule.value, buildMeta) } val homeModule by unsafeLazy { HomeModule(matrixModules.engine, storeModule.value, buildMeta) }
val settingsModule by unsafeLazy { val settingsModule by unsafeLazy {
SettingsModule( SettingsModule(
matrixModules.engine,
storeModule.value, storeModule.value,
pushModule, pushModule,
matrixModules.crypto,
matrixModules.sync,
context.contentResolver, context.contentResolver,
buildMeta, buildMeta,
deviceMeta, deviceMeta,

View File

@ -1,14 +1,21 @@
package app.dapk.st.engine package app.dapk.st.engine
import app.dapk.st.matrix.common.RoomId
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import java.io.InputStream
interface ChatEngine { interface ChatEngine {
fun directory(): Flow<DirectoryState> fun directory(): Flow<DirectoryState>
fun invites(): Flow<InviteState> fun invites(): Flow<InviteState>
suspend fun login(request: LoginRequest): LoginResult suspend fun login(request: LoginRequest): LoginResult
suspend fun me(forceRefresh: Boolean): Me suspend fun me(forceRefresh: Boolean): Me
suspend fun refresh(roomIds: List<RoomId>)
suspend fun InputStream.importRoomKeys(password: String): Flow<ImportResult>
} }

View File

@ -62,3 +62,20 @@ data class Me(
val avatarUrl: AvatarUrl?, val avatarUrl: AvatarUrl?,
val homeServerUrl: HomeServerUrl, val homeServerUrl: HomeServerUrl,
) )
sealed interface ImportResult {
data class Success(val roomIds: Set<RoomId>, val totalImportedKeysCount: Long) : ImportResult
data class Error(val cause: Type) : ImportResult {
sealed interface Type {
data class Unknown(val cause: Throwable) : Type
object NoKeysFound : Type
object UnexpectedDecryptionOutput : Type
object UnableToOpenFile : Type
object InvalidFile : Type
}
}
data class Update(val importedKeysCount: Long) : ImportResult
}

View File

@ -4,5 +4,5 @@ apply plugin: 'kotlin-parcelize'
dependencies { dependencies {
compileOnly project(":domains:android:stub") compileOnly project(":domains:android:stub")
implementation project(":core") implementation project(":core")
implementation project(":matrix:common") implementation project(":chat-engine")
} }

View File

@ -1,8 +1,7 @@
applyAndroidComposeLibraryModule(project) applyAndroidComposeLibraryModule(project)
dependencies { dependencies {
implementation project(":matrix:services:sync") implementation project(":chat-engine")
implementation project(":matrix:services:crypto")
implementation project(":features:navigator") implementation project(":features:navigator")
implementation project(':domains:store') implementation project(':domains:store')
implementation project(':domains:android:push') implementation project(':domains:android:push')

View File

@ -5,16 +5,14 @@ import app.dapk.st.core.*
import app.dapk.st.domain.StoreModule import app.dapk.st.domain.StoreModule
import app.dapk.st.domain.application.eventlog.LoggingStore import app.dapk.st.domain.application.eventlog.LoggingStore
import app.dapk.st.domain.application.message.MessageOptionsStore import app.dapk.st.domain.application.message.MessageOptionsStore
import app.dapk.st.matrix.crypto.CryptoService import app.dapk.st.engine.ChatEngine
import app.dapk.st.matrix.sync.SyncService
import app.dapk.st.push.PushModule import app.dapk.st.push.PushModule
import app.dapk.st.settings.eventlogger.EventLoggerViewModel import app.dapk.st.settings.eventlogger.EventLoggerViewModel
class SettingsModule( class SettingsModule(
private val chatEngine: ChatEngine,
private val storeModule: StoreModule, private val storeModule: StoreModule,
private val pushModule: PushModule, private val pushModule: PushModule,
private val cryptoService: CryptoService,
private val syncService: SyncService,
private val contentResolver: ContentResolver, private val contentResolver: ContentResolver,
private val buildMeta: BuildMeta, private val buildMeta: BuildMeta,
private val deviceMeta: DeviceMeta, private val deviceMeta: DeviceMeta,
@ -26,10 +24,9 @@ class SettingsModule(
internal fun settingsViewModel(): SettingsViewModel { internal fun settingsViewModel(): SettingsViewModel {
return SettingsViewModel( return SettingsViewModel(
chatEngine,
storeModule.cacheCleaner(), storeModule.cacheCleaner(),
contentResolver, contentResolver,
cryptoService,
syncService,
UriFilenameResolver(contentResolver, coroutineDispatchers), UriFilenameResolver(contentResolver, coroutineDispatchers),
SettingsItemFactory(buildMeta, deviceMeta, pushModule.pushTokenRegistrars(), themeStore, loggingStore, messageOptionsStore), SettingsItemFactory(buildMeta, deviceMeta, pushModule.pushTokenRegistrars(), themeStore, loggingStore, messageOptionsStore),
pushModule.pushTokenRegistrars(), pushModule.pushTokenRegistrars(),

View File

@ -42,7 +42,7 @@ import app.dapk.st.core.components.Header
import app.dapk.st.core.extensions.takeAs import app.dapk.st.core.extensions.takeAs
import app.dapk.st.core.getActivity import app.dapk.st.core.getActivity
import app.dapk.st.design.components.* import app.dapk.st.design.components.*
import app.dapk.st.matrix.crypto.ImportResult import app.dapk.st.engine.ImportResult
import app.dapk.st.navigator.Navigator import app.dapk.st.navigator.Navigator
import app.dapk.st.settings.SettingsEvent.* import app.dapk.st.settings.SettingsEvent.*
import app.dapk.st.settings.eventlogger.EventLogActivity import app.dapk.st.settings.eventlogger.EventLogActivity

View File

@ -2,10 +2,9 @@ package app.dapk.st.settings
import android.net.Uri import android.net.Uri
import app.dapk.st.core.Lce import app.dapk.st.core.Lce
import app.dapk.st.core.LceWithProgress
import app.dapk.st.design.components.Route import app.dapk.st.design.components.Route
import app.dapk.st.design.components.SpiderPage import app.dapk.st.design.components.SpiderPage
import app.dapk.st.matrix.crypto.ImportResult import app.dapk.st.engine.ImportResult
import app.dapk.st.push.Registrar import app.dapk.st.push.Registrar
internal data class SettingsScreenState( internal data class SettingsScreenState(

View File

@ -9,9 +9,8 @@ import app.dapk.st.design.components.SpiderPage
import app.dapk.st.domain.StoreCleaner import app.dapk.st.domain.StoreCleaner
import app.dapk.st.domain.application.eventlog.LoggingStore import app.dapk.st.domain.application.eventlog.LoggingStore
import app.dapk.st.domain.application.message.MessageOptionsStore import app.dapk.st.domain.application.message.MessageOptionsStore
import app.dapk.st.matrix.crypto.CryptoService import app.dapk.st.engine.ChatEngine
import app.dapk.st.matrix.crypto.ImportResult import app.dapk.st.engine.ImportResult
import app.dapk.st.matrix.sync.SyncService
import app.dapk.st.push.PushTokenRegistrars import app.dapk.st.push.PushTokenRegistrars
import app.dapk.st.push.Registrar import app.dapk.st.push.Registrar
import app.dapk.st.settings.SettingItem.Id.* import app.dapk.st.settings.SettingItem.Id.*
@ -26,10 +25,9 @@ import kotlinx.coroutines.launch
private const val PRIVACY_POLICY_URL = "https://ouchadam.github.io/small-talk/privacy/" private const val PRIVACY_POLICY_URL = "https://ouchadam.github.io/small-talk/privacy/"
internal class SettingsViewModel( internal class SettingsViewModel(
private val chatEngine: ChatEngine,
private val cacheCleaner: StoreCleaner, private val cacheCleaner: StoreCleaner,
private val contentResolver: ContentResolver, private val contentResolver: ContentResolver,
private val cryptoService: CryptoService,
private val syncService: SyncService,
private val uriFilenameResolver: UriFilenameResolver, private val uriFilenameResolver: UriFilenameResolver,
private val settingsItemFactory: SettingsItemFactory, private val settingsItemFactory: SettingsItemFactory,
private val pushTokenRegistrars: PushTokenRegistrars, private val pushTokenRegistrars: PushTokenRegistrars,
@ -142,7 +140,7 @@ internal class SettingsViewModel(
fun importFromFileKeys(file: Uri, passphrase: String) { fun importFromFileKeys(file: Uri, passphrase: String) {
updatePageState<Page.ImportRoomKey> { copy(importProgress = ImportResult.Update(0)) } updatePageState<Page.ImportRoomKey> { copy(importProgress = ImportResult.Update(0)) }
viewModelScope.launch { viewModelScope.launch {
with(cryptoService) { with(chatEngine) {
runCatching { contentResolver.openInputStream(file)!! } runCatching { contentResolver.openInputStream(file)!! }
.fold( .fold(
onSuccess = { fileStream -> onSuccess = { fileStream ->
@ -159,7 +157,7 @@ internal class SettingsViewModel(
} }
is ImportResult.Success -> { is ImportResult.Success -> {
syncService.forceManualRefresh(it.roomIds.toList()) chatEngine.refresh(it.roomIds.toList())
} }
} }
} }

View File

@ -4,6 +4,7 @@ import app.dapk.st.matrix.auth.AuthService
import app.dapk.st.matrix.sync.InviteMeta import app.dapk.st.matrix.sync.InviteMeta
import app.dapk.st.matrix.auth.AuthService.LoginRequest as MatrixLoginRequest import app.dapk.st.matrix.auth.AuthService.LoginRequest as MatrixLoginRequest
import app.dapk.st.matrix.auth.AuthService.LoginResult as MatrixLoginResult import app.dapk.st.matrix.auth.AuthService.LoginResult as MatrixLoginResult
import app.dapk.st.matrix.crypto.ImportResult as MatrixImportResult
import app.dapk.st.matrix.room.ProfileService.Me as MatrixMe import app.dapk.st.matrix.room.ProfileService.Me as MatrixMe
import app.dapk.st.matrix.sync.LastMessage as MatrixLastMessage import app.dapk.st.matrix.sync.LastMessage as MatrixLastMessage
import app.dapk.st.matrix.sync.RoomInvite as MatrixRoomInvite import app.dapk.st.matrix.sync.RoomInvite as MatrixRoomInvite
@ -62,3 +63,17 @@ fun InviteMeta.engine() = when (this) {
is InviteMeta.Room -> RoomInvite.InviteMeta.Room(this.roomName) is InviteMeta.Room -> RoomInvite.InviteMeta.Room(this.roomName)
} }
fun MatrixImportResult.engine() = when (this) {
is MatrixImportResult.Error -> ImportResult.Error(
when (val error = this.cause) {
MatrixImportResult.Error.Type.InvalidFile -> ImportResult.Error.Type.InvalidFile
MatrixImportResult.Error.Type.NoKeysFound -> ImportResult.Error.Type.NoKeysFound
MatrixImportResult.Error.Type.UnableToOpenFile -> ImportResult.Error.Type.UnableToOpenFile
MatrixImportResult.Error.Type.UnexpectedDecryptionOutput -> ImportResult.Error.Type.UnexpectedDecryptionOutput
is MatrixImportResult.Error.Type.Unknown -> ImportResult.Error.Type.Unknown(error.cause)
}
)
is MatrixImportResult.Success -> ImportResult.Success(this.roomIds, this.totalImportedKeysCount)
is MatrixImportResult.Update -> ImportResult.Update(this.importedKeysCount)
}

View File

@ -30,6 +30,7 @@ import app.dapk.st.olm.OlmStore
import app.dapk.st.olm.OlmWrapper import app.dapk.st.olm.OlmWrapper
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import java.io.InputStream
import java.time.Clock import java.time.Clock
class MatrixEngine internal constructor( class MatrixEngine internal constructor(
@ -50,6 +51,17 @@ class MatrixEngine internal constructor(
return matrix.value.profileService().me(forceRefresh).engine() return matrix.value.profileService().me(forceRefresh).engine()
} }
override suspend fun refresh(roomIds: List<RoomId>) {
matrix.value.syncService().forceManualRefresh(roomIds)
}
override suspend fun InputStream.importRoomKeys(password: String): Flow<ImportResult> {
return with(matrix.value.cryptoService()) {
importRoomKeys(password).map { it.engine() }
}
}
class Factory { class Factory {
fun create( fun create(
@ -72,7 +84,7 @@ class MatrixEngine internal constructor(
knownDeviceStore: KnownDeviceStore, knownDeviceStore: KnownDeviceStore,
olmStore: OlmStore, olmStore: OlmStore,
): ChatEngine { ): ChatEngine {
val lazyMatrix = unsafeLazy { val lazyMatrix = lazy {
MatrixFactory.createMatrix( MatrixFactory.createMatrix(
base64, base64,
buildMeta, buildMeta,