From e617c90fb7cd79e554946aa865e46a9ed9a78b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BBerko?= Date: Tue, 19 Nov 2024 12:24:25 +0100 Subject: [PATCH] fix: folders now found (#3111) --- .../folders/ConversationFolderMappers.kt | 14 +++++++ .../folders/ConversationFolderRepository.kt | 22 ++++++++++ .../ConversationFolderRepositoryTest.kt | 41 +++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderMappers.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderMappers.kt index aece3287d55..997efe7ba17 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderMappers.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderMappers.kt @@ -21,6 +21,7 @@ import com.wire.kalium.logic.data.conversation.ConversationFolder import com.wire.kalium.logic.data.conversation.FolderType import com.wire.kalium.logic.data.conversation.FolderWithConversations import com.wire.kalium.logic.data.id.QualifiedID +import com.wire.kalium.logic.data.id.toApi import com.wire.kalium.logic.data.id.toDao import com.wire.kalium.logic.data.id.toModel import com.wire.kalium.network.api.authenticated.properties.LabelDTO @@ -36,11 +37,24 @@ fun LabelDTO.toFolder(selfDomain: String) = FolderWithConversations( type = type.toFolderType() ) +fun FolderWithConversations.toLabel() = LabelDTO( + id = id, + name = name, + qualifiedConversations = conversationIdList.map { it.toApi() }, + conversations = conversationIdList.map { it.value }, + type = type.toLabel() +) + fun LabelTypeDTO.toFolderType() = when (this) { LabelTypeDTO.USER -> FolderType.USER LabelTypeDTO.FAVORITE -> FolderType.FAVORITE } +fun FolderType.toLabel() = when (this) { + FolderType.USER -> LabelTypeDTO.USER + FolderType.FAVORITE -> LabelTypeDTO.FAVORITE +} + fun ConversationFolderEntity.toModel() = ConversationFolder( id = id, name = name, 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 ea1028f5c3f..caf5173737c 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 @@ -20,6 +20,7 @@ package com.wire.kalium.logic.data.conversation.folders import com.benasher44.uuid.uuid4 import com.wire.kalium.logger.KaliumLogger.Companion.ApplicationFlow.CONVERSATIONS_FOLDERS import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.NetworkFailure import com.wire.kalium.logic.data.conversation.ConversationDetailsWithEvents import com.wire.kalium.logic.data.conversation.ConversationFolder import com.wire.kalium.logic.data.conversation.ConversationMapper @@ -28,14 +29,19 @@ import com.wire.kalium.logic.data.conversation.FolderWithConversations import com.wire.kalium.logic.data.id.QualifiedID import com.wire.kalium.logic.di.MapperProvider import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.functional.flatMapLeft import com.wire.kalium.logic.functional.map import com.wire.kalium.logic.functional.onFailure import com.wire.kalium.logic.functional.onSuccess import com.wire.kalium.logic.kaliumLogger import com.wire.kalium.logic.wrapApiRequest import com.wire.kalium.logic.wrapStorageRequest +import com.wire.kalium.network.api.authenticated.properties.LabelListResponseDTO +import com.wire.kalium.network.api.authenticated.properties.PropertyKey import com.wire.kalium.network.api.base.authenticated.properties.PropertiesApi +import com.wire.kalium.network.exceptions.KaliumException import com.wire.kalium.persistence.dao.conversation.folder.ConversationFolderDAO +import io.ktor.http.HttpStatusCode import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -74,6 +80,18 @@ internal class ConversationFolderDataSource internal constructor( kaliumLogger.withFeatureId(CONVERSATIONS_FOLDERS).v("Fetching conversation folders") userPropertiesApi.getLabels() } + .flatMapLeft { + if (it is NetworkFailure.ServerMiscommunication + && it.kaliumException is KaliumException.InvalidRequestError + && it.kaliumException.errorResponse.code == HttpStatusCode.NotFound.value + ) { + kaliumLogger.withFeatureId(CONVERSATIONS_FOLDERS).v("User has no labels, creating an empty list") + // If the user has no labels, we create an empty list and on next stage we will create a favorite label + Either.Right(LabelListResponseDTO(emptyList())) + } else { + Either.Left(it) + } + } .onSuccess { labelsResponse -> val folders = labelsResponse.labels.map { it.toFolder(selfUserId.domain) }.toMutableList() val favoriteLabel = folders.firstOrNull { it.type == FolderType.FAVORITE } @@ -88,6 +106,10 @@ internal class ConversationFolderDataSource internal constructor( conversationIdList = emptyList() ) ) + userPropertiesApi.setProperty( + PropertyKey.WIRE_LABELS, + labelsResponse.copy(labels = folders.map { it.toLabel() }) + ) } conversationFolderDAO.updateConversationFolders(folders.map { it.toDao() }) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepositoryTest.kt index 88557c7bc48..8b830cb30dc 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepositoryTest.kt @@ -26,7 +26,9 @@ import com.wire.kalium.logic.framework.TestUser import com.wire.kalium.logic.util.shouldFail import com.wire.kalium.logic.util.shouldSucceed import com.wire.kalium.network.api.authenticated.properties.LabelListResponseDTO +import com.wire.kalium.network.api.authenticated.properties.PropertyKey import com.wire.kalium.network.api.base.authenticated.properties.PropertiesApi +import com.wire.kalium.network.api.model.ErrorResponse import com.wire.kalium.network.exceptions.KaliumException import com.wire.kalium.network.utils.NetworkResponse import com.wire.kalium.persistence.dao.conversation.ConversationDetailsWithEventsEntity @@ -34,11 +36,13 @@ import com.wire.kalium.persistence.dao.conversation.folder.ConversationFolderDAO import com.wire.kalium.persistence.dao.conversation.folder.ConversationFolderEntity import com.wire.kalium.persistence.dao.conversation.folder.ConversationFolderTypeEntity import com.wire.kalium.persistence.dao.unread.ConversationUnreadEventEntity +import io.ktor.http.HttpStatusCode import io.ktor.util.reflect.instanceOf import io.mockative.Mock import io.mockative.any import io.mockative.coEvery import io.mockative.coVerify +import io.mockative.eq import io.mockative.mock import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf @@ -119,6 +123,38 @@ class ConversationFolderRepositoryTest { } } + @Test + fun given404ErrorWhenFetchingFoldersThenShouldCreateEmptyLabelList() = runTest { + // given + val arrangement = Arrangement() + .withSetProperty(NetworkResponse.Success(Unit, emptyMap(), HttpStatusCode.OK.value)) + .withFetchConversationLabels( + NetworkResponse.Error( + KaliumException.InvalidRequestError( + errorResponse = ErrorResponse( + code = HttpStatusCode.NotFound.value, + message = "", + label = "" + ) + ) + ) + ) + + // when + val result = arrangement.repository.fetchConversationFolders() + + // then + result.shouldSucceed() + coVerify { + arrangement.userPropertiesApi.setProperty( + eq(PropertyKey.WIRE_LABELS), + any() + ) + }.wasInvoked() + + coVerify { arrangement.conversationFolderDAO.updateConversationFolders(any()) }.wasInvoked() + } + private class Arrangement { @Mock @@ -156,5 +192,10 @@ class ConversationFolderRepositoryTest { coEvery { userPropertiesApi.getLabels() }.returns(response) return this } + + suspend fun withSetProperty(response: NetworkResponse): Arrangement { + coEvery { userPropertiesApi.setProperty(any(), any()) }.returns(response) + return this + } } }