[#748][#749] Preferences for sync

Adds an option to enable/disable background sync, as well as an option to keep the screen on during sync

---------

Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
Carter Jernigan 2023-02-17 11:39:15 -05:00 committed by GitHub
parent e0d3bea3de
commit edaeda56da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 235 additions and 24 deletions

View File

@ -0,0 +1,26 @@
# Configure keep screen on setting - Because sync can take a long time, the app has a feature to keep the screen on until sync completes. The functionality to keep the screen on will apply to any screen while the app is open and syncing is actively in progress
1. Change the systemwide screen timeout in the Android Settings to something short, e.g. 15 seconds
1. Install the app
1. Launch the app
1. Get to the app's settings
1. Enable the "keep screen on while syncing" option
1. Assuming that sync will take a long time, leave the app open and do not touch the screen for more than the systemwide screen timeout duration
1. Verify that the screen does not turn off
1. Go to the settings and disable the "Keep screen on while syncing" option
1. Keeping the app on the screen, leave the device alone for more than the systemwide screen timeout
1. Verify that the screen does turn off
1. Wake the device
1. Turn the "Keep screen on while syncing" option back on
1. Return to the home screen
1. Leave the device alone until sync completes (this may take hours)
1. Verify when you return that the screen is off (the screen should turn off within the systemwide screen timeout after syncing completes)
# Disable background syncing
1. Install a debug build of the app and connect the device to a system with the Android developer tools installed
1. Perform a fresh install of the app
1. Go through the onboarding to get to the home screen
1. In the developer tools (App Inspection -> Background Task Inspector), verify that a periodic WorkManager job is scheduled or running
1. Go into the app's settings and disable the background sync option
1. In the developer tools, verify that no periodic WorkManager job is scheduled or running (e.g. it may be cancelled)
1. Go into the app's settings and re-enable the background sync option
1. In the developer tools, verify that a periodic WorkManager job is scheduled

View File

@ -45,6 +45,7 @@ class HomeTestSetup(
fun getDefaultContent() {
Home(
walletSnapshot,
isKeepScreenOnDuringSync = false,
emptyList(),
goScan = {
onScanCount.incrementAndGet()

View File

@ -55,7 +55,7 @@ class SettingsViewTest : UiTestPrerequisites() {
fun rescan() = runTest {
val testSetup = TestSetup(composeTestRule)
assertEquals(0, testSetup.getBackupCount())
assertEquals(0, testSetup.getRescanCount())
composeTestRule.onNodeWithText(getStringResource(R.string.settings_rescan)).also {
it.performClick()
@ -64,12 +64,40 @@ class SettingsViewTest : UiTestPrerequisites() {
assertEquals(1, testSetup.getRescanCount())
}
@Test
@MediumTest
fun toggle_background_sync() = runTest {
val testSetup = TestSetup(composeTestRule)
assertEquals(0, testSetup.getBackgroundSyncToggleCount())
composeTestRule.onNodeWithText(getStringResource(R.string.settings_enable_background_sync)).also {
it.performClick()
}
assertEquals(1, testSetup.getBackgroundSyncToggleCount())
}
@Test
@MediumTest
fun toggle_keep_screen_on() = runTest {
val testSetup = TestSetup(composeTestRule)
assertEquals(0, testSetup.getKeepScreenOnSyncToggleCount())
composeTestRule.onNodeWithText(getStringResource(R.string.settings_enable_keep_screen_on)).also {
it.performClick()
}
assertEquals(1, testSetup.getKeepScreenOnSyncToggleCount())
}
@Test
@MediumTest
fun toggle_analytics() = runTest {
val testSetup = TestSetup(composeTestRule)
assertEquals(0, testSetup.getBackupCount())
assertEquals(0, testSetup.getAnalyticsToggleCount())
composeTestRule.onNodeWithText(getStringResource(R.string.settings_enable_analytics)).also {
it.performClick()
@ -83,6 +111,8 @@ class SettingsViewTest : UiTestPrerequisites() {
private val onBackCount = AtomicInteger(0)
private val onBackupCount = AtomicInteger(0)
private val onRescanCount = AtomicInteger(0)
private val onBackgroundSyncChangedCount = AtomicInteger(0)
private val onKeepScreenOnChangedCount = AtomicInteger(0)
private val onAnalyticsChangedCount = AtomicInteger(0)
fun getOnBackCount(): Int {
@ -100,6 +130,16 @@ class SettingsViewTest : UiTestPrerequisites() {
return onRescanCount.get()
}
fun getBackgroundSyncToggleCount(): Int {
composeTestRule.waitForIdle()
return onBackgroundSyncChangedCount.get()
}
fun getKeepScreenOnSyncToggleCount(): Int {
composeTestRule.waitForIdle()
return onKeepScreenOnChangedCount.get()
}
fun getAnalyticsToggleCount(): Int {
composeTestRule.waitForIdle()
return onAnalyticsChangedCount.get()
@ -109,6 +149,8 @@ class SettingsViewTest : UiTestPrerequisites() {
composeTestRule.setContent {
ZcashTheme {
Settings(
isBackgroundSyncEnabled = true,
isKeepScreenOnDuringSyncEnabled = true,
isAnalyticsEnabled = true,
onBack = {
onBackCount.incrementAndGet()
@ -119,6 +161,12 @@ class SettingsViewTest : UiTestPrerequisites() {
onRescanWallet = {
onRescanCount.incrementAndGet()
},
onBackgroundSyncSettingsChanged = {
onBackgroundSyncChangedCount.incrementAndGet()
},
onIsKeepScreenOnDuringSyncSettingsChanged = {
onKeepScreenOnChangedCount.incrementAndGet()
},
onAnalyticsSettingsChanged = {
onAnalyticsChangedCount.incrementAndGet()
}

View File

@ -12,7 +12,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.NavHostController
import co.electriccoin.zcash.ui.common.BindCompLocalProvider
import co.electriccoin.zcash.ui.design.component.ConfigurationOverride
@ -20,12 +23,18 @@ import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.Override
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.screen.backup.WrapBackup
import co.electriccoin.zcash.ui.screen.home.viewmodel.HomeViewModel
import co.electriccoin.zcash.ui.screen.home.viewmodel.SecretState
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.onboarding.WrapOnboarding
import co.electriccoin.zcash.ui.screen.warning.WrapNotEnoughSpace
import co.electriccoin.zcash.ui.screen.warning.viewmodel.StorageCheckViewModel
import co.electriccoin.zcash.work.WorkIds
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@ -47,6 +56,8 @@ class MainActivity : ComponentActivity() {
setupSplashScreen()
setupUiContent()
monitorForBackgroundSync()
}
private fun setupSplashScreen() {
@ -116,6 +127,30 @@ class MainActivity : ComponentActivity() {
}
}
private fun monitorForBackgroundSync() {
val isEnableBackgroundSyncFlow = run {
val homeViewModel by viewModels<HomeViewModel>()
val isSecretReadyFlow = walletViewModel.secretState.map { it is SecretState.Ready }
val isBackgroundSyncEnabledFlow = homeViewModel.isBackgroundSyncEnabled.filterNotNull()
isSecretReadyFlow.combine(isBackgroundSyncEnabledFlow) { isSecretReady, isBackgroundSyncEnabled ->
isSecretReady && isBackgroundSyncEnabled
}
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
isEnableBackgroundSyncFlow.collect { isEnableBackgroundSync ->
if (isEnableBackgroundSync) {
WorkIds.enableBackgroundSynchronization(application)
} else {
WorkIds.disableBackgroundSynchronization(application)
}
}
}
}
}
companion object {
@VisibleForTesting
internal val SPLASH_SCREEN_DELAY = 0.seconds

View File

@ -13,6 +13,10 @@ object StandardPreferenceKeys {
// Default to true until https://github.com/zcash/secant-android-wallet/issues/304
val IS_ANALYTICS_ENABLED = BooleanPreferenceDefault(Key("is_analytics_enabled"), true)
val IS_BACKGROUND_SYNC_ENABLED = BooleanPreferenceDefault(Key("is_background_sync_enabled"), true)
val IS_KEEP_SCREEN_ON_DURING_SYNC = BooleanPreferenceDefault(Key("is_keep_screen_on_during_sync"), true)
/**
* The fiat currency that the user prefers.
*/

View File

@ -14,6 +14,7 @@ import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.screen.home.view.Home
import co.electriccoin.zcash.ui.screen.home.viewmodel.CheckUpdateViewModel
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
import co.electriccoin.zcash.ui.screen.update.AppUpdateCheckerImp
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
@ -53,9 +54,12 @@ internal fun WrapHome(
}
val walletViewModel by activity.viewModels<WalletViewModel>()
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
val settingsViewModel by activity.viewModels<SettingsViewModel>()
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
if (null == walletSnapshot) {
// Display loading indicator
} else {
@ -71,6 +75,7 @@ internal fun WrapHome(
Home(
walletSnapshot,
isKeepScreenOnDuringSync = isKeepScreenOnWhileSyncing,
transactionSnapshot,
goScan = goScan,
goRequest = goRequest,

View File

@ -42,10 +42,12 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
import cash.z.ecc.android.sdk.model.PercentDecimal
import co.electriccoin.zcash.crash.android.GlobalCrashReporter
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.DisableScreenTimeout
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.BodyWithFiatCurrencySymbol
@ -67,6 +69,7 @@ fun ComposablePreview() {
GradientSurface {
Home(
WalletSnapshotFixture.new(),
isKeepScreenOnDuringSync = false,
emptyList(),
goScan = {},
goProfile = {},
@ -85,6 +88,7 @@ fun ComposablePreview() {
@Composable
fun Home(
walletSnapshot: WalletSnapshot,
isKeepScreenOnDuringSync: Boolean?,
transactionHistory: List<CommonTransaction>,
goScan: () -> Unit,
goProfile: () -> Unit,
@ -100,6 +104,7 @@ fun Home(
HomeMainContent(
paddingValues,
walletSnapshot,
isKeepScreenOnDuringSync = isKeepScreenOnDuringSync,
transactionHistory,
goScan = goScan,
goProfile = goProfile,
@ -171,6 +176,7 @@ private fun DebugMenu(
private fun HomeMainContent(
paddingValues: PaddingValues,
walletSnapshot: WalletSnapshot,
isKeepScreenOnDuringSync: Boolean?,
transactionHistory: List<CommonTransaction>,
goScan: () -> Unit,
goProfile: () -> Unit,
@ -212,9 +218,20 @@ private fun HomeMainContent(
TertiaryButton(onClick = goRequest, text = stringResource(R.string.home_button_request))
History(transactionHistory)
if (isKeepScreenOnDuringSync == true && isSyncing(walletSnapshot.status)) {
DisableScreenTimeout()
}
}
}
private fun isSyncing(status: Synchronizer.Status): Boolean {
return status == Synchronizer.Status.DOWNLOADING ||
status == Synchronizer.Status.VALIDATING ||
status == Synchronizer.Status.SCANNING ||
status == Synchronizer.Status.ENHANCING
}
@Composable
@Suppress("LongMethod", "MagicNumber")
private fun Status(

View File

@ -0,0 +1,24 @@
package co.electriccoin.zcash.ui.screen.home.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT
import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
import co.electriccoin.zcash.ui.preference.StandardPreferenceSingleton
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
class HomeViewModel(application: Application) : AndroidViewModel(application) {
/**
* A flow of whether background sync is enabled
*/
val isBackgroundSyncEnabled: StateFlow<Boolean?> = flow {
val preferenceProvider = StandardPreferenceSingleton.getInstance(application)
emitAll(StandardPreferenceKeys.IS_BACKGROUND_SYNC_ENABLED.observe(preferenceProvider))
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT.inWholeMilliseconds), null)
}

View File

@ -32,7 +32,6 @@ import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
import co.electriccoin.zcash.ui.preference.StandardPreferenceSingleton
import co.electriccoin.zcash.ui.screen.home.model.CommonTransaction
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
import co.electriccoin.zcash.work.WorkIds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
@ -151,7 +150,7 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
)
// This is not the right API, because the transaction list could be very long and might need UI filtering
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
val transactionSnapshot: StateFlow<List<CommonTransaction>> = synchronizer
.flatMapLatest {
if (null == it) {
@ -205,8 +204,6 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
persistWalletMutex.withLock {
EncryptedPreferenceKeys.PERSISTABLE_WALLET.putValue(preferenceProvider, persistableWallet)
}
WorkIds.enableBackgroundSynchronization(application)
}
}

View File

@ -33,18 +33,29 @@ private fun WrapSettings(
val settingsViewModel by activity.viewModels<SettingsViewModel>()
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
val isBackgroundSyncEnabled = settingsViewModel.isBackgroundSync.collectAsStateWithLifecycle().value
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
val isAnalyticsEnabled = settingsViewModel.isAnalyticsEnabled.collectAsStateWithLifecycle().value
if (null == synchronizer || null == isAnalyticsEnabled) {
@Suppress("ComplexCondition")
if (null == synchronizer || null == isAnalyticsEnabled || null == isBackgroundSyncEnabled || null == isKeepScreenOnWhileSyncing) {
// Display loading indicator
} else {
Settings(
isAnalyticsEnabled,
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnWhileSyncing,
isAnalyticsEnabled = isAnalyticsEnabled,
onBack = goBack,
onBackupWallet = goWalletBackup,
onRescanWallet = {
walletViewModel.rescanBlockchain()
},
onBackgroundSyncSettingsChanged = {
settingsViewModel.setBackgroundSyncEnabled(it)
},
onIsKeepScreenOnDuringSyncSettingsChanged = {
settingsViewModel.setKeepScreenOnWhileSyncing(it)
},
onAnalyticsSettingsChanged = {
settingsViewModel.setAnalyticsEnabled(it)
}

View File

@ -39,10 +39,14 @@ fun PreviewSettings() {
ZcashTheme(darkTheme = true) {
GradientSurface {
Settings(
isBackgroundSyncEnabled = true,
isKeepScreenOnDuringSyncEnabled = true,
isAnalyticsEnabled = true,
onBack = {},
onBackupWallet = {},
onRescanWallet = {},
onBackgroundSyncSettingsChanged = {},
onIsKeepScreenOnDuringSyncSettingsChanged = {},
onAnalyticsSettingsChanged = {}
)
}
@ -53,10 +57,14 @@ fun PreviewSettings() {
@Composable
@Suppress("LongParameterList")
fun Settings(
isBackgroundSyncEnabled: Boolean,
isKeepScreenOnDuringSyncEnabled: Boolean,
isAnalyticsEnabled: Boolean,
onBack: () -> Unit,
onBackupWallet: () -> Unit,
onRescanWallet: () -> Unit,
onBackgroundSyncSettingsChanged: (Boolean) -> Unit,
onIsKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
onAnalyticsSettingsChanged: (Boolean) -> Unit
) {
Scaffold(topBar = {
@ -64,9 +72,13 @@ fun Settings(
}) { paddingValues ->
SettingsMainContent(
paddingValues,
isAnalyticsEnabled,
isBackgroundSyncEnabled = isBackgroundSyncEnabled,
isKeepScreenOnDuringSyncEnabled = isKeepScreenOnDuringSyncEnabled,
isAnalyticsEnabled = isAnalyticsEnabled,
onBackupWallet = onBackupWallet,
onRescanWallet = onRescanWallet,
onBackgroundSyncSettingsChanged = onBackgroundSyncSettingsChanged,
onIsKeepScreenOnDuringSyncSettingsChanged = onIsKeepScreenOnDuringSyncSettingsChanged,
onAnalyticsSettingsChanged = onAnalyticsSettingsChanged
)
}
@ -94,9 +106,13 @@ private fun SettingsTopAppBar(onBack: () -> Unit) {
@Suppress("LongParameterList")
private fun SettingsMainContent(
paddingValues: PaddingValues,
isBackgroundSyncEnabled: Boolean,
isKeepScreenOnDuringSyncEnabled: Boolean,
isAnalyticsEnabled: Boolean,
onBackupWallet: () -> Unit,
onRescanWallet: () -> Unit,
onBackgroundSyncSettingsChanged: (Boolean) -> Unit,
onIsKeepScreenOnDuringSyncSettingsChanged: (Boolean) -> Unit,
onAnalyticsSettingsChanged: (Boolean) -> Unit
) {
Column(
@ -104,9 +120,17 @@ private fun SettingsMainContent(
.padding(top = paddingValues.calculateTopPadding())
) {
PrimaryButton(onClick = onBackupWallet, text = stringResource(id = R.string.settings_backup))
// We have decided to not include this in settings; see overflow debug menu instead
// DangerousButton(onClick = onWipeWallet, text = stringResource(id = R.string.settings_wipe))
TertiaryButton(onClick = onRescanWallet, text = stringResource(id = R.string.settings_rescan))
SwitchWithLabel(
label = stringResource(id = R.string.settings_enable_background_sync),
state = isBackgroundSyncEnabled,
onStateChange = { onBackgroundSyncSettingsChanged(!isBackgroundSyncEnabled) }
)
SwitchWithLabel(
label = stringResource(id = R.string.settings_enable_keep_screen_on),
state = isKeepScreenOnDuringSyncEnabled,
onStateChange = { onIsKeepScreenOnDuringSyncSettingsChanged(!isKeepScreenOnDuringSyncEnabled) }
)
SwitchWithLabel(
label = stringResource(id = R.string.settings_enable_analytics),
state = isAnalyticsEnabled,

View File

@ -3,6 +3,7 @@ package co.electriccoin.zcash.ui.screen.settings.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import co.electriccoin.zcash.preference.model.entry.BooleanPreferenceDefault
import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT
import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
import co.electriccoin.zcash.ui.preference.StandardPreferenceSingleton
@ -19,17 +20,34 @@ import kotlinx.coroutines.sync.withLock
class SettingsViewModel(application: Application) : AndroidViewModel(application) {
private val mutex = Mutex()
val isAnalyticsEnabled: StateFlow<Boolean?> = flow<Boolean?> {
val preferenceProvider = StandardPreferenceSingleton.getInstance(application)
emitAll(StandardPreferenceKeys.IS_ANALYTICS_ENABLED.observe(preferenceProvider))
val isAnalyticsEnabled: StateFlow<Boolean?> = booleanStateFlow(StandardPreferenceKeys.IS_ANALYTICS_ENABLED)
val isBackgroundSync: StateFlow<Boolean?> = booleanStateFlow(StandardPreferenceKeys.IS_BACKGROUND_SYNC_ENABLED)
val isKeepScreenOnWhileSyncing: StateFlow<Boolean?> = booleanStateFlow(StandardPreferenceKeys.IS_KEEP_SCREEN_ON_DURING_SYNC)
private fun booleanStateFlow(default: BooleanPreferenceDefault): StateFlow<Boolean?> = flow<Boolean?> {
val preferenceProvider = StandardPreferenceSingleton.getInstance(getApplication())
emitAll(default.observe(preferenceProvider))
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT), null)
fun setAnalyticsEnabled(enabled: Boolean) {
setBooleanPreference(StandardPreferenceKeys.IS_ANALYTICS_ENABLED, enabled)
}
fun setBackgroundSyncEnabled(enabled: Boolean) {
setBooleanPreference(StandardPreferenceKeys.IS_BACKGROUND_SYNC_ENABLED, enabled)
}
fun setKeepScreenOnWhileSyncing(enabled: Boolean) {
setBooleanPreference(StandardPreferenceKeys.IS_KEEP_SCREEN_ON_DURING_SYNC, enabled)
}
private fun setBooleanPreference(default: BooleanPreferenceDefault, newState: Boolean) {
viewModelScope.launch {
val prefs = StandardPreferenceSingleton.getInstance(getApplication())
mutex.withLock {
// Note that the Application object observes this and performs the actual side effects
StandardPreferenceKeys.IS_ANALYTICS_ENABLED.putValue(prefs, enabled)
default.putValue(prefs, newState)
}
}
}

View File

@ -7,13 +7,6 @@ import androidx.work.WorkManager
object WorkIds {
const val WORK_ID_BACKGROUND_SYNC = "co.electriccoin.zcash.background_sync"
/*
* For now, sync is always enabled. In the future, we can consider whether a preference
* is a good idea.
*
* Also note that if we ever change the sync interval period, this code won't re-run on
* existing installations unless we make changes to call this during app startup.
*/
fun enableBackgroundSynchronization(context: Context) {
val workManager = WorkManager.getInstance(context)
@ -23,4 +16,10 @@ object WorkIds {
SyncWorker.newWorkRequest()
)
}
fun disableBackgroundSynchronization(context: Context) {
val workManager = WorkManager.getInstance(context)
workManager.cancelUniqueWork(WORK_ID_BACKGROUND_SYNC)
}
}

View File

@ -6,6 +6,8 @@
<string name="settings_wipe">Wipe Wallet Data</string>
<string name="settings_rescan">Rescan Blockchain</string>
<string name="settings_enable_background_sync">Background sync</string>
<string name="settings_enable_keep_screen_on">Keep screen on during sync</string>
<string name="settings_enable_analytics">Report crashes</string>
</resources>