diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt index 28ad0d2..0d285fb 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt @@ -19,9 +19,16 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.arkivanov.decompose.extensions.compose.subscribeAsState import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import com.maxkeppeler.sheets.option.OptionDialog +import com.maxkeppeler.sheets.option.models.DisplayMode +import com.maxkeppeler.sheets.option.models.Option +import com.maxkeppeler.sheets.option.models.OptionConfig +import com.maxkeppeler.sheets.option.models.OptionDetails +import com.maxkeppeler.sheets.option.models.OptionSelection import dev.chrisbanes.haze.haze import dev.datlag.aniflow.LocalHaze import dev.datlag.aniflow.LocalPaddingValues +import dev.datlag.aniflow.SharedRes import dev.datlag.aniflow.common.asMedium import dev.datlag.aniflow.common.isScrollingUp import dev.datlag.aniflow.common.plus @@ -29,12 +36,13 @@ import dev.datlag.aniflow.common.preferred import dev.datlag.aniflow.other.StateSaver import dev.datlag.aniflow.other.rememberImagePickerState import dev.datlag.aniflow.trace.TraceStateMachine +import dev.datlag.aniflow.trace.model.SearchResponse import dev.datlag.aniflow.ui.navigation.screen.initial.home.component.AiringOverview import dev.datlag.aniflow.ui.navigation.screen.initial.home.component.PopularSeasonOverview import dev.datlag.aniflow.ui.navigation.screen.initial.home.component.TrendingOverview import dev.datlag.aniflow.ui.navigation.screen.initial.model.FABConfig import dev.datlag.tooling.decompose.lifecycle.collectAsStateWithLifecycle -import io.github.aakira.napier.Napier +import dev.icerock.moko.resources.compose.stringResource @Composable fun HomeScreen(component: HomeComponent) { @@ -66,27 +74,41 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) { when (val current = traceState) { is TraceStateMachine.State.Success -> { - val results = remember(traceState) { current.response.result.sortedByDescending { it.similarity } } - - LaunchedEffect(current) { - results.maxByOrNull { it.similarity }?.aniList?.asMedium()?.let(component::details) + val results = remember(traceState) { + current.response.combinedResults.sortedWith( + compareByDescending { + it.maxSimilarity + }.thenByDescending { + it.avgSimilarity + } + ) } - /*OptionDialog( - state = rememberUseCaseState(visible = true), - config = OptionConfig(mode = DisplayMode.LIST), + val useCase = rememberUseCaseState(visible = results.isNotEmpty()) + + OptionDialog( + state = useCase, selection = OptionSelection.Single( - options = results.mapIndexedNotNull { index, result -> - result.aniList.title?.preferred()?.let { title -> - Option( - titleText = title, - selected = index == 0 + options = results.map { + Option( + titleText = it.aniList.asMedium().title.preferred(), + details = OptionDetails( + title = stringResource(SharedRes.strings.similarity_title), + body = if (it.isSingle) { + stringResource(SharedRes.strings.similarity_text_single, it.avgPercentage) + } else { + stringResource(SharedRes.strings.similarity_text_max_avg, it.maxPercentage, it.avgPercentage) + } ) - } + ) + }, + onSelectOption = { index, _ -> + component.details(results[index].aniList.asMedium()) } - ) { index, _ -> - results.getOrNull(index)?.aniList?.asMedium()?.let(component::details) - } - )*/ + ), + config = OptionConfig( + mode = DisplayMode.LIST + ) + ) } else -> { } } diff --git a/composeApp/src/commonMain/moko-resources/base/strings.xml b/composeApp/src/commonMain/moko-resources/base/strings.xml index 7554b7c..24c1117 100644 --- a/composeApp/src/commonMain/moko-resources/base/strings.xml +++ b/composeApp/src/commonMain/moko-resources/base/strings.xml @@ -45,4 +45,7 @@ Green Gray Custom + Similarity + Maximum: %s\nAverage: %s + Average: %s diff --git a/trace/src/commonMain/kotlin/dev/datlag/aniflow/trace/model/SearchResponse.kt b/trace/src/commonMain/kotlin/dev/datlag/aniflow/trace/model/SearchResponse.kt index fd229f9..6d73ec2 100644 --- a/trace/src/commonMain/kotlin/dev/datlag/aniflow/trace/model/SearchResponse.kt +++ b/trace/src/commonMain/kotlin/dev/datlag/aniflow/trace/model/SearchResponse.kt @@ -12,7 +12,18 @@ data class SearchResponse( val isError = !error.isNullOrBlank() @Transient - val bestResult: Result? = result.maxByOrNull { it.similarity } + val combinedResults: Set = result.groupBy { it.aniList.id }.mapValues { entry -> + CombinedResult( + aniList = Result.AniList( + id = entry.key, + idMal = entry.value.firstNotNullOfOrNull { it.aniList.idMal }, + isAdult = entry.value.any { it.aniList.isAdult }, + title = entry.value.firstNotNullOfOrNull { it.aniList.title } + ), + maxSimilarity = entry.value.maxOf { it.similarity }, + avgSimilarity = entry.value.map { it.similarity }.average().toFloat() + ) + }.values.toSet() @Serializable data class Result( @@ -36,4 +47,14 @@ data class SearchResponse( ) } } + + data class CombinedResult( + val aniList: Result.AniList, + val maxSimilarity: Float, + val avgSimilarity: Float = maxSimilarity, + ) { + val isSingle: Boolean = maxSimilarity == avgSimilarity + val maxPercentage: String = "${(maxSimilarity * 100F).toInt()}%" + val avgPercentage: String = "${(avgSimilarity * 100F).toInt()}%" + } }