Skip to content

Commit

Permalink
feat: conversation favorites [WPB-11637] (#3634)
Browse files Browse the repository at this point in the history
  • Loading branch information
Garzas authored Nov 15, 2024
1 parent 59e5fec commit 91578c9
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -317,4 +317,14 @@ class ConversationModule {
@Provides
fun provideGetPaginatedFlowOfConversationDetailsWithEventsBySearchQueryUseCase(conversationScope: ConversationScope) =
conversationScope.getPaginatedFlowOfConversationDetailsWithEventsBySearchQuery

@ViewModelScoped
@Provides
fun provideObserveConversationsFromFolderUseCase(conversationScope: ConversationScope) =
conversationScope.observeConversationsFromFolder

@ViewModelScoped
@Provides
fun provideGetFavoriteFolderUseCase(conversationScope: ConversationScope) =
conversationScope.getFavoriteFolder
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package com.wire.android.ui.home.conversations.usecase

import androidx.paging.LoadState
import androidx.paging.LoadStates
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.map
Expand All @@ -29,13 +31,18 @@ import com.wire.android.util.ui.WireSessionImageLoader
import com.wire.kalium.logic.data.conversation.ConversationFilter
import com.wire.kalium.logic.data.conversation.ConversationQueryConfig
import com.wire.kalium.logic.feature.conversation.GetPaginatedFlowOfConversationDetailsWithEventsBySearchQueryUseCase
import com.wire.kalium.logic.feature.conversation.folder.GetFavoriteFolderUseCase
import com.wire.kalium.logic.feature.conversation.folder.ObserveConversationsFromFolderUseCase
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class GetConversationsFromSearchUseCase @Inject constructor(
private val useCase: GetPaginatedFlowOfConversationDetailsWithEventsBySearchQueryUseCase,
private val getFavoriteFolderUseCase: GetFavoriteFolderUseCase,
private val observeConversationsFromFromFolder: ObserveConversationsFromFolderUseCase,
private val wireSessionImageLoader: WireSessionImageLoader,
private val userTypeMapper: UserTypeMapper,
private val dispatchers: DispatcherProvider,
Expand All @@ -53,21 +60,44 @@ class GetConversationsFromSearchUseCase @Inject constructor(
initialLoadSize = INITIAL_LOAD_SIZE,
enablePlaceholders = true,
)
return useCase(
queryConfig = ConversationQueryConfig(
searchQuery = searchQuery,
fromArchive = fromArchive,
newActivitiesOnTop = newActivitiesOnTop,
onlyInteractionEnabled = onlyInteractionEnabled,
conversationFilter = conversationFilter,
),
pagingConfig = pagingConfig,
startingOffset = 0L,
).map { pagingData ->
pagingData.map {
it.toConversationItem(wireSessionImageLoader, userTypeMapper, searchQuery)
return when (conversationFilter) {
ConversationFilter.ALL,
ConversationFilter.GROUPS,
ConversationFilter.ONE_ON_ONE -> useCase(
queryConfig = ConversationQueryConfig(
searchQuery = searchQuery,
fromArchive = fromArchive,
newActivitiesOnTop = newActivitiesOnTop,
onlyInteractionEnabled = onlyInteractionEnabled,
conversationFilter = conversationFilter,
),
pagingConfig = pagingConfig,
startingOffset = 0L,
)

ConversationFilter.FAVORITES -> {
when (val result = getFavoriteFolderUseCase.invoke()) {
GetFavoriteFolderUseCase.Result.Failure -> flowOf(emptyList())
is GetFavoriteFolderUseCase.Result.Success ->
observeConversationsFromFromFolder(result.folder.id)
}
.map {
PagingData.from(
it,
sourceLoadStates = LoadStates(
prepend = LoadState.NotLoading(true),
append = LoadState.NotLoading(true),
refresh = LoadState.NotLoading(true),
)
)
}
}
}.flowOn(dispatchers.io())
}
.map { pagingData ->
pagingData.map {
it.toConversationItem(wireSessionImageLoader, userTypeMapper, searchQuery)
}
}.flowOn(dispatchers.io())
}

private companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ class ConversationListViewModelImpl @AssistedInject constructor(
.distinctUntilChanged()
.flatMapLatest { searchQuery: String ->
observeConversationListDetailsWithEvents(
fromArchive = conversationsSource == ConversationsSource.ARCHIVE
fromArchive = conversationsSource == ConversationsSource.ARCHIVE,
conversationFilter = conversationsSource.toFilter()
).map {
it.map { conversationDetails ->
conversationDetails.toConversationItem(
Expand All @@ -230,15 +231,11 @@ class ConversationListViewModelImpl @AssistedInject constructor(
}
}
.map { (conversationItems, searchQuery) ->
val filteredConversationItems = filterConversation(
conversationDetails = conversationItems,
filter = conversationsSource.toFilter()
)
if (searchQuery.isEmpty()) {
filteredConversationItems.withFolders(source = conversationsSource).toImmutableMap()
conversationItems.withFolders(source = conversationsSource).toImmutableMap()
} else {
searchConversation(
conversationDetails = filteredConversationItems,
conversationDetails = conversationItems,
searchQuery = searchQuery
).withFolders(source = conversationsSource).toImmutableMap()
}
Expand Down Expand Up @@ -505,13 +502,3 @@ private fun searchConversation(conversationDetails: List<ConversationItem>, sear
is ConversationItem.PrivateConversation -> details.conversationInfo.name.contains(searchQuery, true)
}
}

private fun filterConversation(conversationDetails: List<ConversationItem>, filter: ConversationFilter): List<ConversationItem> =
conversationDetails.filter { details ->
when (filter) {
ConversationFilter.ALL -> true
ConversationFilter.FAVORITES -> false
ConversationFilter.GROUPS -> details is ConversationItem.GroupConversation
ConversationFilter.ONE_ON_ONE -> details is ConversationItem.PrivateConversation
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@ import com.wire.android.mapper.UserTypeMapper
import com.wire.android.ui.home.conversationslist.model.Membership
import com.wire.android.util.ui.WireSessionImageLoader
import com.wire.kalium.logic.data.conversation.ConversationDetailsWithEvents
import com.wire.kalium.logic.data.conversation.ConversationFilter
import com.wire.kalium.logic.data.conversation.ConversationFolder
import com.wire.kalium.logic.data.conversation.ConversationQueryConfig
import com.wire.kalium.logic.data.conversation.FolderType
import com.wire.kalium.logic.feature.conversation.GetPaginatedFlowOfConversationDetailsWithEventsBySearchQueryUseCase
import com.wire.kalium.logic.feature.conversation.folder.GetFavoriteFolderUseCase
import com.wire.kalium.logic.feature.conversation.folder.ObserveConversationsFromFolderUseCase
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.coVerify
Expand Down Expand Up @@ -80,11 +85,48 @@ class GetConversationsFromSearchUseCaseTest {
}
}

@Test
fun givenFavoritesFilter_whenGettingConversations_thenObserveConversationsFromFolder() = runTest(dispatcherProvider.main()) {
// Given
val favoriteFolderId = "folder_id"
val folderResult = GetFavoriteFolderUseCase.Result.Success(
folder = ConversationFolder(id = favoriteFolderId, name = "", FolderType.FAVORITE)
)
val conversationsList = listOf(
ConversationDetailsWithEvents(TestConversationDetails.CONVERSATION_ONE_ONE)
)

val (arrangement, useCase) = Arrangement()
.withFavoriteFolderResult(folderResult)
.withFolderConversationsResult(conversationsList)
.arrange()

// When
useCase(
searchQuery = "",
fromArchive = false,
newActivitiesOnTop = false,
onlyInteractionEnabled = false,
conversationFilter = ConversationFilter.FAVORITES
).asSnapshot()

// Then
coVerify(exactly = 1) { arrangement.getFavoriteFolderUseCase.invoke() }
coVerify(exactly = 1) { arrangement.observeConversationsFromFolderUseCase.invoke(favoriteFolderId) }
coVerify(exactly = 0) { arrangement.useCase(any(), any(), any()) }
}

inner class Arrangement {

@MockK
lateinit var useCase: GetPaginatedFlowOfConversationDetailsWithEventsBySearchQueryUseCase

@MockK
lateinit var getFavoriteFolderUseCase: GetFavoriteFolderUseCase

@MockK
lateinit var observeConversationsFromFolderUseCase: ObserveConversationsFromFolderUseCase

@MockK
lateinit var wireSessionImageLoader: WireSessionImageLoader

Expand All @@ -110,6 +152,23 @@ class GetConversationsFromSearchUseCaseTest {
} returns flowOf(PagingData.from(conversations))
}

fun arrange() = this to GetConversationsFromSearchUseCase(useCase, wireSessionImageLoader, userTypeMapper, dispatcherProvider)
fun withFavoriteFolderResult(result: GetFavoriteFolderUseCase.Result) = apply {
coEvery { getFavoriteFolderUseCase.invoke() } returns result
}

fun withFolderConversationsResult(conversations: List<ConversationDetailsWithEvents>) = apply {
coEvery {
observeConversationsFromFolderUseCase.invoke(any())
} returns flowOf(conversations)
}

fun arrange() = this to GetConversationsFromSearchUseCase(
useCase,
getFavoriteFolderUseCase,
observeConversationsFromFolderUseCase,
wireSessionImageLoader,
userTypeMapper,
dispatcherProvider
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.wire.android.ui.home.conversations.usecase.GetConversationsFromSearch
import com.wire.android.ui.home.conversationslist.model.ConversationsSource
import com.wire.android.util.ui.WireSessionImageLoader
import com.wire.kalium.logic.data.conversation.ConversationDetailsWithEvents
import com.wire.kalium.logic.data.conversation.ConversationFilter
import com.wire.kalium.logic.data.conversation.MutedConversationStatus
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.user.UserId
Expand Down Expand Up @@ -216,7 +217,7 @@ class ConversationListViewModelTest {
} returns flowOf(
PagingData.from(listOf(TestConversationItem.CONNECTION, TestConversationItem.PRIVATE, TestConversationItem.GROUP))
)
coEvery { observeConversationListDetailsWithEventsUseCase.invoke(false) } returns flowOf(
coEvery { observeConversationListDetailsWithEventsUseCase.invoke(false, ConversationFilter.ALL) } returns flowOf(
listOf(
TestConversationDetails.CONNECTION,
TestConversationDetails.CONVERSATION_ONE_ONE,
Expand Down
2 changes: 1 addition & 1 deletion kalium
Submodule kalium updated 63 files
+1 βˆ’1 .github/workflows/gradle-jvm-tests.yml
+38 βˆ’0 data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationFolder.kt
+1 βˆ’1 logger/src/commonMain/kotlin/com/wire/kalium/logger/KaliumLogger.kt
+1 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationMapper.kt
+22 βˆ’9 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepository.kt
+8 βˆ’26 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryExtensions.kt
+65 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderMappers.kt
+100 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepository.kt
+12 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/event/Event.kt
+9 βˆ’3 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/event/EventMapper.kt
+16 βˆ’3 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/ProtoContentMapper.kt
+11 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/properties/UserPropertyRepository.kt
+1 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/sync/SlowSyncStatus.kt
+20 βˆ’3 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt
+12 βˆ’1 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/ConversationScope.kt
+22 βˆ’3 ...in/kotlin/com/wire/kalium/logic/feature/conversation/ObserveConversationListDetailsWithEventsUseCaseImpl.kt
+49 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/GetFavoriteFolderUseCase.kt
+39 βˆ’0 ...ommonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/ObserveConversationsFromFolderUseCase.kt
+36 βˆ’0 ...c/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/folder/SyncConversationFoldersUseCase.kt
+1 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/RetryFailedMessageUseCase.kt
+17 βˆ’1 logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/UserPropertiesEventReceiver.kt
+1 βˆ’1 logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/slow/SlowSyncManager.kt
+3 βˆ’0 logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/slow/SlowSyncWorker.kt
+1 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryExtensionsTest.kt
+4 βˆ’6 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepositoryTest.kt
+160 βˆ’0 ...c/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/folders/ConversationFolderRepositoryTest.kt
+71 βˆ’5 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/ProtoContentMapperTest.kt
+4 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/properties/UserPropertyRepositoryTest.kt
+4 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/PersistMigratedMessagesUseCaseTest.kt
+32 βˆ’0 logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/RetryFailedMessageUseCaseTest.kt
+16 βˆ’0 logic/src/commonTest/kotlin/com/wire/kalium/logic/framework/TestEvent.kt
+28 βˆ’1 logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/UserPropertiesEventReceiverTest.kt
+13 βˆ’0 logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/slow/SlowSyncWorkerTest.kt
+36 βˆ’10 network-model/src/commonMain/kotlin/com/wire/kalium/network/api/authenticated/notification/EventContentDTO.kt
+2 βˆ’2 ...rk-model/src/commonMain/kotlin/com/wire/kalium/network/api/authenticated/notification/EventSerialization.kt
+61 βˆ’0 network-model/src/commonMain/kotlin/com/wire/kalium/network/api/authenticated/properties/LabelDTO.kt
+2 βˆ’1 network-model/src/commonMain/kotlin/com/wire/kalium/network/api/authenticated/properties/PropertyKey.kt
+2 βˆ’0 network/src/commonMain/kotlin/com/wire/kalium/network/api/base/authenticated/properties/PropertiesApi.kt
+7 βˆ’1 network/src/commonMain/kotlin/com/wire/kalium/network/api/v0/authenticated/PropertiesApiV0.kt
+1 βˆ’0 persistence/src/commonMain/db_user/com/wire/kalium/persistence/Calls.sq
+10 βˆ’0 persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationDetails.sq
+26 βˆ’25 persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationDetailsWithEvents.sq
+48 βˆ’0 persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationFolders.sq
+111 βˆ’0 persistence/src/commonMain/db_user/com/wire/kalium/persistence/LastMessage.sq
+2 βˆ’2 persistence/src/commonMain/db_user/com/wire/kalium/persistence/MessageDrafts.sq
+5 βˆ’8 persistence/src/commonMain/db_user/com/wire/kalium/persistence/Messages.sq
+3 βˆ’0 persistence/src/commonMain/db_user/com/wire/kalium/persistence/UnreadEvents.sq
+208 βˆ’0 persistence/src/commonMain/db_user/migrations/90.sqm
+19 βˆ’0 persistence/src/commonMain/db_user/migrations/91.sqm
+1 βˆ’1 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/ConversationDAO.kt
+5 βˆ’2 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/ConversationDAOImpl.kt
+27 βˆ’0 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAO.kt
+73 βˆ’0 ...ence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOImpl.kt
+38 βˆ’0 ...tence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderEntity.kt
+16 βˆ’0 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/TableMapper.kt
+12 βˆ’1 persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt
+0 βˆ’2 persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/ConnectionDaoTest.kt
+20 βˆ’14 persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/ConversationDAOTest.kt
+102 βˆ’0 ...ence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOTest.kt
+153 βˆ’9 persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOTest.kt
+109 βˆ’1 persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/draft/MessageDraftDAOTest.kt
+7 βˆ’0 protobuf-codegen/src/main/proto/messages.proto
+2 βˆ’2 testservice/Jenkinsfile

0 comments on commit 91578c9

Please sign in to comment.