diff --git a/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFilter.kt b/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFilter.kt index f1ca2a7bf39..a76fac75ca0 100644 --- a/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFilter.kt +++ b/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFilter.kt @@ -17,9 +17,22 @@ */ package com.wire.kalium.logic.data.conversation -enum class ConversationFilter { - ALL, - FAVORITES, - GROUPS, - ONE_ON_ONE +import kotlinx.serialization.Serializable + +@Serializable +sealed class ConversationFilter { + @Serializable + data object All : ConversationFilter() + + @Serializable + data object Favorites : ConversationFilter() + + @Serializable + data object Groups : ConversationFilter() + + @Serializable + data object OneOnOne : ConversationFilter() + + @Serializable + data class Folder(val folderName: String, val folderId: String) : ConversationFilter() } diff --git a/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFolder.kt b/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFolder.kt index 675e9f5794f..cf64352dd3d 100644 --- a/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFolder.kt +++ b/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFolder.kt @@ -18,11 +18,14 @@ package com.wire.kalium.logic.data.conversation import com.wire.kalium.logic.data.id.QualifiedID +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +@Serializable data class ConversationFolder( - val id: String, - val name: String, - val type: FolderType + @SerialName("id") val id: String, + @SerialName("name") val name: String, + @SerialName("folder_type") val type: FolderType ) data class FolderWithConversations( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9060b93e117..b6746e68430 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,7 +44,7 @@ core-crypto-multiplatform = "0.6.0-rc.3-multiplatform-pre1" completeKotlin = "1.1.0" desugar-jdk = "2.0.4" kermit = "2.0.3" -detekt = "1.23.6" +detekt = "1.23.7" agp = "8.5.2" dokka = "1.8.20" carthage = "0.0.1" diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt index 4fd77d402b4..a09c8241f17 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/configuration/server/ServerConfigRepository.kt @@ -66,6 +66,7 @@ interface ServerConfigRepository { */ suspend fun configForUser(userId: UserId): Either suspend fun commonApiVersion(domain: String): Either + suspend fun getTeamUrlForUser(userId: UserId): String? } @Suppress("LongParameterList", "TooManyFunctions") @@ -165,4 +166,6 @@ internal class ServerConfigDataSource( is ApiVersionDTO.Valid -> Either.Right(it) } }.map { serverConfigMapper.fromDTO(it) } + + override suspend fun getTeamUrlForUser(userId: UserId): String? = dao.teamUrlForUser(userId.toDao()) } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationMapper.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationMapper.kt index cc2d9995a75..6382559ee23 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationMapper.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationMapper.kt @@ -676,15 +676,16 @@ internal fun ConversationEntity.VerificationStatus.toModel(): Conversation.Verif } internal fun ConversationFilter.toDao(): ConversationFilterEntity = when (this) { - ConversationFilter.ALL -> ConversationFilterEntity.ALL - ConversationFilter.FAVORITES -> ConversationFilterEntity.FAVORITES - ConversationFilter.GROUPS -> ConversationFilterEntity.GROUPS - ConversationFilter.ONE_ON_ONE -> ConversationFilterEntity.ONE_ON_ONE + ConversationFilter.All -> ConversationFilterEntity.ALL + ConversationFilter.Favorites -> ConversationFilterEntity.FAVORITES + ConversationFilter.Groups -> ConversationFilterEntity.GROUPS + ConversationFilter.OneOnOne -> ConversationFilterEntity.ONE_ON_ONE + is ConversationFilter.Folder -> ConversationFilterEntity.ALL // TODO think how to secure that } internal fun ConversationFilterEntity.toModel(): ConversationFilter = when (this) { - ConversationFilterEntity.ALL -> ConversationFilter.ALL - ConversationFilterEntity.FAVORITES -> ConversationFilter.FAVORITES - ConversationFilterEntity.GROUPS -> ConversationFilter.GROUPS - ConversationFilterEntity.ONE_ON_ONE -> ConversationFilter.ONE_ON_ONE + ConversationFilterEntity.ALL -> ConversationFilter.All + ConversationFilterEntity.FAVORITES -> ConversationFilter.Favorites + ConversationFilterEntity.GROUPS -> ConversationFilter.Groups + ConversationFilterEntity.ONE_ON_ONE -> ConversationFilter.OneOnOne } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepository.kt index f199fe862f7..2508b24762a 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepository.kt @@ -132,12 +132,12 @@ interface ConversationRepository { suspend fun observeConversationList(): Flow> suspend fun observeConversationListDetails( fromArchive: Boolean, - conversationFilter: ConversationFilter = ConversationFilter.ALL + conversationFilter: ConversationFilter = ConversationFilter.All ): Flow> suspend fun observeConversationListDetailsWithEvents( fromArchive: Boolean = false, - conversationFilter: ConversationFilter = ConversationFilter.ALL + conversationFilter: ConversationFilter = ConversationFilter.All ): Flow> suspend fun getConversationIds( diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryExtensions.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryExtensions.kt index aec18932a97..c41464ea225 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryExtensions.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryExtensions.kt @@ -73,5 +73,5 @@ data class ConversationQueryConfig( val fromArchive: Boolean = false, val onlyInteractionEnabled: Boolean = false, val newActivitiesOnTop: Boolean = false, - val conversationFilter: ConversationFilter = ConversationFilter.ALL, + val conversationFilter: ConversationFilter = ConversationFilter.All, ) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepository.kt index 70ad373bdfa..5db72788cbd 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepository.kt @@ -34,6 +34,7 @@ import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.functional.flatMap import com.wire.kalium.logic.functional.flatMapLeft import com.wire.kalium.logic.functional.map +import com.wire.kalium.logic.functional.mapRight import com.wire.kalium.logic.functional.onFailure import com.wire.kalium.logic.functional.onSuccess import com.wire.kalium.logic.kaliumLogger @@ -57,6 +58,7 @@ internal interface ConversationFolderRepository { suspend fun addConversationToFolder(conversationId: QualifiedID, folderId: String): Either suspend fun removeConversationFromFolder(conversationId: QualifiedID, folderId: String): Either suspend fun syncConversationFoldersFromLocal(): Either + suspend fun observeUserFolders(): Flow>> } internal class ConversationFolderDataSource internal constructor( @@ -72,7 +74,7 @@ internal class ConversationFolderDataSource internal constructor( } override suspend fun getFavoriteConversationFolder(): Either = wrapStorageRequest { - conversationFolderDAO.getFavoriteConversationFolder().toModel() + conversationFolderDAO.getFavoriteConversationFolder()?.toModel() } override suspend fun observeConversationsFromFolder(folderId: String): Flow> = @@ -152,4 +154,10 @@ internal class ConversationFolderDataSource internal constructor( } } } + + override suspend fun observeUserFolders(): Flow>> { + return conversationFolderDAO.observeUserFolders() + .wrapStorageRequest() + .mapRight { folderEntities -> folderEntities.map { it.toModel() } } + } } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt index 543d5f9030c..80a977d714e 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt @@ -291,6 +291,7 @@ import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTim import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveTeamSettingsSelfDeletingStatusUseCase import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveTeamSettingsSelfDeletingStatusUseCaseImpl import com.wire.kalium.logic.feature.selfDeletingMessages.PersistNewSelfDeletionTimerUseCaseImpl +import com.wire.kalium.logic.feature.server.GetTeamUrlUseCase import com.wire.kalium.logic.feature.service.ServiceScope import com.wire.kalium.logic.feature.session.GetProxyCredentialsUseCase import com.wire.kalium.logic.feature.session.GetProxyCredentialsUseCaseImpl @@ -1830,6 +1831,7 @@ class UserSessionScope internal constructor( legalHoldHandler, notificationTokenRepository, this, + userStorage, userScopedLogger, ) } @@ -2144,6 +2146,13 @@ class UserSessionScope internal constructor( kaliumLogger = userScopedLogger, ) + val getTeamUrlUseCase: GetTeamUrlUseCase by lazy { + GetTeamUrlUseCase( + userId, + authenticationScope.serverConfigRepository, + ) + } + /** * This will start subscribers of observable work per user session, as long as the user is logged in. * When the user logs out, this work will be canceled. diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ConversationScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ConversationScope.kt index 0f3be756ff3..bc65552ad2d 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ConversationScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ConversationScope.kt @@ -55,6 +55,8 @@ import com.wire.kalium.logic.feature.conversation.folder.GetFavoriteFolderUseCas import com.wire.kalium.logic.feature.conversation.folder.GetFavoriteFolderUseCaseImpl import com.wire.kalium.logic.feature.conversation.folder.ObserveConversationsFromFolderUseCase import com.wire.kalium.logic.feature.conversation.folder.ObserveConversationsFromFolderUseCaseImpl +import com.wire.kalium.logic.feature.conversation.folder.ObserveUserFoldersUseCase +import com.wire.kalium.logic.feature.conversation.folder.ObserveUserFoldersUseCaseImpl import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromFavoritesUseCase import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromFavoritesUseCaseImpl import com.wire.kalium.logic.feature.conversation.guestroomlink.CanCreatePasswordProtectedLinksUseCase @@ -361,4 +363,6 @@ class ConversationScope internal constructor( get() = AddConversationToFavoritesUseCaseImpl(conversationFolderRepository) val removeConversationFromFavorites: RemoveConversationFromFavoritesUseCase get() = RemoveConversationFromFavoritesUseCaseImpl(conversationFolderRepository) + val observeUserFolders: ObserveUserFoldersUseCase + get() = ObserveUserFoldersUseCaseImpl(conversationFolderRepository) } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ObserveConversationListDetailsWithEventsUseCaseImpl.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ObserveConversationListDetailsWithEventsUseCaseImpl.kt index 4f7f9529f61..5a3b59405e8 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ObserveConversationListDetailsWithEventsUseCaseImpl.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ObserveConversationListDetailsWithEventsUseCaseImpl.kt @@ -45,16 +45,26 @@ internal class ObserveConversationListDetailsWithEventsUseCaseImpl( fromArchive: Boolean, conversationFilter: ConversationFilter ): Flow> { - return if (conversationFilter == ConversationFilter.FAVORITES) { - when (val result = getFavoriteFolder()) { - GetFavoriteFolderUseCase.Result.Failure -> { - flowOf(emptyList()) + return when (conversationFilter) { + ConversationFilter.Favorites -> { + when (val result = getFavoriteFolder()) { + GetFavoriteFolderUseCase.Result.Failure -> { + flowOf(emptyList()) + } + + is GetFavoriteFolderUseCase.Result.Success -> + conversationFolderRepository.observeConversationsFromFolder(result.folder.id) } + } - is GetFavoriteFolderUseCase.Result.Success -> conversationFolderRepository.observeConversationsFromFolder(result.folder.id) + is ConversationFilter.Folder -> { + conversationFolderRepository.observeConversationsFromFolder(conversationFilter.folderId) } - } else { - conversationRepository.observeConversationListDetailsWithEvents(fromArchive, conversationFilter) + + ConversationFilter.All, + ConversationFilter.Groups, + ConversationFilter.OneOnOne -> + conversationRepository.observeConversationListDetailsWithEvents(fromArchive, conversationFilter) } } } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveConversationsFromFolderUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveConversationsFromFolderUseCase.kt index b0ffa60fa93..549b951c5fc 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveConversationsFromFolderUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveConversationsFromFolderUseCase.kt @@ -19,7 +19,10 @@ package com.wire.kalium.logic.feature.conversation.folder import com.wire.kalium.logic.data.conversation.ConversationDetailsWithEvents import com.wire.kalium.logic.data.conversation.folders.ConversationFolderRepository +import com.wire.kalium.util.KaliumDispatcher +import com.wire.kalium.util.KaliumDispatcherImpl import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOn /** * This use case will observe and return the list of conversations from given folder. @@ -31,9 +34,10 @@ fun interface ObserveConversationsFromFolderUseCase { internal class ObserveConversationsFromFolderUseCaseImpl( private val conversationFolderRepository: ConversationFolderRepository, + private val dispatchers: KaliumDispatcher = KaliumDispatcherImpl ) : ObserveConversationsFromFolderUseCase { - override suspend operator fun invoke(folderId: String): Flow> { - return conversationFolderRepository.observeConversationsFromFolder(folderId) - } + override suspend operator fun invoke(folderId: String): Flow> = + conversationFolderRepository.observeConversationsFromFolder(folderId) + .flowOn(dispatchers.io) } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveUserFoldersUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveUserFoldersUseCase.kt new file mode 100644 index 00000000000..3935cd2af28 --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveUserFoldersUseCase.kt @@ -0,0 +1,46 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.feature.conversation.folder + +import com.wire.kalium.logic.data.conversation.ConversationFolder +import com.wire.kalium.logic.data.conversation.folders.ConversationFolderRepository +import com.wire.kalium.logic.functional.mapToRightOr +import com.wire.kalium.util.KaliumDispatcher +import com.wire.kalium.util.KaliumDispatcherImpl +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOn + +/** + * This use case will observe and return the list of all user folders. + * @see ConversationFolder + */ +fun interface ObserveUserFoldersUseCase { + suspend operator fun invoke(): Flow> +} + +internal class ObserveUserFoldersUseCaseImpl( + private val conversationFolderRepository: ConversationFolderRepository, + private val dispatchers: KaliumDispatcher = KaliumDispatcherImpl +) : ObserveUserFoldersUseCase { + + override suspend operator fun invoke(): Flow> { + return conversationFolderRepository.observeUserFolders() + .mapToRightOr(emptyList()) + .flowOn(dispatchers.io) + } +} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/debug/ChangeProfilingUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/debug/ChangeProfilingUseCase.kt new file mode 100644 index 00000000000..83588fea472 --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/debug/ChangeProfilingUseCase.kt @@ -0,0 +1,32 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.feature.debug + +import com.wire.kalium.logic.di.UserStorage + +class ChangeProfilingUseCase( + private val userStorage: UserStorage, +) { + /** + * Changes the profiling of the database (cipher_profile) if the profile is specified and the database is encrypted + * @param enabled true to enable profiling, false to disable + */ + operator fun invoke(enabled: Boolean) { + userStorage.database.changeProfiling(enabled) + } +} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/debug/DebugScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/debug/DebugScope.kt index 92d7176faaf..34b31cdf4b7 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/debug/DebugScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/debug/DebugScope.kt @@ -40,6 +40,7 @@ import com.wire.kalium.logic.data.prekey.PreKeyRepository import com.wire.kalium.logic.data.sync.SlowSyncRepository import com.wire.kalium.logic.data.user.UserId import com.wire.kalium.logic.data.user.UserRepository +import com.wire.kalium.logic.di.UserStorage import com.wire.kalium.logic.feature.message.MLSMessageCreator import com.wire.kalium.logic.feature.message.MLSMessageCreatorImpl import com.wire.kalium.logic.feature.message.MessageEnvelopeCreator @@ -92,6 +93,7 @@ class DebugScope internal constructor( private val legalHoldHandler: LegalHoldHandler, private val notificationTokenRepository: NotificationTokenRepository, private val scope: CoroutineScope, + userStorage: UserStorage, logger: KaliumLogger, internal val dispatcher: KaliumDispatcher = KaliumDispatcherImpl, ) { @@ -224,4 +226,6 @@ class DebugScope internal constructor( clientRepository, notificationTokenRepository, ) + + val changeProfiling: ChangeProfilingUseCase = ChangeProfilingUseCase(userStorage) } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/GetTeamUrlUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/GetTeamUrlUseCase.kt new file mode 100644 index 00000000000..fc11e34b573 --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/server/GetTeamUrlUseCase.kt @@ -0,0 +1,31 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.feature.server + +import com.wire.kalium.logic.configuration.server.ServerConfigRepository +import com.wire.kalium.logic.data.user.UserId + +/** + * Use case to get the team url for the current user. + */ +class GetTeamUrlUseCase internal constructor( + private val selfUserId: UserId, + private val serverConfigRepository: ServerConfigRepository +) { + suspend operator fun invoke(): String = serverConfigRepository.getTeamUrlForUser(selfUserId) ?: "" +} diff --git a/persistence/src/androidMain/kotlin/com/wire/kalium/persistence/db/UserDatabase.kt b/persistence/src/androidMain/kotlin/com/wire/kalium/persistence/db/UserDatabase.kt index 39f73fdb694..4491d1bf47c 100644 --- a/persistence/src/androidMain/kotlin/com/wire/kalium/persistence/db/UserDatabase.kt +++ b/persistence/src/androidMain/kotlin/com/wire/kalium/persistence/db/UserDatabase.kt @@ -51,7 +51,14 @@ actual fun userDatabaseBuilder( ) { isWALEnabled = enableWAL } - return UserDatabaseBuilder(userId, driver, dispatcher, platformDatabaseData, isEncryptionEnabled) + return UserDatabaseBuilder( + userId = userId, + sqlDriver = driver, + dispatcher = dispatcher, + platformDatabaseData = platformDatabaseData, + isEncrypted = isEncryptionEnabled, + cipherProfile = "logcat", + ) } actual fun userDatabaseDriverByPath( diff --git a/persistence/src/commonMain/db_global/com/wire/kalium/persistence/ServerConfiguration.sq b/persistence/src/commonMain/db_global/com/wire/kalium/persistence/ServerConfiguration.sq index 4fa81bcab28..dfcd7807ffd 100644 --- a/persistence/src/commonMain/db_global/com/wire/kalium/persistence/ServerConfiguration.sq +++ b/persistence/src/commonMain/db_global/com/wire/kalium/persistence/ServerConfiguration.sq @@ -56,6 +56,9 @@ SELECT * FROM ServerConfiguration WHERE title = ? AND apiBaseUrl = ? AND webSock getByUser: SELECT * FROM ServerConfiguration WHERE id = (SELECT server_config_id FROM Accounts WHERE id = :userId); +getTeamUrlByUser: +SELECT teamsUrl FROM ServerConfiguration WHERE id = (SELECT server_config_id FROM Accounts WHERE id = :userId); + getServerConfigsWithAccIdWithLastCheckBeforeDate: SELECT sc.*, acc.id FROM Accounts AS acc LEFT JOIN ServerConfiguration AS sc ON acc.server_config_id == sc.id diff --git a/persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationFolders.sq b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationFolders.sq index db44a482e77..38d2c6db4bf 100644 --- a/persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationFolders.sq +++ b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationFolders.sq @@ -17,6 +17,10 @@ CREATE TABLE LabeledConversation ( PRIMARY KEY (folder_id, conversation_id) ); +getUserFolders: +SELECT * FROM ConversationFolder +WHERE folder_type != 'FAVORITE'; + getAllFoldersWithConversations: SELECT conversationFolder.id AS label_id, @@ -60,8 +64,8 @@ VALUES(?, ?); deleteLabeledConversation: DELETE FROM LabeledConversation WHERE conversation_id = ? AND folder_id = ?; -clearFolders: -DELETE FROM ConversationFolder; - clearLabeledConversations: DELETE FROM LabeledConversation; + +clearFolders: +DELETE FROM ConversationFolder; diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAO.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAO.kt index ed1ae82a9f8..0c201de5b8d 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAO.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAO.kt @@ -24,8 +24,9 @@ import kotlinx.coroutines.flow.Flow interface ConversationFolderDAO { suspend fun getFoldersWithConversations(): List suspend fun observeConversationListFromFolder(folderId: String): Flow> - suspend fun getFavoriteConversationFolder(): ConversationFolderEntity + suspend fun getFavoriteConversationFolder(): ConversationFolderEntity? suspend fun updateConversationFolders(folderWithConversationsList: List) suspend fun addConversationToFolder(conversationId: QualifiedIDEntity, folderId: String) suspend fun removeConversationFromFolder(conversationId: QualifiedIDEntity, folderId: String) + suspend fun observeUserFolders(): Flow> } diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOImpl.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOImpl.kt index 3316f030bd9..6e703b82419 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOImpl.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOImpl.kt @@ -18,6 +18,7 @@ package com.wire.kalium.persistence.dao.conversation.folder import app.cash.sqldelight.coroutines.asFlow +import com.wire.kalium.persistence.ConversationFolder import com.wire.kalium.persistence.ConversationFoldersQueries import com.wire.kalium.persistence.GetAllFoldersWithConversations import com.wire.kalium.persistence.dao.QualifiedIDEntity @@ -26,6 +27,7 @@ import com.wire.kalium.persistence.dao.conversation.ConversationDetailsWithEvent import com.wire.kalium.persistence.util.mapToList import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext import kotlin.coroutines.CoroutineContext @@ -35,6 +37,14 @@ class ConversationFolderDAOImpl internal constructor( ) : ConversationFolderDAO { private val conversationDetailsWithEventsMapper = ConversationDetailsWithEventsMapper + override suspend fun observeUserFolders(): Flow> { + return conversationFoldersQueries.getUserFolders() + .asFlow() + .mapToList() + .map { it.map(::toEntity) } + .flowOn(coroutineContext) + } + override suspend fun getFoldersWithConversations(): List = withContext(coroutineContext) { val labeledConversationList = conversationFoldersQueries.getAllFoldersWithConversations().executeAsList().map(::toEntity) @@ -59,6 +69,12 @@ class ConversationFolderDAOImpl internal constructor( conversationId = row.conversation_id ) + private fun toEntity(row: ConversationFolder) = ConversationFolderEntity( + id = row.id, + name = row.name, + type = row.folder_type + ) + override suspend fun observeConversationListFromFolder(folderId: String): Flow> { return conversationFoldersQueries.getConversationsFromFolder( folderId, @@ -69,11 +85,11 @@ class ConversationFolderDAOImpl internal constructor( .flowOn(coroutineContext) } - override suspend fun getFavoriteConversationFolder(): ConversationFolderEntity { + override suspend fun getFavoriteConversationFolder(): ConversationFolderEntity? { return conversationFoldersQueries.getFavoriteFolder { id, name, folderType -> ConversationFolderEntity(id, name, folderType) } - .executeAsOne() + .executeAsOneOrNull() } override suspend fun updateConversationFolders(folderWithConversationsList: List) = diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/ServerConfigurationDAO.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/ServerConfigurationDAO.kt index 04c83e96f77..00b56040372 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/ServerConfigurationDAO.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/daokaliumdb/ServerConfigurationDAO.kt @@ -118,6 +118,7 @@ internal object ServerConfigMapper { ) } +@Suppress("TooManyFunctions") interface ServerConfigurationDAO { suspend fun deleteById(id: String) suspend fun insert(insertData: InsertData) @@ -129,6 +130,7 @@ interface ServerConfigurationDAO { suspend fun updateServerMetaData(id: String, federation: Boolean, commonApiVersion: Int) suspend fun updateApiVersionAndDomain(id: String, domain: String, commonApiVersion: Int) suspend fun configForUser(userId: UserIDEntity): ServerConfigEntity? + suspend fun teamUrlForUser(userId: UserIDEntity): String? suspend fun setFederationToTrue(id: String) suspend fun getServerConfigsWithAccIdWithLastCheckBeforeDate(date: String): Flow> suspend fun updateBlackListCheckDate(configIds: Set, date: String) @@ -152,6 +154,7 @@ interface ServerConfigurationDAO { ) } +@Suppress("TooManyFunctions") internal class ServerConfigurationDAOImpl internal constructor( private val queries: ServerConfigurationQueries, private val queriesContext: CoroutineContext, @@ -240,4 +243,8 @@ internal class ServerConfigurationDAOImpl internal constructor( override suspend fun updateBlackListCheckDate(configIds: Set, date: String) = withContext(queriesContext) { queries.updateLastBlackListCheckByIds(date, configIds) } + + override suspend fun teamUrlForUser(userId: UserIDEntity): String? = withContext(queriesContext) { + queries.getTeamUrlByUser(userId).executeAsOneOrNull() + } } diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt index 7c75ee447b6..fdf7c7bac9e 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt @@ -112,13 +112,15 @@ internal expect fun userDatabaseDriverByPath( enableWAL: Boolean ): SqlDriver +@Suppress("LongParameterList") class UserDatabaseBuilder internal constructor( private val userId: UserIDEntity, internal val sqlDriver: SqlDriver, dispatcher: CoroutineDispatcher, private val platformDatabaseData: PlatformDatabaseData, private val isEncrypted: Boolean, - private val queriesContext: CoroutineContext = KaliumDispatcherImpl.io + private val queriesContext: CoroutineContext = KaliumDispatcherImpl.io, + private val cipherProfile: String? = null, ) { internal val database: UserDatabase = UserDatabase( @@ -316,6 +318,25 @@ class UserDatabaseBuilder internal constructor( */ fun dbFileLocation(): String? = getDatabaseAbsoluteFileLocation(platformDatabaseData, userId) + /** + * Changes the profiling of the database (cipher_profile) if the profile is specified and the database is encrypted + * @param enabled true to enable profiling, false to disable + */ + fun changeProfiling(enabled: Boolean) { + if (isEncrypted && cipherProfile != null) { + val cipherProfileValue = if (enabled) cipherProfile else "off" + sqlDriver.executeQuery( + identifier = null, + sql = "PRAGMA cipher_profile='$cipherProfileValue'", + mapper = { + it.next() + it.getLong(0).let { QueryResult.Value(it) } + }, + parameters = 0, + ) + } + } + /** * drops DB connection and delete the DB file */ diff --git a/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOTest.kt b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOTest.kt index c55255dd733..d533ccc6dec 100644 --- a/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOTest.kt +++ b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOTest.kt @@ -59,7 +59,8 @@ class ConversationFolderDAOTest : BaseDatabaseTest() { id = folderId, name = "folderName", type = ConversationFolderTypeEntity.USER, - conversationIdList = listOf(conversationEntity1.id)) + conversationIdList = listOf(conversationEntity1.id) + ) db.conversationFolderDAO.updateConversationFolders(listOf(conversationFolderEntity)) val result = db.conversationFolderDAO.observeConversationListFromFolder(folderId).first().first() @@ -79,12 +80,13 @@ class ConversationFolderDAOTest : BaseDatabaseTest() { id = folderId, name = "", type = ConversationFolderTypeEntity.FAVORITE, - conversationIdList = listOf(conversationEntity1.id)) + conversationIdList = listOf(conversationEntity1.id) + ) db.conversationFolderDAO.updateConversationFolders(listOf(conversationFolderEntity)) val result = db.conversationFolderDAO.getFavoriteConversationFolder() - assertEquals(folderId, result.id) + assertEquals(folderId, result?.id) } @Test