Skip to content

Commit f657fb7

Browse files
mdrlzykirillt
authored andcommitted
Extract SearchUseCase, improve search
1 parent 5626867 commit f657fb7

File tree

10 files changed

+108
-79
lines changed

10 files changed

+108
-79
lines changed

core/di/src/main/java/dev/arkbuilders/rate/core/di/CoreComponent.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import dev.arkbuilders.rate.core.domain.usecase.CalcFrequentCurrUseCase
1919
import dev.arkbuilders.rate.core.domain.usecase.ConvertWithRateUseCase
2020
import dev.arkbuilders.rate.core.domain.usecase.DefaultGroupNameProvider
2121
import dev.arkbuilders.rate.core.domain.usecase.GetGroupByIdOrCreateDefaultUseCase
22-
import dev.arkbuilders.rate.core.domain.usecase.GetTopResultUseCase
2322
import dev.arkbuilders.rate.core.domain.usecase.GroupReorderSwapUseCase
23+
import dev.arkbuilders.rate.core.domain.usecase.SearchUseCase
2424
import dev.arkbuilders.rate.core.domain.usecase.ValidateGroupNameUseCase
2525
import javax.inject.Singleton
2626

@@ -57,7 +57,7 @@ interface CoreComponent {
5757

5858
fun calcFrequentCurrUseCase(): CalcFrequentCurrUseCase
5959

60-
fun getTopResultUseCase(): GetTopResultUseCase
60+
fun searchUseCase(): SearchUseCase
6161

6262
fun validateGroupNameUseCase(): ValidateGroupNameUseCase
6363

core/di/src/main/java/dev/arkbuilders/rate/core/di/modules/UseCaseModule.kt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ package dev.arkbuilders.rate.core.di.modules
22

33
import dagger.Module
44
import dagger.Provides
5+
import dev.arkbuilders.rate.core.domain.BuildConfigFieldsProvider
56
import dev.arkbuilders.rate.core.domain.repo.CodeUseStatRepo
67
import dev.arkbuilders.rate.core.domain.repo.CurrencyRepo
78
import dev.arkbuilders.rate.core.domain.repo.GroupRepo
89
import dev.arkbuilders.rate.core.domain.usecase.CalcFrequentCurrUseCase
910
import dev.arkbuilders.rate.core.domain.usecase.ConvertWithRateUseCase
1011
import dev.arkbuilders.rate.core.domain.usecase.DefaultGroupNameProvider
1112
import dev.arkbuilders.rate.core.domain.usecase.GetGroupByIdOrCreateDefaultUseCase
12-
import dev.arkbuilders.rate.core.domain.usecase.GetTopResultUseCase
1313
import dev.arkbuilders.rate.core.domain.usecase.GroupReorderSwapUseCase
14+
import dev.arkbuilders.rate.core.domain.usecase.SearchUseCase
1415
import dev.arkbuilders.rate.core.domain.usecase.ValidateGroupNameUseCase
1516
import javax.inject.Singleton
1617

@@ -25,13 +26,6 @@ class UseCaseModule {
2526
@Provides
2627
fun convertWithRateUseCase(currencyRepo: CurrencyRepo) = ConvertWithRateUseCase(currencyRepo)
2728

28-
@Singleton
29-
@Provides
30-
fun getTopResultUseCase(
31-
currencyRepo: CurrencyRepo,
32-
calcFrequentCurrUseCase: CalcFrequentCurrUseCase,
33-
) = GetTopResultUseCase(currencyRepo, calcFrequentCurrUseCase)
34-
3529
@Singleton
3630
@Provides
3731
fun prepopulateDefaultGroupUseCase(
@@ -46,4 +40,9 @@ class UseCaseModule {
4640
@Singleton
4741
@Provides
4842
fun validateGroupNameUseCase() = ValidateGroupNameUseCase()
43+
44+
@Singleton
45+
@Provides
46+
fun searchUseCase(buildConfigFieldsProvider: BuildConfigFieldsProvider) =
47+
SearchUseCase(buildConfigFieldsProvider.provide())
4948
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package dev.arkbuilders.rate.core.domain.usecase
2+
3+
import dev.arkbuilders.rate.core.domain.BuildConfigFields
4+
import dev.arkbuilders.rate.core.domain.model.CurrencyCode
5+
import dev.arkbuilders.rate.core.domain.model.CurrencyName
6+
7+
class SearchUseCase(
8+
private val buildConfigFields: BuildConfigFields,
9+
) {
10+
operator fun invoke(
11+
all: List<CurrencyName>,
12+
frequent: List<CurrencyCode>,
13+
query: String,
14+
): List<CurrencyName> {
15+
val filtered =
16+
all
17+
.filter {
18+
it.name.contains(query, ignoreCase = true) ||
19+
it.code.contains(query, ignoreCase = true)
20+
}.sortedBy { it.code }
21+
22+
val prefix =
23+
filtered.filter { it.code.startsWith(query, ignoreCase = true) }
24+
val frequent = filtered.filter { it.code in frequent }
25+
val icons = filtered.filter { it.code in buildConfigFields.availableIconCodes }
26+
27+
val result = prefix + frequent + icons + filtered
28+
return result.distinct()
29+
}
30+
}

feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickScreen.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,7 @@ private fun Content(
277277
}
278278
if (state.filter.isNotEmpty()) {
279279
QuickSearchPage(
280-
filter = state.filter,
281-
topResults = state.topResults,
280+
topResultsFiltered = state.topResultsFiltered,
282281
onNewCode = onNewCode,
283282
)
284283
} else {

feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickSearchPage.kt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,15 @@ import dev.arkbuilders.rate.core.presentation.ui.NoResult
1515

1616
@Composable
1717
fun QuickSearchPage(
18-
filter: String,
19-
topResults: List<CurrencyName>,
18+
topResultsFiltered: List<CurrencyName>,
2019
onNewCode: (CurrencyCode) -> Unit,
2120
) {
22-
val filtered =
23-
topResults.filter {
24-
it.name.contains(filter, ignoreCase = true) ||
25-
it.code.contains(filter, ignoreCase = true)
26-
}
27-
if (filtered.isNotEmpty()) {
21+
if (topResultsFiltered.isNotEmpty()) {
2822
LazyColumn(modifier = Modifier.fillMaxSize()) {
2923
item {
3024
ListHeader(text = stringResource(CoreRString.top_results))
3125
}
32-
items(filtered) { name ->
26+
items(topResultsFiltered) { name ->
3327
CurrencyInfoItem(name) { onNewCode(it.code) }
3428
}
3529
}

feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickViewModel.kt

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import dev.arkbuilders.rate.core.domain.repo.Prefs
1717
import dev.arkbuilders.rate.core.domain.repo.TimestampRepo
1818
import dev.arkbuilders.rate.core.domain.usecase.CalcFrequentCurrUseCase
1919
import dev.arkbuilders.rate.core.domain.usecase.ConvertWithRateUseCase
20-
import dev.arkbuilders.rate.core.domain.usecase.GetTopResultUseCase
2120
import dev.arkbuilders.rate.core.domain.usecase.GroupReorderSwapUseCase
21+
import dev.arkbuilders.rate.core.domain.usecase.SearchUseCase
2222
import dev.arkbuilders.rate.core.presentation.ui.group.EditGroupOptionsSheetState
2323
import dev.arkbuilders.rate.core.presentation.ui.group.EditGroupRenameSheetState
2424
import dev.arkbuilders.rate.core.presentation.ui.group.EditGroupReorderSheetState
@@ -45,7 +45,7 @@ data class QuickScreenState(
4545
val filter: String = "",
4646
val currencies: List<CurrencyName> = emptyList(),
4747
val frequent: List<CurrencyName> = emptyList(),
48-
val topResults: List<CurrencyName> = emptyList(),
48+
val topResultsFiltered: List<CurrencyName> = emptyList(),
4949
val pages: List<QuickScreenPage> = emptyList(),
5050
val pairOptionsData: PairOptionsData? = null,
5151
val editGroupReorderSheetState: EditGroupReorderSheetState? = null,
@@ -76,7 +76,7 @@ class QuickViewModel(
7676
private val convertUseCase: ConvertWithRateUseCase,
7777
private val calcFrequentCurrUseCase: CalcFrequentCurrUseCase,
7878
private val groupReorderSwapUseCase: GroupReorderSwapUseCase,
79-
private val getTopResultUseCase: GetTopResultUseCase,
79+
private val searchUseCase: SearchUseCase,
8080
private val analyticsManager: AnalyticsManager,
8181
private val prefs: Prefs,
8282
) : ViewModel(), ContainerHost<QuickScreenState, QuickScreenEffect> {
@@ -118,25 +118,21 @@ class QuickViewModel(
118118
val frequent =
119119
calcFrequentCurrUseCase.invoke()
120120
.map { currencyRepo.nameByCode(it) }
121-
val topResults = getTopResultUseCase()
122121
reduce {
123122
state.copy(
124123
frequent = frequent,
125-
topResults = topResults,
126124
)
127125
}
128126
}.launchIn(viewModelScope)
129127

130128
val frequent =
131129
calcFrequentCurrUseCase()
132130
.map { currencyRepo.nameByCode(it) }
133-
val topResults = getTopResultUseCase()
134131
val pages = mapPairsToPages(quickRepo.getAll())
135132
reduce {
136133
state.copy(
137134
currencies = allCurrencies,
138135
frequent = frequent,
139-
topResults = topResults,
140136
pages = pages,
141137
initialized = true,
142138
)
@@ -195,7 +191,17 @@ class QuickViewModel(
195191

196192
fun onFilterChanged(filter: String) =
197193
blockingIntent {
198-
reduce { state.copy(filter = filter) }
194+
reduce {
195+
state.copy(
196+
filter = filter,
197+
topResultsFiltered =
198+
searchUseCase(
199+
state.currencies,
200+
state.frequent.map { it.code },
201+
filter,
202+
),
203+
)
204+
}
199205
}
200206

201207
fun onDelete(pair: QuickPair) =
@@ -357,7 +363,7 @@ class QuickViewModelFactory @AssistedInject constructor(
357363
private val convertUseCase: ConvertWithRateUseCase,
358364
private val calcFrequentCurrUseCase: CalcFrequentCurrUseCase,
359365
private val groupReorderSwapUseCase: GroupReorderSwapUseCase,
360-
private val getTopResultUseCase: GetTopResultUseCase,
366+
private val searchUseCase: SearchUseCase,
361367
private val analyticsManager: AnalyticsManager,
362368
private val prefs: Prefs,
363369
) : ViewModelProvider.Factory {
@@ -370,7 +376,7 @@ class QuickViewModelFactory @AssistedInject constructor(
370376
convertUseCase,
371377
calcFrequentCurrUseCase,
372378
groupReorderSwapUseCase,
373-
getTopResultUseCase,
379+
searchUseCase,
374380
analyticsManager,
375381
prefs,
376382
) as T

feature/search/src/main/java/dev/arkbuilders/rate/feature/search/di/SearchComponent.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package dev.arkbuilders.rate.feature.search.di
33
import dagger.Component
44
import dev.arkbuilders.rate.core.di.CoreComponent
55
import dev.arkbuilders.rate.core.domain.repo.AnalyticsManager
6-
import dev.arkbuilders.rate.core.domain.usecase.GetTopResultUseCase
6+
import dev.arkbuilders.rate.core.domain.usecase.SearchUseCase
77
import dev.arkbuilders.rate.feature.search.presentation.SearchViewModelFactory
88

99
@SearchScope
1010
@Component(dependencies = [CoreComponent::class])
1111
interface SearchComponent {
12-
fun getTopResultUseCase(): GetTopResultUseCase
12+
fun searchUseCase(): SearchUseCase
1313

1414
fun analyticsManager(): AnalyticsManager
1515

feature/search/src/main/java/dev/arkbuilders/rate/feature/search/presentation/SearchCurrencyInfoItem.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ import androidx.compose.ui.Modifier
1515
import androidx.compose.ui.draw.alpha
1616
import androidx.compose.ui.text.font.FontWeight
1717
import androidx.compose.ui.unit.dp
18+
import dev.arkbuilders.rate.core.domain.model.CurrencyName
1819
import dev.arkbuilders.rate.core.presentation.theme.ArkColor
1920
import dev.arkbuilders.rate.core.presentation.ui.CurrIcon
2021

2122
@Composable
2223
fun SearchCurrencyInfoItem(
23-
model: CurrencySearchModel,
24-
onClick: (CurrencySearchModel) -> Unit,
24+
model: CurrencyName,
25+
isProhibited: Boolean,
26+
onClick: (CurrencyName) -> Unit,
2527
) {
26-
val contentAlpha = if (model.isProhibited) 0.4f else 1f
28+
val contentAlpha = if (isProhibited) 0.4f else 1f
2729
Column {
2830
Row(
2931
modifier =

feature/search/src/main/java/dev/arkbuilders/rate/feature/search/presentation/SearchCurrencyScreen.kt

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.ramcosta.composedestinations.annotation.Destination
2121
import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
2222
import com.ramcosta.composedestinations.result.ResultBackNavigator
2323
import dev.arkbuilders.rate.core.domain.model.CurrencyCode
24+
import dev.arkbuilders.rate.core.domain.model.CurrencyName
2425
import dev.arkbuilders.rate.core.presentation.CoreRString
2526
import dev.arkbuilders.rate.core.presentation.ui.AppHorDiv
2627
import dev.arkbuilders.rate.core.presentation.ui.AppTopBarBack
@@ -83,6 +84,7 @@ fun SearchCurrencyScreen(
8384
Input(state.filter, viewModel::onInputChange)
8485
Results(
8586
filter = state.filter,
87+
prohibitedCodes = state.prohibitedCodes,
8688
frequent = state.frequent,
8789
all = state.all,
8890
topResultsFiltered = state.topResultsFiltered,
@@ -114,18 +116,22 @@ private fun Input(
114116
@Composable
115117
private fun Results(
116118
filter: String,
117-
frequent: List<CurrencySearchModel>,
118-
all: List<CurrencySearchModel>,
119-
topResultsFiltered: List<CurrencySearchModel>,
120-
onClick: (CurrencySearchModel) -> Unit,
119+
prohibitedCodes: List<CurrencyCode>,
120+
frequent: List<CurrencyName>,
121+
all: List<CurrencyName>,
122+
topResultsFiltered: List<CurrencyName>,
123+
onClick: (CurrencyName) -> Unit,
121124
) {
122125
when {
123126
filter.isNotEmpty() -> {
124127
if (topResultsFiltered.isNotEmpty()) {
125128
LazyColumn {
126129
item { ListHeader(stringResource(CoreRString.top_results)) }
127130
items(topResultsFiltered) { model ->
128-
SearchCurrencyInfoItem(model) { onClick(it) }
131+
SearchCurrencyInfoItem(
132+
model,
133+
model.code in prohibitedCodes,
134+
) { onClick(it) }
129135
}
130136
}
131137
} else {
@@ -138,12 +144,18 @@ private fun Results(
138144
if (frequent.isNotEmpty()) {
139145
item { ListHeader(stringResource(CoreRString.frequent_currencies)) }
140146
items(frequent) { model ->
141-
SearchCurrencyInfoItem(model) { onClick(it) }
147+
SearchCurrencyInfoItem(
148+
model,
149+
model.code in prohibitedCodes,
150+
) { onClick(it) }
142151
}
143152
}
144153
item { ListHeader(stringResource(CoreRString.all_currencies)) }
145154
items(all) { model ->
146-
SearchCurrencyInfoItem(model) { onClick(it) }
155+
SearchCurrencyInfoItem(
156+
model,
157+
model.code in prohibitedCodes,
158+
) { onClick(it) }
147159
}
148160
}
149161
}

0 commit comments

Comments
 (0)