Skip to content

Commit 62818d2

Browse files
committed
fix: make paykit flag local only
1 parent cb84239 commit 62818d2

12 files changed

Lines changed: 67 additions & 74 deletions

File tree

app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ android {
164164
buildConfigField("boolean", "TREZOR_BRIDGE", trezorBridgeEnv)
165165
buildConfigField("String", "TREZOR_BRIDGE_URL", "\"$trezorBridgeUrlEnv\"")
166166
buildConfigField("boolean", "GEO", System.getenv("GEO")?.toBoolean()?.toString() ?: "true")
167-
buildConfigField("boolean", "PAYKIT_UI_DISABLED", System.getenv("PAYKIT_UI_DISABLED")?.toBoolean()?.toString() ?: "false")
167+
buildConfigField("boolean", "FEATURE_PAYKIT_UI_DISABLED", System.getenv("PAYKIT_UI_DISABLED")?.toBoolean()?.toString() ?: "false")
168168
buildConfigField("String", "LOCALES", "\"${bcp47Locales.joinToString(",")}\"")
169169
}
170170

app/src/main/java/to/bitkit/data/SettingsStore.kt

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ package to.bitkit.data
33
import android.content.Context
44
import androidx.datastore.core.DataStore
55
import androidx.datastore.dataStore
6+
import androidx.datastore.preferences.core.Preferences
7+
import androidx.datastore.preferences.core.booleanPreferencesKey
8+
import androidx.datastore.preferences.core.edit
9+
import androidx.datastore.preferences.preferencesDataStore
610
import dagger.hilt.android.qualifiers.ApplicationContext
711
import kotlinx.coroutines.flow.Flow
12+
import kotlinx.coroutines.flow.map
813
import kotlinx.serialization.Serializable
914
import to.bitkit.data.serializers.SettingsSerializer
1015
import to.bitkit.env.Env
@@ -16,7 +21,6 @@ import to.bitkit.models.SettingsBackupV1
1621
import to.bitkit.models.Suggestion
1722
import to.bitkit.models.TransactionSpeed
1823
import to.bitkit.utils.Logger
19-
import to.bitkit.utils.PaykitFeatureFlags
2024
import javax.inject.Inject
2125
import javax.inject.Singleton
2226

@@ -25,26 +29,25 @@ private val Context.settingsDataStore: DataStore<SettingsData> by dataStore(
2529
serializer = SettingsSerializer,
2630
)
2731

32+
private val Context.localSettingsDataStore: DataStore<Preferences> by preferencesDataStore("local_settings")
33+
2834
@Singleton
2935
class SettingsStore @Inject constructor(
3036
@ApplicationContext private val context: Context,
3137
) {
3238
private val store = context.settingsDataStore
39+
private val localStore = context.localSettingsDataStore
3340

3441
val data: Flow<SettingsData> = store.data
42+
val isPaykitEnabled: Flow<Boolean> = localStore.data.map { it[PAYKIT_ENABLED_KEY] ?: false }
3543

3644
@Volatile
3745
var restoredMonitoredTypesFromBackup: Boolean = false
3846
private set
3947

4048
suspend fun restoreFromBackup(payload: SettingsBackupV1) =
4149
runCatching {
42-
val restored = payload.settings.resetPin()
43-
val data = if (PaykitFeatureFlags.isUiEnabled(restored) || !restored.hasPaykitState()) {
44-
restored
45-
} else {
46-
restored.paykitDisabled(markPublicCleanupPending = restored.hasPublicPaykitPublicationState())
47-
}
50+
val data = payload.settings.resetPin()
4851
store.updateData { data }
4952

5053
val monitored = data.addressTypesToMonitor
@@ -59,6 +62,10 @@ class SettingsStore @Inject constructor(
5962
store.updateData(transform)
6063
}
6164

65+
suspend fun setIsPaykitEnabled(value: Boolean) {
66+
localStore.edit { it[PAYKIT_ENABLED_KEY] = value }
67+
}
68+
6269
suspend fun addLastUsedTag(newTag: String) {
6370
store.updateData { currentSettings ->
6471
val combinedTags = (listOf(newTag) + currentSettings.lastUsedTags).distinct()
@@ -82,13 +89,15 @@ class SettingsStore @Inject constructor(
8289

8390
suspend fun reset() {
8491
store.updateData { SettingsData() }
92+
localStore.edit { it.clear() }
8593
restoredMonitoredTypesFromBackup = false
8694
Logger.info("Deleted all user settings data.")
8795
}
8896

8997
companion object {
9098
private const val TAG = "SettingsStore"
9199
private const val MAX_LAST_USED_TAGS = 10
100+
private val PAYKIT_ENABLED_KEY = booleanPreferencesKey("paykit_enabled")
92101
}
93102
}
94103

@@ -106,7 +115,6 @@ data class SettingsData(
106115
val hasSeenShopIntro: Boolean = false,
107116
val hasSeenProfileIntro: Boolean = false,
108117
val hasSeenContactsIntro: Boolean = false,
109-
val isPaykitEnabled: Boolean = false,
110118
val hasConfirmedPublicPaykitEndpoints: Boolean = false,
111119
val sharesPublicPaykitEndpoints: Boolean = false,
112120
val sharesPrivatePaykitEndpoints: Boolean = false,
@@ -166,12 +174,10 @@ fun SettingsData.hasPublicPaykitPublicationState(): Boolean =
166174
publicPaykitBolt11ExpiresAtMillis > 0L
167175

168176
fun SettingsData.hasPaykitState(): Boolean =
169-
isPaykitEnabled ||
170-
hasPublicPaykitPublicationState() ||
177+
hasPublicPaykitPublicationState() ||
171178
sharesPrivatePaykitEndpoints
172179

173180
fun SettingsData.paykitDisabled(markPublicCleanupPending: Boolean = false) = copy(
174-
isPaykitEnabled = false,
175181
hasConfirmedPublicPaykitEndpoints = false,
176182
sharesPublicPaykitEndpoints = false,
177183
sharesPrivatePaykitEndpoints = false,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package to.bitkit.flags
2+
3+
import to.bitkit.BuildConfig
4+
5+
object PaykitFeatureFlags {
6+
const val isUiAvailable = !BuildConfig.FEATURE_PAYKIT_UI_DISABLED
7+
8+
fun isUiEnabled(localFlagEnabled: Boolean): Boolean {
9+
return isUiAvailable && localFlagEnabled
10+
}
11+
}

app/src/main/java/to/bitkit/repositories/BackupRepo.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ import to.bitkit.models.WidgetsBackupV1
4949
import to.bitkit.services.LightningService
5050
import to.bitkit.ui.shared.toast.ToastEventBus
5151
import to.bitkit.utils.Logger
52-
import to.bitkit.utils.PaykitFeatureFlags
5352
import to.bitkit.utils.jsonLogOf
5453
import java.util.concurrent.ConcurrentHashMap
5554
import javax.inject.Inject
@@ -626,10 +625,6 @@ class BackupRepo @Inject constructor(
626625
addressReservationRepo.restoreBackup(parsed.privatePaykitHighestReservedReceiveIndexByAddressType).getOrThrow()
627626
val privateRepo = privatePaykitRepo.get()
628627
privateRepo.restoreBackup(parsed.privatePaykitContactLinks).getOrThrow()
629-
val isPaykitEnabled = PaykitFeatureFlags.isUiEnabled(settingsStore.data.first())
630-
if (!isPaykitEnabled && !parsed.privatePaykitContactLinks.isNullOrEmpty()) {
631-
privateRepo.setContactSharingCleanupPending(true).getOrThrow()
632-
}
633628
addressReservationRepo.reconcileReservedIndexesWithLdk().getOrThrow()
634629
Logger.debug("Restored ${parsed.transfers.size} transfers", context = TAG)
635630
return parsed.createdAt

app/src/main/java/to/bitkit/ui/screens/settings/DevSettingsScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import androidx.navigation.NavController
2222
import org.lightningdevkit.ldknode.Network
2323
import to.bitkit.R
2424
import to.bitkit.env.Env
25+
import to.bitkit.flags.PaykitFeatureFlags
2526
import to.bitkit.models.Toast
2627
import to.bitkit.ui.Routes
2728
import to.bitkit.ui.activityListViewModel
@@ -36,7 +37,6 @@ import to.bitkit.ui.scaffold.DrawerNavIcon
3637
import to.bitkit.ui.scaffold.ScreenColumn
3738
import to.bitkit.ui.settingsViewModel
3839
import to.bitkit.ui.shared.util.shareZipFile
39-
import to.bitkit.utils.PaykitFeatureFlags
4040
import to.bitkit.viewmodels.DevSettingsViewModel
4141

4242
@Composable

app/src/main/java/to/bitkit/utils/PaykitFeatureFlags.kt

Lines changed: 0 additions & 12 deletions
This file was deleted.

app/src/main/java/to/bitkit/viewmodels/ActivityListViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ import to.bitkit.data.SettingsStore
2929
import to.bitkit.di.BgDispatcher
3030
import to.bitkit.ext.isReplacedSentTransaction
3131
import to.bitkit.ext.isTransfer
32+
import to.bitkit.flags.PaykitFeatureFlags
3233
import to.bitkit.models.PubkyProfile
3334
import to.bitkit.repositories.ActivityRepo
3435
import to.bitkit.repositories.PubkyRepo
3536
import to.bitkit.ui.screens.wallets.activity.components.ActivityTab
3637
import to.bitkit.utils.Logger
37-
import to.bitkit.utils.PaykitFeatureFlags
3838
import javax.inject.Inject
3939

4040
@Suppress("TooManyFunctions")
@@ -60,7 +60,7 @@ class ActivityListViewModel @Inject constructor(
6060
val contacts: StateFlow<ImmutableList<PubkyProfile>> =
6161
combine(
6262
pubkyRepo.contacts,
63-
settingsStore.data.map { PaykitFeatureFlags.isUiEnabled(it) },
63+
settingsStore.isPaykitEnabled.map { PaykitFeatureFlags.isUiEnabled(it) },
6464
) { contacts, isPaykitEnabled ->
6565
if (isPaykitEnabled) contacts.toImmutableList() else persistentListOf<PubkyProfile>()
6666
}.stateInScope(persistentListOf())

app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ import to.bitkit.ext.toHex
9595
import to.bitkit.ext.toUserMessage
9696
import to.bitkit.ext.totalValue
9797
import to.bitkit.ext.watchUntil
98+
import to.bitkit.flags.PaykitFeatureFlags
9899
import to.bitkit.models.FeeRate
99100
import to.bitkit.models.NewTransactionSheetDetails
100101
import to.bitkit.models.NewTransactionSheetDirection
@@ -146,7 +147,6 @@ import to.bitkit.utils.AppError
146147
import to.bitkit.utils.Bip21Utils
147148
import to.bitkit.utils.Logger
148149
import to.bitkit.utils.NetworkValidationHelper
149-
import to.bitkit.utils.PaykitFeatureFlags
150150
import to.bitkit.utils.jsonLogOf
151151
import to.bitkit.utils.timedsheets.TimedSheetManager
152152
import to.bitkit.utils.timedsheets.sheets.AppUpdateTimedSheet
@@ -261,7 +261,7 @@ class AppViewModel @Inject constructor(
261261
private var isCompletingMigration = false
262262
private var addressValidationJob: Job? = null
263263
private var lastPrivatePaykitContactKeys: Set<String> = emptySet()
264-
private val isPaykitEnabled = settingsStore.data
264+
private val isPaykitEnabled = settingsStore.isPaykitEnabled
265265
.map { PaykitFeatureFlags.isUiEnabled(it) }
266266
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
267267

@@ -442,7 +442,7 @@ class AppViewModel @Inject constructor(
442442

443443
private suspend fun refreshPublicPaykitEndpointsIfEnabled(forceRefreshLightning: Boolean = false) {
444444
val settings = settingsStore.data.first()
445-
if (!PaykitFeatureFlags.isUiEnabled(settings) || !settings.sharesPublicPaykitEndpoints) return
445+
if (!isPaykitEnabled.value || !settings.sharesPublicPaykitEndpoints) return
446446

447447
val onchainAddress = walletRepo.walletState.value.onchainAddress
448448
if (onchainAddress.isBlank() && !lightningRepo.canReceive()) return
@@ -457,7 +457,7 @@ class AppViewModel @Inject constructor(
457457
pubkyRepo.publicKey,
458458
pubkyRepo.contacts,
459459
pubkyRepo.contactsLoadVersion,
460-
settingsStore.data.map { PaykitFeatureFlags.isUiEnabled(it) },
460+
settingsStore.isPaykitEnabled.map { PaykitFeatureFlags.isUiEnabled(it) },
461461
) { publicKey, contacts, contactsLoadVersion, isPaykitEnabled ->
462462
PaykitContactSyncState(
463463
publicKey = publicKey,
@@ -506,7 +506,7 @@ class AppViewModel @Inject constructor(
506506
val contactKeys = pubkyRepo.contacts.value.map { it.publicKey }
507507
retryPendingPaykitEndpointRemoval(contactKeys, reason)
508508

509-
if (!PaykitFeatureFlags.isUiEnabled(settingsStore.data.first())) return
509+
if (!isPaykitEnabled.value) return
510510

511511
privatePaykitRepo.reconcileReservedReceiveIndexes()
512512
.onFailure {
@@ -2951,13 +2951,13 @@ class AppViewModel @Inject constructor(
29512951
}
29522952

29532953
PubkyRingAuthCallback.parse(uri)?.let {
2954-
if (!PaykitFeatureFlags.isUiEnabled(settingsStore.data.first())) return@launch
2954+
if (!isPaykitEnabled.value) return@launch
29552955
handlePubkyRingAuthCallback(it)
29562956
return@launch
29572957
}
29582958

29592959
if (uri.scheme == PUBKYAUTH_SCHEME) {
2960-
if (!PaykitFeatureFlags.isUiEnabled(settingsStore.data.first())) return@launch
2960+
if (!isPaykitEnabled.value) return@launch
29612961
handlePubkyAuth(uri.toString())
29622962
return@launch
29632963
}

app/src/main/java/to/bitkit/viewmodels/SettingsViewModel.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import to.bitkit.data.WidgetsStore
1717
import to.bitkit.data.hasPaykitState
1818
import to.bitkit.data.hasPublicPaykitPublicationState
1919
import to.bitkit.data.paykitDisabled
20+
import to.bitkit.flags.PaykitFeatureFlags
2021
import to.bitkit.models.TransactionSpeed
2122
import to.bitkit.repositories.PrivatePaykitRepo
2223
import to.bitkit.repositories.PubkyRepo
2324
import to.bitkit.repositories.PublicPaykitRepo
2425
import to.bitkit.repositories.WidgetsRepo
2526
import to.bitkit.utils.Logger
26-
import to.bitkit.utils.PaykitFeatureFlags
2727
import javax.inject.Inject
2828

2929
@Suppress("TooManyFunctions")
@@ -43,7 +43,8 @@ class SettingsViewModel @Inject constructor(
4343
init {
4444
viewModelScope.launch {
4545
val settings = settingsStore.data.first()
46-
if (!PaykitFeatureFlags.isUiEnabled(settings) && settings.hasPaykitState()) {
46+
val isPaykitEnabled = PaykitFeatureFlags.isUiEnabled(settingsStore.isPaykitEnabled.first())
47+
if (!isPaykitEnabled && settings.hasPaykitState()) {
4748
updatePaykitEnabled(false)
4849
}
4950
}
@@ -181,10 +182,10 @@ class SettingsViewModel @Inject constructor(
181182
}
182183
}
183184

184-
val isPaykitEnabled = settingsStore.data.map { PaykitFeatureFlags.isUiEnabled(it) }
185+
val isPaykitEnabled = settingsStore.isPaykitEnabled.map { PaykitFeatureFlags.isUiEnabled(it) }
185186
.asStateFlow(initialValue = false)
186187

187-
val isPaykitStateLoaded = settingsStore.data.map { true }
188+
val isPaykitStateLoaded = settingsStore.isPaykitEnabled.map { true }
188189
.asStateFlow(initialValue = false)
189190

190191
fun setIsPaykitEnabled(value: Boolean) {
@@ -196,15 +197,12 @@ class SettingsViewModel @Inject constructor(
196197
private suspend fun updatePaykitEnabled(value: Boolean) {
197198
val shouldEnable = value && PaykitFeatureFlags.isUiAvailable
198199
val hadPublicPaykitState = settingsStore.data.first().hasPublicPaykitPublicationState()
199-
settingsStore.update {
200-
if (shouldEnable) {
201-
it.copy(isPaykitEnabled = true)
202-
} else {
203-
it.paykitDisabled(markPublicCleanupPending = it.hasPublicPaykitPublicationState())
204-
}
205-
}
200+
settingsStore.setIsPaykitEnabled(shouldEnable)
206201

207202
if (!shouldEnable) {
203+
settingsStore.update {
204+
it.paykitDisabled(markPublicCleanupPending = it.hasPublicPaykitPublicationState())
205+
}
208206
removePaykitEndpoints(hadPublicPaykitState)
209207
}
210208
}

app/src/test/java/to/bitkit/repositories/BackupRepoTest.kt

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class BackupRepoTest : BaseUnitTest() {
6565
whenever(settingsStore.data).thenReturn(settingsData)
6666
whenever { settingsStore.update(any()) }.thenReturn(Unit)
6767
whenever { vssBackupClient.getObject(any()) }.thenReturn(Result.success(null))
68+
whenever { vssBackupClient.putObject(any(), any()) }
69+
.thenReturn(Result.success(VssItem(key = BackupCategory.SETTINGS.name, value = byteArrayOf(), version = 1)))
6870
whenever { privatePaykitRepo.restoreBackup(anyOrNull()) }.thenReturn(Result.success(Unit))
6971
whenever { privatePaykitAddressReservationRepo.restoreBackup(any()) }.thenReturn(Result.success(Unit))
7072
whenever {
@@ -111,21 +113,6 @@ class BackupRepoTest : BaseUnitTest() {
111113
verify(settingsStore, never()).update(any())
112114
}
113115

114-
@Test
115-
fun `full restore marks private cleanup pending when restored links exist and Paykit is disabled`() = test {
116-
val contactKey = "pubkycytinw71a3ge1esmzj5e53hsr3jtj6t4pogpgr6k75w9mzmyokzo"
117-
stubWalletBackup(
118-
privatePaykitContactLinks = mapOf(
119-
contactKey to PrivatePaykitContactLinkBackupV1(publicKey = contactKey)
120-
)
121-
)
122-
123-
val result = sut.performFullRestoreFromLatestBackup()
124-
125-
assertTrue(result.isSuccess)
126-
verify(privatePaykitRepo).setContactSharingCleanupPending(true)
127-
}
128-
129116
private fun stubWalletBackup(
130117
privatePaykitContactLinks: Map<String, PrivatePaykitContactLinkBackupV1>? = null,
131118
) {

0 commit comments

Comments
 (0)