Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 82 additions & 24 deletions app/src/main/java/dev/arkbuilders/rate/presentation/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.currentBackStackEntryAsState
import com.ramcosta.composedestinations.DestinationsNavHost
Expand All @@ -36,6 +38,8 @@ import com.ramcosta.composedestinations.navargs.primitives.longNavType
import com.ramcosta.composedestinations.rememberNavHostEngine
import com.ramcosta.composedestinations.scope.resultRecipient
import com.ramcosta.composedestinations.utils.startDestination
import dev.arkbuilders.rate.core.domain.repo.AnalyticsManager
import dev.arkbuilders.rate.core.domain.repo.NetworkStatus
import dev.arkbuilders.rate.core.presentation.ui.ConnectivityOfflineSnackbar
import dev.arkbuilders.rate.core.presentation.ui.ConnectivityOfflineSnackbarVisuals
import dev.arkbuilders.rate.core.presentation.ui.ConnectivityOnlineSnackbar
Expand Down Expand Up @@ -70,31 +74,19 @@ fun MainScreen() {
val engine = rememberNavHostEngine()
val navController = engine.rememberNavController()
val snackState = remember { SnackbarHostState() }
val ctx = LocalContext.current
val coreComponent = App.instance.coreComponent

LaunchedEffect(key1 = Unit) {
val activity = ctx.findActivity()
val intent = activity?.intent
val createNewCalc = intent?.getStringExtra(ADD_NEW_CALCULATION) ?: ""
if (createNewCalc.isNotEmpty()) {
val groupId = intent?.getLongExtra(ADD_NEW_CALCULATION_GROUP_KEY, 0L)
navController.navigate(AddQuickScreenDestination(groupId = groupId))
intent?.removeExtra(ADD_NEW_CALCULATION_GROUP_KEY)
intent?.removeExtra(ADD_NEW_CALCULATION)
}
}
LaunchedEffect(key1 = Unit) {
App.instance.coreComponent.networkStatus().onlineStatus
.drop(1)
.collect { online ->
val visuals =
if (online)
ConnectivityOnlineSnackbarVisuals
else
ConnectivityOfflineSnackbarVisuals
snackState.showSnackbar(visuals)
}
}
HandleAddQuickCalculationIntentEffect(navController)

ObserveNetworkStatusEffect(
networkStatus = coreComponent.networkStatus(),
snackState = snackState,
)

ObserveNavigationAnalyticsEffect(
navController = navController,
analyticsManager = coreComponent.analyticsManager(),
)

val isKeyboardOpen by keyboardAsState()
val bottomBarVisible = rememberSaveable { mutableStateOf(false) }
Expand Down Expand Up @@ -205,3 +197,69 @@ fun MainScreen() {
}
}
}

@Composable
private fun HandleAddQuickCalculationIntentEffect(navController: NavController) {
val ctx = LocalContext.current
LaunchedEffect(key1 = Unit) {
val activity = ctx.findActivity()
val intent = activity?.intent
val createNewCalc = intent?.getStringExtra(ADD_NEW_CALCULATION) ?: ""
if (createNewCalc.isNotEmpty()) {
val groupId = intent?.getLongExtra(ADD_NEW_CALCULATION_GROUP_KEY, 0L)
navController.navigate(AddQuickScreenDestination(groupId = groupId))
intent?.removeExtra(ADD_NEW_CALCULATION_GROUP_KEY)
intent?.removeExtra(ADD_NEW_CALCULATION)
}
}
}

@Composable
private fun ObserveNetworkStatusEffect(
networkStatus: NetworkStatus,
snackState: SnackbarHostState,
) {
LaunchedEffect(key1 = Unit) {
networkStatus.onlineStatus
.drop(1)
.collect { online ->
val visuals =
if (online)
ConnectivityOnlineSnackbarVisuals
else
ConnectivityOfflineSnackbarVisuals
snackState.showSnackbar(visuals)
}
}
}

@Composable
private fun ObserveNavigationAnalyticsEffect(
navController: NavController,
analyticsManager: AnalyticsManager,
) {
DisposableEffect(navController) {
val listener =
NavController.OnDestinationChangedListener { _, destination, _ ->
destination.route?.let { route ->
val name = extractScreenName(route)
analyticsManager.trackScreen(name)
}
}
navController.addOnDestinationChangedListener(listener)
onDispose {
navController.removeOnDestinationChangedListener(listener)
}
}
}

private fun extractScreenName(route: String): String {
val routeWithoutArguments = route.substringBefore("?")

val name =
routeWithoutArguments.split("/").findLast {
it.contains("{").not()
}

return name ?: route
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ class AddPairAlertViewModel(
container(AddPairAlertScreenState())

init {
analyticsManager.trackScreen("AddPairAlertScreen")

pairAlertId?.let {
setupFromExisting()
checkAboveNotBelow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ class PairAlertViewModel(
)

init {
analyticsManager.trackScreen("PairAlertScreen")

intent {
if (pairAlertRepo.getAll().isNotEmpty() &&
notificationPermissionHelper.isGranted().not()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.arkbuilders.rate.feature.portfolio.presentation.add

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -84,6 +85,10 @@ fun AddAssetScreen(
}
}

BackHandler {
viewModel.onBackClick()
}

val state by viewModel.collectAsState()

viewModel.collectSideEffect { effect ->
Expand All @@ -94,7 +99,7 @@ fun AddAssetScreen(
topBar = {
AppTopBarBack(
title = stringResource(CoreRString.portfolio_add_new_assets),
onBackClick = { navigator.popBackStack() },
onBackClick = { viewModel.onBackClick() },
)
},
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ sealed class AddAssetSideEffect {

data class NavigateSearchSet(val index: Int, val prohibitedCodes: List<CurrencyCode>) :
AddAssetSideEffect()

data object NavigateBack : AddAssetSideEffect()
}

enum class SearchNavResultType {
Expand All @@ -61,8 +63,6 @@ class AddAssetViewModel(
container(AddAssetState())

init {
analyticsManager.trackScreen("AddAssetScreen")

intent {
val group = getGroupByIdOrCreateDefaultUseCase(groupId, GroupFeatureType.Portfolio)
val groups = groupRepo.getAllSorted(GroupFeatureType.Portfolio)
Expand Down Expand Up @@ -108,6 +108,7 @@ class AddAssetViewModel(

fun onAssetRemove(removeIndex: Int) =
intent {
analyticsManager.logEvent("add_asset_currency_removed")
reduce {
state.copy(
currencies =
Expand All @@ -119,6 +120,7 @@ class AddAssetViewModel(

fun onGroupCreate(name: String) =
intent {
analyticsManager.logEvent("add_asset_group_created")
val group = Group.empty(name = name)
val inAvailable = state.availableGroups.any { it.name == group.name }
reduce {
Expand All @@ -137,6 +139,7 @@ class AddAssetViewModel(

fun onGroupSelect(group: Group) =
intent {
analyticsManager.logEvent("add_asset_group_selected")
reduce { state.copy(group = group) }
}

Expand All @@ -163,6 +166,7 @@ class AddAssetViewModel(

fun onAddAsset() =
intent {
analyticsManager.logEvent("add_asset_added")
val group = groupRepo.getByNameOrCreateNew(state.group.name, GroupFeatureType.Portfolio)

val currencies =
Expand All @@ -186,16 +190,24 @@ class AddAssetViewModel(

fun onSetCode(index: Int) =
intent {
analyticsManager.logEvent("add_asset_set_code_clicked")
val prohibitedCodes = state.currencies.map { it.code }.toMutableList()
prohibitedCodes.removeAt(index)
postSideEffect(AddAssetSideEffect.NavigateSearchSet(index, prohibitedCodes))
}

fun onAddCode() =
intent {
analyticsManager.logEvent("add_asset_add_code_clicked")
val prohibitedCodes = state.currencies.map { it.code }
postSideEffect(AddAssetSideEffect.NavigateSearchAdd(prohibitedCodes))
}

fun onBackClick() =
intent {
analyticsManager.logEvent("add_asset_back_clicked")
postSideEffect(AddAssetSideEffect.NavigateBack)
}
}

class AddAssetViewModelFactory @AssistedInject constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ suspend fun handleAddAssetSideEffect(
prohibitedCodes = effect.prohibitedCodes.toTypedArray(),
),
)

AddAssetSideEffect.NavigateBack -> navigator.popBackStack()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package dev.arkbuilders.rate.feature.portfolio.presentation.edit

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -43,6 +44,7 @@ import dev.arkbuilders.rate.core.presentation.ui.InfoDialog
import dev.arkbuilders.rate.core.presentation.ui.LoadingScreen
import dev.arkbuilders.rate.feature.portfolio.di.PortfolioComponentHolder
import org.orbitmvi.orbit.compose.collectAsState
import org.orbitmvi.orbit.compose.collectSideEffect

@Destination<ExternalModuleGraph>
@Composable
Expand All @@ -63,11 +65,21 @@ fun EditAssetScreen(

val state by viewModel.collectAsState()

viewModel.collectSideEffect { effect ->
when (effect) {
EditAssetScreenEffect.NavigateBack -> navigator.popBackStack()
}
}

BackHandler {
viewModel.onBackClick()
}

Scaffold(
topBar = {
AppTopBarBack(
title = stringResource(CoreRString.asset_detail),
onBackClick = { navigator.popBackStack() },
onBackClick = { viewModel.onBackClick() },
)
},
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ data class EditAssetScreenState(
val initialized: Boolean = false,
)

sealed class EditAssetScreenEffect
sealed class EditAssetScreenEffect {
data object NavigateBack : EditAssetScreenEffect()
}

private val PERSIST_AMOUNT_DEBOUNCE = 300L

Expand All @@ -46,8 +48,6 @@ class EditAssetViewModel(
private val inputFlow = MutableSharedFlow<String>()

init {
analyticsManager.trackScreen("EditAssetScreen")

intent {
val asset = assetsRepo.getById(assetId)
val name = currencyRepo.infoByCode(asset!!.code)
Expand All @@ -70,6 +70,12 @@ class EditAssetViewModel(
state.copy(value = validated)
}
}

fun onBackClick() =
intent {
analyticsManager.logEvent("edit_asset_back_clicked")
postSideEffect(EditAssetScreenEffect.NavigateBack)
}
}

class EditAssetViewModelFactory @AssistedInject constructor(
Expand Down
Loading