Skip to content

Commit d33a5c4

Browse files
authored
Merge pull request #14725 from woocommerce/issue/woomob-1446-woo-poslocal-catalog-save-downloadovercellular-preference-in
[WOOMOB-1446] Implement cellular data preference for WooPos local catalog sync
2 parents de66262 + e54cf5c commit d33a5c4

File tree

4 files changed

+94
-41
lines changed

4 files changed

+94
-41
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosLocalCatalogSyncScheduler.kt

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import androidx.work.PeriodicWorkRequestBuilder
1111
import androidx.work.WorkInfo
1212
import androidx.work.WorkManager
1313
import com.woocommerce.android.ui.woopos.common.util.WooPosLogWrapper
14+
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
1415
import dagger.hilt.android.qualifiers.ApplicationContext
16+
import kotlinx.coroutines.CoroutineScope
17+
import kotlinx.coroutines.flow.first
18+
import kotlinx.coroutines.launch
1519
import java.util.Calendar
1620
import java.util.concurrent.TimeUnit
1721
import javax.inject.Inject
@@ -21,6 +25,8 @@ import javax.inject.Singleton
2125
class WooPosLocalCatalogSyncScheduler @Inject constructor(
2226
@ApplicationContext private val context: Context,
2327
private val logger: WooPosLogWrapper,
28+
private val preferencesRepository: WooPosPreferencesRepository,
29+
private val applicationScope: CoroutineScope,
2430
) {
2531

2632
private companion object {
@@ -33,45 +39,51 @@ class WooPosLocalCatalogSyncScheduler @Inject constructor(
3339
private val workManager by lazy { WorkManager.getInstance(context) }
3440

3541
fun schedulePeriodicFullCatalogSync() {
36-
val syncWorkRequest = PeriodicWorkRequestBuilder<WooPosLocalCatalogSyncWorker>(
37-
REFRESH_INTERVAL_HOURS,
38-
TimeUnit.HOURS
39-
)
40-
.setInitialDelay(calculateDelayToNight(), TimeUnit.MILLISECONDS)
41-
.setConstraints(getConstraints())
42-
.setBackoffCriteria(
43-
BackoffPolicy.EXPONENTIAL,
44-
1,
45-
TimeUnit.MINUTES
42+
applicationScope.launch {
43+
val constraints = getConstraintsBasedOnPreference()
44+
val syncWorkRequest = PeriodicWorkRequestBuilder<WooPosLocalCatalogSyncWorker>(
45+
REFRESH_INTERVAL_HOURS,
46+
TimeUnit.HOURS
47+
)
48+
.setInitialDelay(calculateDelayToNight(), TimeUnit.MILLISECONDS)
49+
.setConstraints(constraints)
50+
.setBackoffCriteria(
51+
BackoffPolicy.EXPONENTIAL,
52+
1,
53+
TimeUnit.MINUTES
54+
)
55+
.build()
56+
57+
workManager.enqueueUniquePeriodicWork(
58+
WooPosLocalCatalogSyncWorker.WORK_NAME,
59+
ExistingPeriodicWorkPolicy.UPDATE,
60+
syncWorkRequest
4661
)
47-
.build()
48-
49-
workManager.enqueueUniquePeriodicWork(
50-
WooPosLocalCatalogSyncWorker.WORK_NAME,
51-
ExistingPeriodicWorkPolicy.KEEP,
52-
syncWorkRequest
53-
)
5462

55-
logger.d("POS local catalog full sync scheduled.")
63+
logger.d("POS local catalog full sync scheduled.")
64+
}
5665
}
5766

5867
fun triggerManualFullCatalogSync() {
59-
val oneTimeWorkRequest = OneTimeWorkRequestBuilder<WooPosLocalCatalogSyncWorker>()
60-
.setConstraints(getConstraints())
61-
.setBackoffCriteria(
62-
BackoffPolicy.EXPONENTIAL,
63-
1,
64-
TimeUnit.MINUTES
68+
applicationScope.launch {
69+
val constraints = getConstraintsBasedOnPreference()
70+
val oneTimeWorkRequest = OneTimeWorkRequestBuilder<WooPosLocalCatalogSyncWorker>()
71+
.setConstraints(constraints)
72+
.setBackoffCriteria(
73+
BackoffPolicy.EXPONENTIAL,
74+
1,
75+
TimeUnit.MINUTES
76+
)
77+
.build()
78+
79+
workManager.enqueueUniqueWork(
80+
ONE_TIME_WORK_NAME,
81+
ExistingWorkPolicy.REPLACE,
82+
oneTimeWorkRequest
6583
)
66-
.build()
67-
68-
workManager.enqueueUniqueWork(
69-
ONE_TIME_WORK_NAME,
70-
ExistingWorkPolicy.REPLACE,
71-
oneTimeWorkRequest
72-
)
7384

74-
logger.d("Manual POS local catalog sync triggered")
85+
logger.d("Manual POS local catalog sync triggered")
86+
}
7587
}
7688

7789
fun isPeriodicWorkRunning(): Boolean {
@@ -86,9 +98,23 @@ class WooPosLocalCatalogSyncScheduler @Inject constructor(
8698
return oneTimeWork.any { it.state == WorkInfo.State.RUNNING }
8799
}
88100

89-
private fun getConstraints(): Constraints {
101+
fun updateWorkConstraints() {
102+
logger.d("Updating work constraints based on cellular preference change")
103+
cancelPeriodicWork()
104+
schedulePeriodicFullCatalogSync()
105+
}
106+
107+
fun cancelPeriodicWork() {
108+
workManager.cancelUniqueWork(WooPosLocalCatalogSyncWorker.WORK_NAME)
109+
logger.d("Cancelled periodic work for constraint update")
110+
}
111+
112+
private suspend fun getConstraintsBasedOnPreference(): Constraints {
113+
val allowCellular = preferencesRepository.allowCellularDataUpdate.first()
114+
val networkType = if (allowCellular) NetworkType.NOT_ROAMING else NetworkType.UNMETERED
115+
90116
return Constraints.Builder()
91-
.setRequiredNetworkType(NetworkType.CONNECTED)
117+
.setRequiredNetworkType(networkType)
92118
.setRequiresBatteryNotLow(true)
93119
.build()
94120
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/details/localcatalog/WooPosSettingsLocalCatalogScreen.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fun WooPosSettingsLocalCatalogScreen(
5555
@Composable
5656
private fun WooPosSettingsLocalCatalogScreen(
5757
state: WooPosSettingsLocalCatalogState,
58-
onToggleCellularData: () -> Unit,
58+
onToggleCellularData: (Boolean) -> Unit,
5959
onRefreshCatalog: () -> Unit,
6060
modifier: Modifier = Modifier
6161
) {
@@ -144,7 +144,7 @@ private fun CatalogStatusSection(
144144
@Composable
145145
private fun SettingsSection(
146146
allowCellularDataUpdate: Boolean,
147-
onToggleCellularData: () -> Unit,
147+
onToggleCellularData: (Boolean) -> Unit,
148148
isLoading: Boolean
149149
) {
150150
Column(
@@ -181,7 +181,7 @@ private fun SettingsSection(
181181

182182
Switch(
183183
checked = allowCellularDataUpdate,
184-
onCheckedChange = { onToggleCellularData() },
184+
onCheckedChange = { onToggleCellularData(it) },
185185
enabled = !isLoading,
186186
colors = SwitchDefaults.colors(
187187
checkedThumbColor = MaterialTheme.colorScheme.primary,

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/settings/details/localcatalog/WooPosSettingsLocalCatalogViewModel.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import androidx.lifecycle.viewModelScope
55
import com.woocommerce.android.tools.SelectedSite
66
import com.woocommerce.android.ui.woopos.localcatalog.PosLocalCatalogSyncResult
77
import com.woocommerce.android.ui.woopos.localcatalog.WooPosLocalCatalogSyncRepository
8+
import com.woocommerce.android.ui.woopos.localcatalog.WooPosLocalCatalogSyncScheduler
9+
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
810
import com.woocommerce.android.ui.woopos.util.datastore.WooPosSyncTimestampManager
911
import com.woocommerce.android.ui.woopos.util.format.WooPosDateFormatter
1012
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -21,12 +23,16 @@ class WooPosSettingsLocalCatalogViewModel @Inject constructor(
2123
private val localCatalogSyncRepository: WooPosLocalCatalogSyncRepository,
2224
private val selectedSite: SelectedSite,
2325
private val dateFormatter: WooPosDateFormatter,
26+
private val preferencesRepository: WooPosPreferencesRepository,
27+
private val syncScheduler: WooPosLocalCatalogSyncScheduler,
2428
) : ViewModel() {
2529
private val _state = MutableStateFlow(WooPosSettingsLocalCatalogState())
2630
val state: StateFlow<WooPosSettingsLocalCatalogState> = _state.asStateFlow()
2731

2832
init {
2933
loadCatalogStatus()
34+
35+
listenToCellularDataUpdateValue()
3036
}
3137

3238
private fun loadCatalogStatus() {
@@ -53,12 +59,20 @@ class WooPosSettingsLocalCatalogViewModel @Inject constructor(
5359
}
5460
}
5561

56-
fun toggleCellularDataUpdate() {
62+
private fun listenToCellularDataUpdateValue() {
5763
viewModelScope.launch {
58-
_state.update {
59-
it.copy(allowCellularDataUpdate = !it.allowCellularDataUpdate)
64+
preferencesRepository.allowCellularDataUpdate.collect { allowCellularDataUpdate ->
65+
_state.update {
66+
it.copy(allowCellularDataUpdate = allowCellularDataUpdate)
67+
}
6068
}
61-
// TBD local catalog: Save preference to shared preferences or data store
69+
}
70+
}
71+
72+
fun toggleCellularDataUpdate(newValue: Boolean) {
73+
viewModelScope.launch {
74+
preferencesRepository.setAllowCellularDataUpdate(newValue)
75+
syncScheduler.updateWorkConstraints()
6276
}
6377
}
6478

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosPreferencesRepository.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class WooPosPreferencesRepository @Inject constructor(
1717
private val recentProductSearchesSiteSpecificKey = buildSiteSpecificKey(RECENT_PRODUCT_SEARCHES_KEY)
1818
private val recentCouponSearchesSiteSpecificKey = buildSiteSpecificKey(RECENT_COUPON_SEARCHES_KEY)
1919
private val wasOpenedOnceKey = booleanPreferencesKey(POS_WAS_OPENED_ONCE_KEY)
20+
private val allowCellularDataUpdateKey = booleanPreferencesKey(ALLOW_FULL_SYNC_ON_CELLULAR_DATA_KEY)
2021

2122
val recentProductSearches: Flow<List<String>> = dataStore.data
2223
.map { preferences ->
@@ -35,6 +36,11 @@ class WooPosPreferencesRepository @Inject constructor(
3536
preferences[wasOpenedOnceKey] ?: false
3637
}
3738

39+
val allowCellularDataUpdate: Flow<Boolean> = dataStore.data
40+
.map { preferences ->
41+
preferences[allowCellularDataUpdateKey] ?: true
42+
}
43+
3844
suspend fun addRecentProductSearch(search: String) {
3945
dataStore.edit { preferences ->
4046
val currentSearches = preferences[recentProductSearchesSiteSpecificKey]?.let {
@@ -69,13 +75,20 @@ class WooPosPreferencesRepository @Inject constructor(
6975
}
7076
}
7177

78+
suspend fun setAllowCellularDataUpdate(allow: Boolean) {
79+
dataStore.edit { preferences ->
80+
preferences[allowCellularDataUpdateKey] = allow
81+
}
82+
}
83+
7284
private fun buildSiteSpecificKey(key: String): Preferences.Key<String> =
7385
stringPreferencesKey("${selectedSite.getOrNull()?.siteId}-$key")
7486

7587
private companion object {
7688
const val RECENT_PRODUCT_SEARCHES_KEY = "recent_product_searches_key"
7789
const val RECENT_COUPON_SEARCHES_KEY = "recent_coupon_searches_key"
7890
const val POS_WAS_OPENED_ONCE_KEY = "pos_was_opened_once_key"
91+
const val ALLOW_FULL_SYNC_ON_CELLULAR_DATA_KEY = "allow_full_sync_on_cellular_data_key"
7992

8093
const val MAX_RECENT_SEARCHES_COUNT = 10
8194
}

0 commit comments

Comments
 (0)