Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Commit

Permalink
Add an option to fetch missing transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
ILIYANGERMANOV committed Jun 25, 2022
1 parent 3fc70a6 commit c055670
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 1 deletion.
2 changes: 2 additions & 0 deletions app/src/main/java/com/ivy/wallet/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ object Constants {
const val SWIPE_UP_EXPANDED_THRESHOLD = 200

const val SUPPORT_EMAIL = "[email protected]"

const val PAGE_TRANSACTIONS_SIZE = 100
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.ivy.wallet.domain.action.transaction

import com.ivy.frp.action.FPAction
import com.ivy.frp.monad.Res
import com.ivy.frp.monad.tryOp
import com.ivy.wallet.Constants
import com.ivy.wallet.io.network.RestClient
import com.ivy.wallet.io.persistence.dao.TransactionDao
import javax.inject.Inject

class FetchAllTrnsFromServerAct @Inject constructor(
restClient: RestClient,
private val transactionDao: TransactionDao
) : FPAction<Unit, Res<Exception, Unit>>() {
companion object {
private const val MAX_LIMIT_IF_SHIT_HAPPENS = 1000
}

private val transactionService = restClient.transactionService

override suspend fun Unit.compose(): suspend () -> Res<Exception, Unit> = tryOp(
operation = ::fetch
)

private suspend fun fetch() {
tailrec suspend fun fetchInternal(page: Int) {
val transactions = transactionService.getPaginated(
page = page,
size = Constants.PAGE_TRANSACTIONS_SIZE
).transactions.map { it.toEntity() }

transactionDao.save(transactions)

if (transactions.isNotEmpty() && page < MAX_LIMIT_IF_SHIT_HAPPENS) {
//recurse
fetchInternal(page = page + 1)
}
}

fetchInternal(page = 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ interface TransactionService {
@GET("/wallet/transactions")
suspend fun get(@Query("after") after: Long? = null): TransactionsResponse

@GET("/wallet/transactions/paginated")
suspend fun getPaginated(
@Query("page") page: Int,
@Query("size") size: Int
): TransactionsResponse


@HTTP(method = "DELETE", path = "/wallet/transactions/delete", hasBody = true)
suspend fun delete(@Body request: DeleteTransactionRequest)
}
48 changes: 47 additions & 1 deletion app/src/main/java/com/ivy/wallet/ui/settings/SettingsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ fun BoxWithConstraintsScope.SettingsScreen(screen: Settings) {
val progressState by viewModel.progressState.collectAsState()

val nameLocalAccount by viewModel.nameLocalAccount.observeAsState()
val opFetchTrns by viewModel.opFetchTrns.collectAsState()

onScreenStart {
viewModel.start()
Expand All @@ -88,6 +89,7 @@ fun BoxWithConstraintsScope.SettingsScreen(screen: Settings) {

nameLocalAccount = nameLocalAccount,
startDateOfMonth = startDateOfMonth,
opFetchTrns = opFetchTrns,


onSetCurrency = viewModel::setCurrency,
Expand Down Expand Up @@ -115,7 +117,8 @@ fun BoxWithConstraintsScope.SettingsScreen(screen: Settings) {
)
},
onDeleteAllUserData = viewModel::deleteAllUserData,
onDeleteCloudUserData = viewModel::deleteCloudUserData
onDeleteCloudUserData = viewModel::deleteCloudUserData,
onFetchMissingTransactions = viewModel::fetchMissingTransactions
)
}

Expand All @@ -135,6 +138,8 @@ private fun BoxWithConstraintsScope.UI(
nameLocalAccount: String?,
startDateOfMonth: Int = 1,

opFetchTrns: OpResult<Unit>? = null,

onSetCurrency: (String) -> Unit,
onSetName: (String) -> Unit = {},

Expand All @@ -152,6 +157,7 @@ private fun BoxWithConstraintsScope.UI(
onRequestFeature: (String, String) -> Unit = { _, _ -> },
onDeleteAllUserData: () -> Unit = {},
onDeleteCloudUserData: () -> Unit = {},
onFetchMissingTransactions: () -> Unit = {},

) {
var currencyModalVisible by remember { mutableStateOf(false) }
Expand Down Expand Up @@ -227,6 +233,17 @@ private fun BoxWithConstraintsScope.UI(
// Premium()
}

item {
SettingsSectionDivider(text = "Sync")

Spacer(Modifier.height(16.dp))

FetchMissingTransactionsButton(
opFetchTrns = opFetchTrns,
onFetchMissingTransactions = onFetchMissingTransactions
)
}

item {
SettingsSectionDivider(text = stringResource(R.string.import_export))

Expand Down Expand Up @@ -1203,6 +1220,35 @@ private fun SettingsSectionDivider(
)
}

@Composable
fun FetchMissingTransactionsButton(
opFetchTrns: OpResult<Unit>?,
onFetchMissingTransactions: () -> Unit
) {
val background = Gradient.solid(
when (opFetchTrns) {
is OpResult.Failure -> Red
OpResult.Loading -> Orange
is OpResult.Success -> Green
null -> UI.colors.medium
}
)
SettingsPrimaryButton(
icon = R.drawable.ic_sync,
text = when (opFetchTrns) {
is OpResult.Failure -> "Error: ${opFetchTrns.error()}"
OpResult.Loading -> "Full sync... wait!"
is OpResult.Success -> "Success. Check transactions."
else -> "Fetch missing transactions"
},
backgroundGradient = background,
textColor = findContrastTextColor(background.startColor),
iconPadding = 0.dp
) {
onFetchMissingTransactions()
}
}

@Composable
private fun SettingsDefaultButton(
@DrawableRes icon: Int,
Expand Down
31 changes: 31 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/settings/SettingsViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ivy.frp.monad.Res
import com.ivy.frp.test.TestIdlingResource
import com.ivy.frp.view.navigation.Navigation
import com.ivy.wallet.domain.action.global.StartDayOfMonthAct
import com.ivy.wallet.domain.action.global.UpdateStartDayOfMonthAct
import com.ivy.wallet.domain.action.transaction.FetchAllTrnsFromServerAct
import com.ivy.wallet.domain.data.analytics.AnalyticsEvent
import com.ivy.wallet.domain.data.core.User
import com.ivy.wallet.domain.deprecated.logic.LogoutLogic
Expand All @@ -26,6 +28,7 @@ import com.ivy.wallet.io.persistence.dao.SettingsDao
import com.ivy.wallet.io.persistence.dao.UserDao
import com.ivy.wallet.refreshWidget
import com.ivy.wallet.ui.IvyWalletCtx
import com.ivy.wallet.ui.Main
import com.ivy.wallet.ui.RootActivity
import com.ivy.wallet.ui.widget.WalletBalanceReceiver
import com.ivy.wallet.utils.*
Expand Down Expand Up @@ -54,6 +57,8 @@ class SettingsViewModel @Inject constructor(
private val exportZipLogic: ExportZipLogic,
private val startDayOfMonthAct: StartDayOfMonthAct,
private val updateStartDayOfMonthAct: UpdateStartDayOfMonthAct,
private val fetchAllTrnsFromServerAct: FetchAllTrnsFromServerAct,
private val nav: Navigation
) : ViewModel() {

private val _user = MutableLiveData<User?>()
Expand Down Expand Up @@ -86,6 +91,9 @@ class SettingsViewModel @Inject constructor(
private val _startDateOfMonth = MutableLiveData<Int>()
val startDateOfMonth = _startDateOfMonth

private val _opFetchtrns = MutableStateFlow<OpResult<Unit>?>(null)
val opFetchTrns = _opFetchtrns.asStateFlow()

fun start() {
viewModelScope.launch {
TestIdlingResource.increment()
Expand Down Expand Up @@ -399,4 +407,27 @@ class SettingsViewModel @Inject constructor(
cloudLogout()
}
}

fun fetchMissingTransactions() {
if (opFetchTrns.value is OpResult.Loading) {
//wait for sync to finish
return
}

if (opFetchTrns.value is OpResult.Success) {
//go to home screen
ivyContext.setMoreMenuExpanded(expanded = false)
nav.navigateTo(Main)
return
}

viewModelScope.launch {
_opFetchtrns.value = OpResult.loading()

when (val res = fetchAllTrnsFromServerAct(Unit)) {
is Res.Ok -> _opFetchtrns.value = OpResult.success(Unit)
is Res.Err -> _opFetchtrns.value = OpResult.failure(res.error)
}
}
}
}

0 comments on commit c055670

Please sign in to comment.