diff --git a/app/src/main/java/dev/arkbuilders/rate/presentation/MainScreen.kt b/app/src/main/java/dev/arkbuilders/rate/presentation/MainScreen.kt index cbde7fe92..cb5b789e8 100644 --- a/app/src/main/java/dev/arkbuilders/rate/presentation/MainScreen.kt +++ b/app/src/main/java/dev/arkbuilders/rate/presentation/MainScreen.kt @@ -32,6 +32,7 @@ import dev.arkbuilders.rate.core.presentation.utils.findActivity import dev.arkbuilders.rate.core.presentation.utils.keyboardAsState import dev.arkbuilders.rate.feature.pairalert.presentation.destinations.PairAlertConditionScreenDestination import dev.arkbuilders.rate.feature.portfolio.presentation.destinations.PortfolioScreenDestination +import dev.arkbuilders.rate.feature.quick.presentation.add.AddQuickScreenArgs import dev.arkbuilders.rate.feature.quick.presentation.destinations.AddQuickScreenDestination import dev.arkbuilders.rate.feature.quick.presentation.destinations.QuickScreenDestination import dev.arkbuilders.rate.feature.quickwidget.presentation.action.AddNewPairAction.Companion.ADD_NEW_PAIR @@ -40,7 +41,6 @@ import dev.arkbuilders.rate.feature.settings.presentation.destinations.SettingsS import dev.arkbuilders.rate.presentation.navigation.AnimatedRateBottomNavigation import dev.arkbuilders.rate.presentation.navigation.NavGraphs import kotlinx.coroutines.flow.drop -import timber.log.Timber @Composable fun MainScreen() { @@ -58,7 +58,7 @@ fun MainScreen() { val createNewPair = intent?.getStringExtra(ADD_NEW_PAIR) ?: "" if (createNewPair.isNotEmpty()) { val group = intent?.getStringExtra(ADD_NEW_PAIR_GROUP_KEY) - navController.navigate(AddQuickScreenDestination(group = group)) + navController.navigate(AddQuickScreenDestination(AddQuickScreenArgs(group = group))) intent?.removeExtra(ADD_NEW_PAIR_GROUP_KEY) intent?.removeExtra(ADD_NEW_PAIR) } @@ -82,7 +82,6 @@ fun MainScreen() { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route ?: NavGraphs.root.startRoute.route - Timber.d("ALLO $currentRoute") bottomBarVisible.value = when { currentRoute.startsWith(QuickScreenDestination.route) -> true diff --git a/build.gradle.kts b/build.gradle.kts index dfe74c414..0af1e123e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,6 +4,7 @@ plugins { alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.ksp) + alias(libs.plugins.kotlin.parcelize) apply false id("com.google.gms.google-services") version "4.4.2" apply false id("com.google.firebase.crashlytics") version "3.0.1" apply false id("org.jlleitschuh.gradle.ktlint") version "12.1.1" diff --git a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/AppSharedFlow.kt b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/AppSharedFlow.kt index 112de10ef..e2ead81bb 100644 --- a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/AppSharedFlow.kt +++ b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/AppSharedFlow.kt @@ -30,6 +30,12 @@ sealed class AppSharedFlow(val flow: MutableSharedFlow) { data object ShowAddedSnackbarPairAlert : AppSharedFlow(MutableSharedFlow()) + + data object SelectGroupQuick : AppSharedFlow(MutableSharedFlow()) + + data object SelectGroupPortfolio : AppSharedFlow(MutableSharedFlow()) + + data object SelectGroupPairAlert : AppSharedFlow(MutableSharedFlow()) } enum class AppSharedFlowKey { diff --git a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/ui/GroupViewPager.kt b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/ui/GroupViewPager.kt index fa8699d0d..6fc1d9206 100644 --- a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/ui/GroupViewPager.kt +++ b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/ui/GroupViewPager.kt @@ -8,7 +8,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.pager.PagerState import androidx.compose.material3.ScrollableTabRow import androidx.compose.material3.Tab import androidx.compose.material3.TabRowDefaults @@ -29,11 +29,11 @@ import kotlinx.coroutines.launch @Composable fun GroupViewPager( modifier: Modifier = Modifier, + pagerState: PagerState, groups: List, pageContent: @Composable (index: Int) -> Unit, ) { val scope = rememberCoroutineScope() - val pagerState = rememberPagerState { groups.size } Column(modifier = modifier) { Box { AppHorDiv(modifier = Modifier.align(Alignment.BottomCenter)) diff --git a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/ui/RatePagerState.kt b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/ui/RatePagerState.kt new file mode 100644 index 000000000..a051ac8a3 --- /dev/null +++ b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/ui/RatePagerState.kt @@ -0,0 +1,16 @@ +package dev.arkbuilders.rate.core.presentation.ui + +import androidx.compose.foundation.pager.PagerState + +/** See: + * rememberPagerState() + * androidx.compose.foundation.pager.DefaultPagerState + */ + +class RatePagerState( + currentPage: Int = 0, + currentPageOffsetFraction: Float = 0f, + private val updatedPageCount: () -> Int, +) : PagerState(currentPage, currentPageOffsetFraction) { + override val pageCount: Int get() = updatedPageCount() +} diff --git a/feature/pairalert/build.gradle.kts b/feature/pairalert/build.gradle.kts index c1fcffcc8..39cf05ead 100644 --- a/feature/pairalert/build.gradle.kts +++ b/feature/pairalert/build.gradle.kts @@ -2,6 +2,7 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) alias(libs.plugins.ksp) + alias(libs.plugins.kotlin.parcelize) } android { diff --git a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertScreen.kt b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertScreen.kt index 719227c14..49f3ffb80 100644 --- a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertScreen.kt +++ b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertScreen.kt @@ -2,6 +2,7 @@ package dev.arkbuilders.rate.feature.pairalert.presentation.add +import android.os.Parcelable import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -61,14 +62,21 @@ import dev.arkbuilders.rate.core.presentation.ui.GroupSelectPopup import dev.arkbuilders.rate.core.presentation.ui.NotifyAddedSnackbarVisuals import dev.arkbuilders.rate.feature.pairalert.di.PairAlertComponentHolder import dev.arkbuilders.rate.feature.search.presentation.destinations.SearchCurrencyScreenDestination +import kotlinx.parcelize.Parcelize import org.orbitmvi.orbit.compose.collectAsState import org.orbitmvi.orbit.compose.collectSideEffect import dev.arkbuilders.rate.core.presentation.R as CoreR +@Parcelize +data class AddPairAlertScreenArgs( + val pairAlertId: Long? = null, + val group: String?, +) : Parcelable + @Destination @Composable fun AddPairAlertScreen( - pairAlertId: Long? = null, + args: AddPairAlertScreenArgs, navigator: DestinationsNavigator, ) { val ctx = LocalContext.current @@ -78,7 +86,7 @@ fun AddPairAlertScreen( } val viewModel: AddPairAlertViewModel = viewModel( - factory = component.addPairAlertVMFactory().create(pairAlertId), + factory = component.addPairAlertVMFactory().create(args), ) val state by viewModel.collectAsState() diff --git a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertViewModel.kt b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertViewModel.kt index 1801f9c4c..8c79a95fe 100644 --- a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertViewModel.kt +++ b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/add/AddPairAlertViewModel.kt @@ -50,7 +50,7 @@ sealed class AddPairAlertScreenEffect { } class AddPairAlertViewModel( - private val pairAlertId: Long?, + private val args: AddPairAlertScreenArgs, private val currencyRepo: CurrencyRepo, private val pairAlertRepo: PairAlertRepo, private val codeUseStatRepo: CodeUseStatRepo, @@ -71,12 +71,12 @@ class AddPairAlertViewModel( initOnCodeChange(newBase = it) }.launchIn(viewModelScope) - pairAlertId?.let { + args.pairAlertId?.let { setupFromExisting() intent { checkAboveNotBelow() } - } ?: initOnCodeChange() + } ?: initOnCodeChange(firstInit = true) intent { val groups = @@ -90,6 +90,7 @@ class AddPairAlertViewModel( private fun initOnCodeChange( newTarget: CurrencyCode? = null, newBase: CurrencyCode? = null, + firstInit: Boolean = false, ) { intent { val target = newTarget ?: state.targetCode @@ -104,6 +105,7 @@ class AddPairAlertViewModel( currentPrice = currentPrice, targetCode = target, baseCode = base, + group = if (firstInit) args.group else state.group, ) val priceOrPercent = calcNewPriceOrPercent(newState) @@ -191,7 +193,7 @@ class AddPairAlertViewModel( val percent = state.priceOrPercent.getOrNull()?.toDoubleArk() - val id = if (state.editExisting) pairAlertId!! else 0 + val id = if (state.editExisting) args.pairAlertId!! else 0 val pairAlert = PairAlert( @@ -208,6 +210,7 @@ class AddPairAlertViewModel( ) pairAlertRepo.insert(pairAlert) codeUseStatRepo.codesUsed(pairAlert.baseCode, pairAlert.targetCode) + AppSharedFlow.SelectGroupPairAlert.flow.emit(state.group) postSideEffect(AddPairAlertScreenEffect.NotifyPairAdded(pairAlert)) postSideEffect(AddPairAlertScreenEffect.NavigateBack) } @@ -296,7 +299,7 @@ class AddPairAlertViewModel( private fun setupFromExisting() = intent { - val pair = pairAlertRepo.getById(pairAlertId!!)!! + val pair = pairAlertRepo.getById(args.pairAlertId!!)!! val priceOrPercent = pair.percent?.let { percent -> @@ -314,8 +317,8 @@ class AddPairAlertViewModel( fromCode = pair.targetCode, toCode = pair.baseCode, ) - val state = - AddPairAlertScreenState( + reduce { + state.copy( targetCode = pair.targetCode, baseCode = pair.baseCode, priceOrPercent = priceOrPercent, @@ -325,7 +328,7 @@ class AddPairAlertViewModel( oneTimeNotRecurrent = pair.oneTimeNotRecurrent, editExisting = true, ) - reduce { state } + } } private fun checkFinishEnabled() = @@ -353,7 +356,7 @@ class AddPairAlertViewModel( } class AddPairAlertViewModelFactory @AssistedInject constructor( - @Assisted private val pairAlertId: Long?, + @Assisted private val args: AddPairAlertScreenArgs, private val currencyRepo: CurrencyRepo, private val pairAlertRepo: PairAlertRepo, private val codeUseStatRepo: CodeUseStatRepo, @@ -362,7 +365,7 @@ class AddPairAlertViewModelFactory @AssistedInject constructor( ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return AddPairAlertViewModel( - pairAlertId, + args, currencyRepo, pairAlertRepo, codeUseStatRepo, @@ -373,6 +376,6 @@ class AddPairAlertViewModelFactory @AssistedInject constructor( @AssistedFactory interface Factory { - fun create(pairAlertId: Long?): AddPairAlertViewModelFactory + fun create(args: AddPairAlertScreenArgs): AddPairAlertViewModelFactory } } diff --git a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertConditionScreen.kt b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertConditionScreen.kt index 633e93bb2..5a99574a1 100644 --- a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertConditionScreen.kt +++ b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertConditionScreen.kt @@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -100,11 +101,7 @@ fun PairAlertConditionScreen(navigator: DestinationsNavigator) { viewModel.collectSideEffect { effect -> when (effect) { is PairAlertEffect.NavigateToAdd -> - navigator.navigate( - AddPairAlertScreenDestination( - pairAlertId = effect.pairId, - ), - ) + navigator.navigate(AddPairAlertScreenDestination(effect.args)) PairAlertEffect.AskNotificationPermissionOnScreenOpen -> { onScreenOpenNotificationPermissionLauncher @@ -139,6 +136,8 @@ fun PairAlertConditionScreen(navigator: DestinationsNavigator) { ) snackState.showSnackbar(visuals) } + + is PairAlertEffect.SelectGroup -> viewModel.pagerState.scrollToPage(effect.groupIndex) } } @@ -176,6 +175,7 @@ fun PairAlertConditionScreen(navigator: DestinationsNavigator) { Content( component = component, state = state, + pagerState = viewModel.pagerState, onDelete = viewModel::onDelete, onClick = { pair -> viewModel.onNewPair(pair.id) @@ -191,6 +191,7 @@ fun PairAlertConditionScreen(navigator: DestinationsNavigator) { private fun Content( component: PairAlertComponent, state: PairAlertScreenState, + pagerState: PagerState, onDelete: (PairAlert) -> Unit, onClick: (PairAlert) -> Unit, onEnableToggle: (PairAlert, Boolean) -> Unit, @@ -207,6 +208,7 @@ private fun Content( } else { GroupViewPager( modifier = Modifier.padding(top = 16.dp), + pagerState = pagerState, groups = state.pages.map { it.group }, ) { index -> GroupPage( diff --git a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertViewModel.kt b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertViewModel.kt index ebf93c3cd..9127eefe0 100644 --- a/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertViewModel.kt +++ b/feature/pairalert/src/main/java/dev/arkbuilders/rate/feature/pairalert/presentation/main/PairAlertViewModel.kt @@ -7,10 +7,12 @@ import dev.arkbuilders.rate.core.domain.repo.AnalyticsManager import dev.arkbuilders.rate.core.domain.repo.CurrencyRepo import dev.arkbuilders.rate.core.presentation.AppSharedFlow import dev.arkbuilders.rate.core.presentation.ui.NotifyAddedSnackbarVisuals +import dev.arkbuilders.rate.core.presentation.ui.RatePagerState import dev.arkbuilders.rate.feature.pairalert.data.permission.NotificationPermissionHelper import dev.arkbuilders.rate.feature.pairalert.di.PairAlertScope import dev.arkbuilders.rate.feature.pairalert.domain.model.PairAlert import dev.arkbuilders.rate.feature.pairalert.domain.repo.PairAlertRepo +import dev.arkbuilders.rate.feature.pairalert.presentation.add.AddPairAlertScreenArgs import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.orbitmvi.orbit.Container @@ -32,10 +34,12 @@ data class PairAlertScreenState( val initialized: Boolean = false, val noInternet: Boolean = false, val askNotificationPermissionPairId: Long? = null, -) +) { + fun currentGroup(index: Int) = pages.getOrNull(index)?.group +} sealed class PairAlertEffect { - data class NavigateToAdd(val pairId: Long? = null) : PairAlertEffect() + data class NavigateToAdd(val args: AddPairAlertScreenArgs) : PairAlertEffect() data object AskNotificationPermissionOnScreenOpen : PairAlertEffect() @@ -46,6 +50,8 @@ sealed class PairAlertEffect { ) : PairAlertEffect() data class ShowRemovedSnackbar(val pair: PairAlert) : PairAlertEffect() + + data class SelectGroup(val groupIndex: Int) : PairAlertEffect() } class PairAlertViewModel( @@ -59,6 +65,8 @@ class PairAlertViewModel( PairAlertScreenState(), ) + val pagerState = RatePagerState(updatedPageCount = { container.stateFlow.value.pages.size }) + init { analyticsManager.trackScreen("PairAlertScreen") @@ -82,13 +90,24 @@ class PairAlertViewModel( } } - private fun init() = - intent { - AppSharedFlow.ShowAddedSnackbarQuick.flow.onEach { visuals -> + private fun init() { + AppSharedFlow.SelectGroupPairAlert.flow.onEach { group -> + intent { + val page = state.pages.find { it.group == group } + val index = page?.let { state.pages.indexOf(it) } + if (index != null && index != -1) + postSideEffect(PairAlertEffect.SelectGroup(index)) + } + }.launchIn(viewModelScope) + + AppSharedFlow.ShowAddedSnackbarQuick.flow.onEach { visuals -> + intent { postSideEffect(PairAlertEffect.ShowSnackbarAdded(visuals)) - }.launchIn(viewModelScope) + } + }.launchIn(viewModelScope) - pairAlertRepo.getAllFlow().onEach { all -> + pairAlertRepo.getAllFlow().onEach { all -> + intent { val pages = all.reversed().groupBy { it.group } .map { (group, pairAlertList) -> @@ -100,18 +119,24 @@ class PairAlertViewModel( PairAlertScreenPage(group, created, oneTimeTriggered) } - intent { - reduce { - state.copy(pages = pages, initialized = true) - } + reduce { + state.copy(pages = pages, initialized = true) } - }.launchIn(viewModelScope) - } + } + }.launchIn(viewModelScope) + } fun onNewPair(pairId: Long? = null) = intent { if (notificationPermissionHelper.isGranted()) { - postSideEffect(PairAlertEffect.NavigateToAdd(pairId)) + postSideEffect( + PairAlertEffect.NavigateToAdd( + AddPairAlertScreenArgs( + pairId, + state.currentGroup(pagerState.currentPage), + ), + ), + ) } else { reduce { state.copy(askNotificationPermissionPairId = pairId) @@ -122,7 +147,14 @@ class PairAlertViewModel( fun onNotificationPermissionGrantedOnNewPair() = intent { - postSideEffect(PairAlertEffect.NavigateToAdd(state.askNotificationPermissionPairId)) + postSideEffect( + PairAlertEffect.NavigateToAdd( + AddPairAlertScreenArgs( + state.askNotificationPermissionPairId, + state.currentGroup(pagerState.currentPage), + ), + ), + ) reduce { state.copy(askNotificationPermissionPairId = null) } diff --git a/feature/portfolio/build.gradle.kts b/feature/portfolio/build.gradle.kts index 414ac99da..be88a8c5a 100644 --- a/feature/portfolio/build.gradle.kts +++ b/feature/portfolio/build.gradle.kts @@ -2,6 +2,7 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) alias(libs.plugins.ksp) + alias(libs.plugins.kotlin.parcelize) } android { diff --git a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/di/PortfolioComponent.kt b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/di/PortfolioComponent.kt index 2ebc2bff5..c413327f5 100644 --- a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/di/PortfolioComponent.kt +++ b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/di/PortfolioComponent.kt @@ -13,7 +13,7 @@ import dev.arkbuilders.rate.feature.portfolio.presentation.main.PortfolioViewMod interface PortfolioComponent { fun assetsVMFactory(): PortfolioViewModelFactory - fun addCurrencyVMFactory(): AddAssetViewModelFactory + fun addCurrencyVMFactory(): AddAssetViewModelFactory.Factory fun editAssetVMFactory(): EditAssetViewModelFactory.Factory diff --git a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetScreen.kt b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetScreen.kt index 18c56c1ed..66901de7b 100644 --- a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetScreen.kt +++ b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetScreen.kt @@ -1,5 +1,6 @@ package dev.arkbuilders.rate.feature.portfolio.presentation.add +import android.os.Parcelable import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -64,26 +65,36 @@ import dev.arkbuilders.rate.feature.portfolio.di.PortfolioComponentHolder import dev.arkbuilders.rate.feature.portfolio.presentation.ui.PortfolioCreateDialog import dev.arkbuilders.rate.feature.portfolio.presentation.ui.PortfolioSelectPopup import dev.arkbuilders.rate.feature.search.presentation.destinations.SearchCurrencyScreenDestination +import kotlinx.parcelize.Parcelize import org.orbitmvi.orbit.compose.collectAsState import org.orbitmvi.orbit.compose.collectSideEffect import dev.arkbuilders.rate.core.presentation.R as CoreR +@Parcelize +data class AddAssetScreenArgs( + val group: String?, +) : Parcelable + @Destination @Composable -fun AddAssetScreen(navigator: DestinationsNavigator) { +fun AddAssetScreen( + args: AddAssetScreenArgs, + navigator: DestinationsNavigator, +) { val ctx = LocalContext.current val component = remember { PortfolioComponentHolder.provide(ctx) } val viewModel: AddAssetViewModel = - viewModel(factory = component.addCurrencyVMFactory()) + viewModel(factory = component.addCurrencyVMFactory().create(args)) val state by viewModel.collectAsState() viewModel.collectSideEffect { effect -> when (effect) { AddAssetSideEffect.NavigateBack -> navigator.popBackStack() + is AddAssetSideEffect.NotifyAssetAdded -> { val added = effect.amounts diff --git a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetViewModel.kt b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetViewModel.kt index a333b286e..7564cc0e4 100644 --- a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetViewModel.kt +++ b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/add/AddAssetViewModel.kt @@ -3,6 +3,9 @@ package dev.arkbuilders.rate.feature.portfolio.presentation.add import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import dev.arkbuilders.rate.core.domain.CurrUtils import dev.arkbuilders.rate.core.domain.model.AmountStr import dev.arkbuilders.rate.core.domain.repo.AnalyticsManager @@ -10,7 +13,6 @@ import dev.arkbuilders.rate.core.domain.repo.CodeUseStatRepo import dev.arkbuilders.rate.core.domain.repo.CurrencyRepo import dev.arkbuilders.rate.core.domain.toBigDecimalArk import dev.arkbuilders.rate.core.presentation.AppSharedFlow -import dev.arkbuilders.rate.feature.portfolio.di.PortfolioScope import dev.arkbuilders.rate.feature.portfolio.domain.model.Asset import dev.arkbuilders.rate.feature.portfolio.domain.repo.PortfolioRepo import dev.arkbuilders.rate.feature.portfolio.domain.usecase.AddNewAssetsUseCase @@ -24,7 +26,6 @@ import org.orbitmvi.orbit.syntax.simple.postSideEffect import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container import timber.log.Timber -import javax.inject.Inject data class AddAssetState( val currencies: List = listOf(AmountStr("USD", "")), @@ -40,6 +41,7 @@ sealed class AddAssetSideEffect { } class AddAssetViewModel( + private val args: AddAssetScreenArgs, private val assetsRepo: PortfolioRepo, private val currencyRepo: CurrencyRepo, private val codeUseStatRepo: CodeUseStatRepo, @@ -82,7 +84,7 @@ class AddAssetViewModel( val groups = assetsRepo.allAssets().mapNotNull { it.group }.distinct() reduce { - state.copy(availableGroups = groups) + state.copy(availableGroups = groups, group = args.group) } } } @@ -136,13 +138,14 @@ class AddAssetViewModel( } addNewAssetsUseCase(currencies) codeUseStatRepo.codesUsed(*currencies.map { it.code }.toTypedArray()) + AppSharedFlow.SelectGroupPortfolio.flow.emit(state.group) postSideEffect(AddAssetSideEffect.NotifyAssetAdded(currencies)) postSideEffect(AddAssetSideEffect.NavigateBack) } } -@PortfolioScope -class AddAssetViewModelFactory @Inject constructor( +class AddAssetViewModelFactory @AssistedInject constructor( + @Assisted private val args: AddAssetScreenArgs, private val assetsRepo: PortfolioRepo, private val currencyRepo: CurrencyRepo, private val codeUseStatRepo: CodeUseStatRepo, @@ -151,6 +154,7 @@ class AddAssetViewModelFactory @Inject constructor( ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return AddAssetViewModel( + args, assetsRepo, currencyRepo, codeUseStatRepo, @@ -158,4 +162,9 @@ class AddAssetViewModelFactory @Inject constructor( addNewAssetsUseCase, ) as T } + + @AssistedFactory + interface Factory { + fun create(args: AddAssetScreenArgs): AddAssetViewModelFactory + } } diff --git a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioScreen.kt b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioScreen.kt index 5e085acd3..1f0ed0572 100644 --- a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioScreen.kt +++ b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioScreen.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -62,6 +63,7 @@ import dev.arkbuilders.rate.core.presentation.ui.RateSnackbarHost import dev.arkbuilders.rate.core.presentation.ui.SearchTextField import dev.arkbuilders.rate.feature.portfolio.di.PortfolioComponentHolder import dev.arkbuilders.rate.feature.portfolio.domain.model.Asset +import dev.arkbuilders.rate.feature.portfolio.presentation.add.AddAssetScreenArgs import dev.arkbuilders.rate.feature.portfolio.presentation.destinations.AddAssetScreenDestination import dev.arkbuilders.rate.feature.portfolio.presentation.destinations.EditAssetScreenDestination import org.orbitmvi.orbit.compose.collectAsState @@ -106,6 +108,9 @@ fun PortfolioScreen(navigator: DestinationsNavigator) { ) snackState.showSnackbar(visuals) } + + is PortfolioScreenEffect.SelectGroup -> + viewModel.pagerState.scrollToPage(effect.groupIndex) } } @@ -124,7 +129,16 @@ fun PortfolioScreen(navigator: DestinationsNavigator) { containerColor = ArkColor.Secondary, shape = CircleShape, onClick = { - navigator.navigate(AddAssetScreenDestination) + navigator.navigate( + AddAssetScreenDestination( + AddAssetScreenArgs( + group = + state.currentGroup( + viewModel.pagerState.currentPage, + ), + ), + ), + ) }, ) { Icon(Icons.Default.Add, contentDescription = "") @@ -148,6 +162,7 @@ fun PortfolioScreen(navigator: DestinationsNavigator) { }, onFilterChange = viewModel::onFilterChange, onDelete = viewModel::onAssetRemove, + pagerState = viewModel.pagerState, ) } } @@ -176,13 +191,13 @@ private val previewState = ), ) -@Preview(showBackground = true) @Composable private fun Content( state: PortfolioScreenState = previewState, onClick: (PortfolioDisplayAsset) -> Unit = {}, onFilterChange: (String) -> Unit = {}, onDelete: (Asset) -> Unit = {}, + pagerState: PagerState, ) { val groups = state.pages.map { it.group } Column { @@ -208,6 +223,7 @@ private fun Content( } else { GroupViewPager( modifier = Modifier.padding(top = 20.dp), + pagerState = pagerState, groups = groups, ) { index -> GroupPage( @@ -396,7 +412,7 @@ private fun PortfolioEmpty(navigator: DestinationsNavigator) { AppButton( modifier = Modifier.padding(top = 24.dp), onClick = { - navigator.navigate(AddAssetScreenDestination) + navigator.navigate(AddAssetScreenDestination(AddAssetScreenArgs(group = null))) }, ) { Icon( diff --git a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioViewModel.kt b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioViewModel.kt index e147b5f45..127a9a31a 100644 --- a/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioViewModel.kt +++ b/feature/portfolio/src/main/java/dev/arkbuilders/rate/feature/portfolio/presentation/main/PortfolioViewModel.kt @@ -12,6 +12,7 @@ import dev.arkbuilders.rate.core.domain.repo.Prefs import dev.arkbuilders.rate.core.domain.usecase.ConvertWithRateUseCase import dev.arkbuilders.rate.core.presentation.AppSharedFlow import dev.arkbuilders.rate.core.presentation.ui.NotifyAddedSnackbarVisuals +import dev.arkbuilders.rate.core.presentation.ui.RatePagerState import dev.arkbuilders.rate.feature.portfolio.di.PortfolioScope import dev.arkbuilders.rate.feature.portfolio.domain.model.Asset import dev.arkbuilders.rate.feature.portfolio.domain.repo.PortfolioRepo @@ -34,7 +35,9 @@ data class PortfolioScreenState( val pages: List = emptyList(), val initialized: Boolean = false, val noInternet: Boolean = false, -) +) { + fun currentGroup(index: Int) = pages.getOrNull(index)?.group +} data class PortfolioScreenPage( val group: String?, @@ -53,6 +56,8 @@ sealed class PortfolioScreenEffect { ) : PortfolioScreenEffect() data class ShowRemovedSnackbar(val asset: Asset) : PortfolioScreenEffect() + + data class SelectGroup(val groupIndex: Int) : PortfolioScreenEffect() } class PortfolioViewModel( @@ -65,6 +70,8 @@ class PortfolioViewModel( override val container: Container = container(PortfolioScreenState()) + val pagerState = RatePagerState(updatedPageCount = { container.stateFlow.value.pages.size }) + init { analyticsManager.trackScreen("PortfolioScreen") @@ -80,22 +87,32 @@ class PortfolioViewModel( } } - private fun init() = - intent { - initPages() + private fun init() { + initPages() - AppSharedFlow.ShowAddedSnackbarPortfolio.flow.onEach { visuals -> + AppSharedFlow.SelectGroupPortfolio.flow.onEach { group -> + intent { + val page = state.pages.find { it.group == group } + val index = page?.let { state.pages.indexOf(it) } + if (index != null && index != -1) + postSideEffect(PortfolioScreenEffect.SelectGroup(index)) + } + }.launchIn(viewModelScope) + + AppSharedFlow.ShowAddedSnackbarPortfolio.flow.onEach { visuals -> + intent { postSideEffect(PortfolioScreenEffect.ShowSnackbarAdded(visuals)) - }.launchIn(viewModelScope) + } + }.launchIn(viewModelScope) - prefs.flow(PreferenceKey.BaseCurrencyCode).drop(1).onEach { - initPages() - }.launchIn(viewModelScope) + prefs.flow(PreferenceKey.BaseCurrencyCode).drop(1).onEach { + initPages() + }.launchIn(viewModelScope) - assetsRepo.allAssetsFlow().drop(1).onEach { - initPages() - }.launchIn(viewModelScope) - } + assetsRepo.allAssetsFlow().drop(1).onEach { + initPages() + }.launchIn(viewModelScope) + } fun onRefreshClick() = intent { diff --git a/feature/quick/build.gradle.kts b/feature/quick/build.gradle.kts index 35017441b..fd5ec8d96 100644 --- a/feature/quick/build.gradle.kts +++ b/feature/quick/build.gradle.kts @@ -2,6 +2,7 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) alias(libs.plugins.ksp) + alias(libs.plugins.kotlin.parcelize) } android { diff --git a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt index d00822d35..ee7b0322c 100644 --- a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt +++ b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt @@ -2,6 +2,7 @@ package dev.arkbuilders.rate.feature.quick.presentation.add +import android.os.Parcelable import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -69,16 +70,22 @@ import dev.arkbuilders.rate.core.presentation.ui.GroupSelectPopup import dev.arkbuilders.rate.core.presentation.ui.NotifyAddedSnackbarVisuals import dev.arkbuilders.rate.feature.quick.di.QuickComponentHolder import dev.arkbuilders.rate.feature.search.presentation.destinations.SearchCurrencyScreenDestination +import kotlinx.parcelize.Parcelize import org.orbitmvi.orbit.compose.collectAsState import org.orbitmvi.orbit.compose.collectSideEffect +@Parcelize +data class AddQuickScreenArgs( + val quickPairId: Long? = null, + val newCode: CurrencyCode? = null, + val reuseNotEdit: Boolean = true, + val group: String?, +) : Parcelable + @Composable @Destination fun AddQuickScreen( - quickPairId: Long? = null, - newCode: CurrencyCode? = null, - reuseNotEdit: Boolean = true, - group: String? = null, + args: AddQuickScreenArgs, navigator: DestinationsNavigator, ) { val ctx = LocalContext.current @@ -90,7 +97,7 @@ fun AddQuickScreen( viewModel( factory = quickComponent.addQuickVMFactory() - .create(quickPairId, newCode, reuseNotEdit, group), + .create(args), ) val state by viewModel.collectAsState() @@ -121,7 +128,7 @@ fun AddQuickScreen( Scaffold( topBar = { val title = - if (reuseNotEdit) + if (args.reuseNotEdit) R.string.quick_add_new_calculation else R.string.quick_edit_pair diff --git a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt index 3c28d4f54..e480de184 100644 --- a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt +++ b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt @@ -8,7 +8,6 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import dev.arkbuilders.rate.core.domain.CurrUtils import dev.arkbuilders.rate.core.domain.model.AmountStr -import dev.arkbuilders.rate.core.domain.model.CurrencyCode import dev.arkbuilders.rate.core.domain.model.toAmount import dev.arkbuilders.rate.core.domain.model.toStrAmount import dev.arkbuilders.rate.core.domain.repo.AnalyticsManager @@ -45,10 +44,7 @@ sealed class AddQuickScreenEffect { } class AddQuickViewModel( - private val quickPairId: Long?, - private val newCode: CurrencyCode?, - private val reuseNotEdit: Boolean, - private val group: String?, + private val args: AddQuickScreenArgs, private val quickRepo: QuickRepo, private val convertUseCase: ConvertWithRateUseCase, private val codeUseStatRepo: CodeUseStatRepo, @@ -82,7 +78,7 @@ class AddQuickViewModel( intent { val groups = quickRepo.getAll().mapNotNull { it.group }.distinct() - val quickPair = quickPairId?.let { quickRepo.getById(it) } + val quickPair = args.quickPairId?.let { quickRepo.getById(it) } quickPair?.let { val currencies = listOf( @@ -95,7 +91,7 @@ class AddQuickViewModel( reduce { state.copy( - quickPairId = quickPairId, + quickPairId = args.quickPairId, currencies = calc, group = quickPair.group, availableGroups = groups, @@ -104,10 +100,10 @@ class AddQuickViewModel( checkFinishEnabled() } ?: reduce { val currencies = - newCode?.let { - listOf(AmountStr(newCode, "")) + args.newCode?.let { + listOf(AmountStr(args.newCode, "")) } ?: state.currencies - state.copy(currencies = currencies, availableGroups = groups, group = group) + state.copy(currencies = currencies, availableGroups = groups, group = args.group) } } } @@ -142,8 +138,8 @@ class AddQuickViewModel( intent { val from = state.currencies.first() val id = - if (quickPairId != null) { - if (reuseNotEdit) 0 else quickPairId + if (args.quickPairId != null) { + if (args.reuseNotEdit) 0 else args.quickPairId } else { 0 } @@ -163,6 +159,7 @@ class AddQuickViewModel( quick.from, *quick.to.map { it.code }.toTypedArray(), ) + AppSharedFlow.SelectGroupQuick.flow.emit(state.group) postSideEffect(AddQuickScreenEffect.NotifyPairAdded(quick)) postSideEffect(AddQuickScreenEffect.NavigateBack) } @@ -202,10 +199,7 @@ class AddQuickViewModel( } class AddQuickViewModelFactory @AssistedInject constructor( - @Assisted private val quickPairId: Long?, - @Assisted("newCode") private val newCode: CurrencyCode?, - @Assisted private val reuseNotEdit: Boolean, - @Assisted("group") private val group: String?, + @Assisted private val args: AddQuickScreenArgs, private val quickRepo: QuickRepo, private val codeUseStatRepo: CodeUseStatRepo, private val convertUseCase: ConvertWithRateUseCase, @@ -213,10 +207,7 @@ class AddQuickViewModelFactory @AssistedInject constructor( ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return AddQuickViewModel( - quickPairId, - newCode, - reuseNotEdit, - group, + args, quickRepo, convertUseCase, codeUseStatRepo, @@ -226,11 +217,6 @@ class AddQuickViewModelFactory @AssistedInject constructor( @AssistedFactory interface Factory { - fun create( - quickPairId: Long?, - @Assisted("newCode") newCode: CurrencyCode?, - reuseNotEdit: Boolean, - @Assisted("group") group: String?, - ): AddQuickViewModelFactory + fun create(args: AddQuickScreenArgs): AddQuickViewModelFactory } } diff --git a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickScreen.kt b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickScreen.kt index 066225362..28d6d28b3 100644 --- a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickScreen.kt +++ b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -70,6 +71,7 @@ import dev.arkbuilders.rate.core.presentation.utils.DateFormatUtils import dev.arkbuilders.rate.feature.quick.di.QuickComponentHolder import dev.arkbuilders.rate.feature.quick.domain.model.PinnedQuickPair import dev.arkbuilders.rate.feature.quick.domain.model.QuickPair +import dev.arkbuilders.rate.feature.quick.presentation.add.AddQuickScreenArgs import dev.arkbuilders.rate.feature.quick.presentation.destinations.AddQuickScreenDestination import dev.arkbuilders.rate.feature.quick.presentation.ui.PinnedQuickSwipeItem import dev.arkbuilders.rate.feature.quick.presentation.ui.QuickOptionsBottomSheet @@ -121,6 +123,8 @@ fun QuickScreen(navigator: DestinationsNavigator) { ) snackState.showSnackbar(visuals) } + + is QuickScreenEffect.SelectGroup -> viewModel.pagerState.scrollToPage(effect.groupIndex) } } @@ -145,7 +149,16 @@ fun QuickScreen(navigator: DestinationsNavigator) { containerColor = ArkColor.Secondary, shape = CircleShape, onClick = { - navigator.navigate(AddQuickScreenDestination()) + navigator.navigate( + AddQuickScreenDestination( + AddQuickScreenArgs( + group = + state.currentGroup( + viewModel.pagerState.currentPage, + ), + ), + ), + ) }, ) { Icon(Icons.Default.Add, contentDescription = "") @@ -163,6 +176,7 @@ fun QuickScreen(navigator: DestinationsNavigator) { else -> Content( state = state, + pagerState = viewModel.pagerState, onFilterChanged = viewModel::onFilterChanged, onDelete = viewModel::onDelete, onClick = { @@ -171,8 +185,17 @@ fun QuickScreen(navigator: DestinationsNavigator) { onPin = viewModel::onPin, onUnpin = viewModel::onUnpin, onNewCode = { - navigator - .navigate(AddQuickScreenDestination(newCode = it)) + navigator.navigate( + AddQuickScreenDestination( + AddQuickScreenArgs( + newCode = it, + group = + state.currentGroup( + viewModel.pagerState.currentPage, + ), + ), + ), + ) }, ) } @@ -186,14 +209,22 @@ fun QuickScreen(navigator: DestinationsNavigator) { onEdit = { navigator.navigate( AddQuickScreenDestination( - quickPairId = it.id, - reuseNotEdit = false, + AddQuickScreenArgs( + quickPairId = it.id, + reuseNotEdit = false, + group = state.currentGroup(viewModel.pagerState.currentPage), + ), ), ) }, onReuse = { navigator.navigate( - AddQuickScreenDestination(quickPairId = it.id), + AddQuickScreenDestination( + AddQuickScreenArgs( + quickPairId = it.id, + group = state.currentGroup(viewModel.pagerState.currentPage), + ), + ), ) }, onDelete = viewModel::onDelete, @@ -211,6 +242,7 @@ fun QuickScreen(navigator: DestinationsNavigator) { @Composable private fun Content( state: QuickScreenState, + pagerState: PagerState, onFilterChanged: (String) -> Unit, onDelete: (QuickPair) -> Unit, onClick: (QuickPair) -> Unit, @@ -254,6 +286,7 @@ private fun Content( } else { GroupViewPager( modifier = Modifier.padding(top = 20.dp), + pagerState = pagerState, groups = groups, ) { index -> GroupPage( @@ -588,7 +621,7 @@ private fun QuickEmpty(navigator: DestinationsNavigator) { AppButton( modifier = Modifier.padding(top = 24.dp), onClick = { - navigator.navigate(AddQuickScreenDestination()) + navigator.navigate(AddQuickScreenDestination(AddQuickScreenArgs(group = null))) }, ) { Icon( diff --git a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickViewModel.kt b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickViewModel.kt index 90611a25f..5c38fdfd2 100644 --- a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickViewModel.kt +++ b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/main/QuickViewModel.kt @@ -15,6 +15,7 @@ import dev.arkbuilders.rate.core.domain.usecase.ConvertWithRateUseCase import dev.arkbuilders.rate.core.domain.usecase.GetTopResultUseCase import dev.arkbuilders.rate.core.presentation.AppSharedFlow import dev.arkbuilders.rate.core.presentation.ui.NotifyAddedSnackbarVisuals +import dev.arkbuilders.rate.core.presentation.ui.RatePagerState import dev.arkbuilders.rate.feature.quick.domain.model.PinnedQuickPair import dev.arkbuilders.rate.feature.quick.domain.model.QuickPair import dev.arkbuilders.rate.feature.quick.domain.repo.QuickRepo @@ -47,7 +48,9 @@ data class QuickScreenState( val optionsData: OptionsData? = null, val initialized: Boolean = false, val noInternet: Boolean = false, -) +) { + fun currentGroup(index: Int) = pages.getOrNull(index)?.group +} sealed class QuickScreenEffect { data class ShowSnackbarAdded( @@ -55,6 +58,8 @@ sealed class QuickScreenEffect { ) : QuickScreenEffect() data class ShowRemovedSnackbar(val pair: QuickPair) : QuickScreenEffect() + + data class SelectGroup(val groupIndex: Int) : QuickScreenEffect() } class QuickViewModel( @@ -69,6 +74,8 @@ class QuickViewModel( override val container: Container = container(QuickScreenState()) + val pagerState = RatePagerState(updatedPageCount = { container.stateFlow.value.pages.size }) + init { analyticsManager.trackScreen("QuickScreen") @@ -84,25 +91,35 @@ class QuickViewModel( } } - private fun init() = - intent { - AppSharedFlow.ShowAddedSnackbarQuick.flow.onEach { visuals -> + private fun init() { + AppSharedFlow.SelectGroupQuick.flow.onEach { group -> + intent { + val page = state.pages.find { it.group == group } + val index = page?.let { state.pages.indexOf(it) } + if (index != null && index != -1) + postSideEffect(QuickScreenEffect.SelectGroup(index)) + } + }.launchIn(viewModelScope) + + AppSharedFlow.ShowAddedSnackbarQuick.flow.onEach { visuals -> + intent { postSideEffect(QuickScreenEffect.ShowSnackbarAdded(visuals)) - }.launchIn(viewModelScope) - - quickRepo.allFlow().drop(1).onEach { quick -> - intent { - val pages = mapPairsToPages(quick) - reduce { - state.copy( - pages = pages, - ) - } + } + }.launchIn(viewModelScope) + + quickRepo.allFlow().drop(1).onEach { quick -> + intent { + val pages = mapPairsToPages(quick) + reduce { + state.copy( + pages = pages, + ) } - }.launchIn(viewModelScope) + } + }.launchIn(viewModelScope) - val allCurrencies = currencyRepo.getCurrencyNameUnsafe() - calcFrequentCurrUseCase.flow().drop(1).onEach { + calcFrequentCurrUseCase.flow().drop(1).onEach { + intent { val frequent = calcFrequentCurrUseCase.invoke() .map { currencyRepo.nameByCodeUnsafe(it) } @@ -113,8 +130,11 @@ class QuickViewModel( topResults = topResults, ) } - }.launchIn(viewModelScope) + } + }.launchIn(viewModelScope) + intent { + val allCurrencies = currencyRepo.getCurrencyNameUnsafe() val frequent = calcFrequentCurrUseCase() .map { currencyRepo.nameByCodeUnsafe(it) } @@ -130,6 +150,7 @@ class QuickViewModel( ) } } + } fun onRefreshClick() = intent { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d936546e6..aa41dedfa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -89,3 +89,4 @@ material = { group = "com.google.android.material", name = "material", version.r android-library = { id = "com.android.library", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"} +kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }