Skip to content

Commit

Permalink
Implement ServerStopScreen.kt
Browse files Browse the repository at this point in the history
  • Loading branch information
ILIYANGERMANOV committed Nov 14, 2022
1 parent 70f8b62 commit c8032de
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,24 @@ class CustomerJourneyLogic(
donateIvyWallet()
)

fun ivyCloudNuke() = CustomerJourneyCardData(
id = "ivy_cloud_nuke",
condition = { trnCount, _, ivyContext ->
trnCount > 3 && !ivyContext.dataBackupCompleted
},
title = "WARNING!!!",
description = "IMPORTANT: Ivy Cloud (Google) sync will be stopped on Jan 1st, 2023! " +
"To prevent data loss backup your data. " +
"If you don't export your data now you risk losing your transactions.",
cta = "Backup data",
ctaIcon = R.drawable.ic_vue_security_shield,
background = Gradient.solid(Red),
hasDismiss = false,
onAction = { nav, _, _ ->
nav.navigateTo(ServerStop)
}
)

fun adjustBalanceCard() = CustomerJourneyCardData(
id = "adjust_balance",
condition = { trnCount, _, _ ->
Expand Down Expand Up @@ -281,6 +299,18 @@ class CustomerJourneyLogic(
}
}

@Preview
@Composable
private fun PreviewIvyCloudNuke() {
IvyWalletComponentPreview {
CustomerJourneyCard(
cardData = CustomerJourneyLogic.ivyCloudNuke(),
onCTA = { },
onDismiss = {}
)
}
}

@Preview
@Composable
private fun PreviewAdjustBalanceCard() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class SharedPrefs(appContext: Context) {

//----------------------------- Others -----------------------------------------------
const val CATEGORY_SORT_ORDER = "categorySortOrder"
const val DATA_BACKUP_COMPLETED = "data_backup_completed"
}

private val preferences = appContext.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/IvyWalletCtx.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class IvyWalletCtx : IvyContext() {
val accountMap: MutableMap<UUID, Account> = mutableMapOf()
//---------------------- Optimization ----------------------------

var dataBackupCompleted = false

@Deprecated("use StartDayOfMonthAct")
fun initStartDayOfMonthInMemory(sharedPrefs: SharedPrefs): Int {
startDayOfMonth = sharedPrefs.getInt(SharedPrefs.START_DATE_OF_MONTH, 1)
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/RootActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import com.ivy.wallet.ui.planned.edit.EditPlannedScreen
import com.ivy.wallet.ui.planned.list.PlannedPaymentsScreen
import com.ivy.wallet.ui.reports.ReportScreen
import com.ivy.wallet.ui.search.SearchScreen
import com.ivy.wallet.ui.serverstop.ServerStopScreen
import com.ivy.wallet.ui.settings.SettingsScreen
import com.ivy.wallet.ui.settings.experimental.ExperimentalScreen
import com.ivy.wallet.ui.statistic.level1.PieChartStatisticScreen
Expand Down Expand Up @@ -189,6 +190,7 @@ class RootActivity : AppCompatActivity() {
when (screen) {
is Main -> MainScreen(screen = screen)
is Onboarding -> OnboardingScreen(screen = screen)
is ServerStop -> ServerStopScreen()
is EditTransaction -> EditTransactionScreen(screen = screen)
is ItemStatistic -> ItemStatisticScreen(screen = screen)
is PieChartStatistic -> PieChartStatisticScreen(screen = screen)
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/Screens.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ object Main : Screen

object Onboarding : Screen

object ServerStop : Screen

data class EditTransaction(
val initialTransactionId: UUID?,
val type: TransactionType,
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/main/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.ivy.wallet.domain.deprecated.logic.currency.ExchangeRatesLogic
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.domain.deprecated.sync.IvySync
import com.ivy.wallet.domain.event.AccountsUpdatedEvent
import com.ivy.wallet.io.persistence.SharedPrefs
import com.ivy.wallet.io.persistence.dao.SettingsDao
import com.ivy.wallet.ui.IvyWalletCtx
import com.ivy.wallet.ui.Main
Expand All @@ -28,6 +29,7 @@ class MainViewModel @Inject constructor(
private val ivySync: IvySync,
private val exchangeRatesLogic: ExchangeRatesLogic,
private val accountCreator: AccountCreator,
private val sharedPrefs: SharedPrefs,
) : ViewModel() {

private val _currency = MutableLiveData<String>()
Expand All @@ -50,6 +52,9 @@ class MainViewModel @Inject constructor(
val baseCurrency = ioThread { settingsDao.findFirst().currency }
_currency.value = baseCurrency

ivyContext.dataBackupCompleted =
sharedPrefs.getBoolean(SharedPrefs.DATA_BACKUP_COMPLETED, false)

ioThread {
// try {
// bankIntegrationsLogic.sync() //sync bank integrations
Expand Down
165 changes: 165 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/serverstop/ServerStopScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package com.ivy.wallet.ui.serverstop

import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.ivy.design.l0_system.Orange
import com.ivy.design.l0_system.UI
import com.ivy.design.l0_system.style
import com.ivy.design.l1_buildingBlocks.ColumnRoot
import com.ivy.design.l1_buildingBlocks.SpacerVer
import com.ivy.design.l1_buildingBlocks.SpacerWeight
import com.ivy.wallet.ui.IvyWalletPreview
import com.ivy.wallet.ui.theme.components.IvyButton

@Composable
fun ServerStopScreen() {
val viewModel: ServerStopViewModel = viewModel()
val state by viewModel.state.collectAsState()
val context = LocalContext.current
UI(
state = state,
onBackup = {
viewModel.exportToZip(context)
}
)
}

@Composable
private fun UI(
state: ServerStopState,
onBackup: () -> Unit,
) {
ColumnRoot(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(horizontal = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
if (state.exportInProgress) {
Loading()
} else {
Content(
onBackup = onBackup
)
}
}
}

@Composable
private fun Content(
onBackup: () -> Unit
) {
SpacerVer(height = 24.dp)
Text(
text = "Backup your data",
style = UI.typo.h2.style(color = UI.colors.primary)
)
SpacerVer(height = 16.dp)
Text(
text = "We're shutting down the Ivy Cloud servers on Jan 1st, 2023. " +
"The cloud sync using Google account will no longer work!",
style = UI.typo.b1.style(color = UI.colors.red)
)
SpacerVer(height = 12.dp)
Text(
modifier = Modifier.fillMaxWidth(),
text = "The reason for that is because we're a FOSS (Free & Open Source Software) and " +
"it isn't profitable for us to pay our servers monthly bills. More importantly, " +
"we don't have a dedicated person to maintain them which is bad.",
style = UI.typo.b2.style(
color = UI.colors.pureInverse,
fontWeight = FontWeight.Normal,
)
)
SpacerVer(height = 12.dp)
Text(
modifier = Modifier.fillMaxWidth(),
text = "To keep your data safe in case of device change or app uninstall/clear data, " +
"you need to make manually export a backup file of Ivy Wallet.",
style = UI.typo.b2.style(
color = UI.colors.pureInverse,
fontWeight = FontWeight.Bold,
)
)
SpacerVer(height = 12.dp)
Text(
modifier = Modifier.fillMaxWidth(),
text = "To export a backup file:\n" +
"1) Click the arrow at top-right on the \"Home\" screen.\n" +
"2) Go to \"Settings\"\n" +
"3) Click \"Backup Data\"",
style = UI.typo.b2.style(
color = UI.colors.primary,
fontWeight = FontWeight.Bold,
)
)
SpacerVer(height = 12.dp)
Text(
modifier = Modifier.fillMaxWidth(),
text = "To restore your data on Ivy Wallet fresh install, " +
"you'll simply need to import the backup file that you've exported. " +
"We recommend making regular exports and keeping the backup file on Google Drive, " +
"OneDrive, DropBox or other safe cloud storage. Thank you for your understanding!",
style = UI.typo.b2.style(
color = UI.colors.pureInverse,
fontWeight = FontWeight.Normal,
)
)
SpacerVer(height = 24.dp)
IvyButton(text = "Export backup file") {
onBackup()
}
SpacerVer(height = 24.dp)
}

@Composable
private fun ColumnScope.Loading() {
SpacerWeight(weight = 1f)
Text(
text = "Exporting data...",
style = UI.typo.b1.style(
fontWeight = FontWeight.Bold,
color = Orange
)
)
SpacerWeight(weight = 1f)
}


// region Preview
@Preview
@Composable
private fun Preview() {
IvyWalletPreview {
UI(
state = ServerStopState(exportInProgress = false)
) {}
}
}

@Preview
@Composable
private fun PreviewLoading() {
IvyWalletPreview {
UI(
state = ServerStopState(exportInProgress = true)
) {}
}
}
// endregion
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.ivy.wallet.ui.serverstop

data class ServerStopState(
val exportInProgress: Boolean
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.ivy.wallet.ui.serverstop

import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ivy.frp.test.TestIdlingResource
import com.ivy.wallet.domain.deprecated.logic.zip.ExportZipLogic
import com.ivy.wallet.io.persistence.SharedPrefs
import com.ivy.wallet.ui.IvyWalletCtx
import com.ivy.wallet.ui.RootActivity
import com.ivy.wallet.utils.uiThread
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class ServerStopViewModel @Inject constructor(
private val ivyContext: IvyWalletCtx,
private val sharedPrefs: SharedPrefs,
private val exportZipLogic: ExportZipLogic,
) : ViewModel() {
private val exportInProgress = MutableStateFlow(false)

val state = exportInProgress.map { exportInProgress ->
ServerStopState(
exportInProgress = exportInProgress
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = ServerStopState(
exportInProgress = false
)
)

fun exportToZip(context: Context) {
ivyContext.createNewFile(
"Ivy-Wallet-backup.zip"
) { fileUri ->
viewModelScope.launch(Dispatchers.IO) {
TestIdlingResource.increment()

exportInProgress.value = true
exportZipLogic.exportToFile(context = context, zipFileUri = fileUri)
exportInProgress.value = false

sharedPrefs.putBoolean(SharedPrefs.DATA_BACKUP_COMPLETED, true)
ivyContext.dataBackupCompleted = true

uiThread {
(context as RootActivity).shareZipFile(
fileUri = fileUri
)
}

TestIdlingResource.decrement()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ class SettingsViewModel @Inject constructor(
exportZipLogic.exportToFile(context = context, zipFileUri = fileUri)
_progressState.value = false

sharedPrefs.putBoolean(SharedPrefs.DATA_BACKUP_COMPLETED, true)
ivyContext.dataBackupCompleted = true

uiThread {
(context as RootActivity).shareZipFile(
fileUri = fileUri
Expand Down

0 comments on commit c8032de

Please sign in to comment.