Skip to content

Commit 4d164d8

Browse files
committed
Introduce PirFeatureState
1 parent 7aeb21b commit 4d164d8

File tree

6 files changed

+73
-30
lines changed

6 files changed

+73
-30
lines changed

pir/pir-api/src/main/java/com/duckduckgo/pir/api/PirFeature.kt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,14 @@
1616

1717
package com.duckduckgo.pir.api
1818

19-
interface PirFeature {
19+
import com.duckduckgo.pir.api.dashboard.PirFeatureState
2020

21-
/**
22-
* Runs on the IO thread by default.
23-
*
24-
* @return true if the PIR beta is enabled, false otherwise
25-
*/
26-
suspend fun isPirBetaEnabled(): Boolean
21+
interface PirFeature {
2722

2823
/**
2924
* Runs on the IO thread by default.
3025
*
31-
* @return true if PIR storage is available, false otherwise
26+
* @return [PirFeatureState] that represents the current state of the feature
3227
*/
33-
suspend fun isPirStorageAvailable(): Boolean
28+
suspend fun getPirFeatureState(): PirFeatureState
3429
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2025 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.pir.api.dashboard
18+
19+
/**
20+
* Represents the state of the PIR (Private Information Retrieval) feature.
21+
*/
22+
enum class PirFeatureState {
23+
/**
24+
* The PIR feature is enabled and available for use.
25+
*/
26+
ENABLED,
27+
28+
/**
29+
* The PIR feature is disabled and cannot be used.
30+
*/
31+
DISABLED,
32+
33+
/**
34+
* The PIR feature is enabled but not available.
35+
*/
36+
NOT_AVAILABLE,
37+
}

pir/pir-impl/src/main/java/com/duckduckgo/pir/impl/PirRemoteFeatures.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.duckduckgo.feature.toggles.api.Toggle
2323
import com.duckduckgo.feature.toggles.api.Toggle.DefaultFeatureValue
2424
import com.duckduckgo.feature.toggles.api.Toggle.DefaultValue
2525
import com.duckduckgo.pir.api.PirFeature
26+
import com.duckduckgo.pir.api.dashboard.PirFeatureState
2627
import com.duckduckgo.pir.impl.store.PirRepository
2728
import com.squareup.anvil.annotations.ContributesBinding
2829
import dagger.SingleInstanceIn
@@ -52,11 +53,17 @@ class PirRemoteFeatureImpl @Inject constructor(
5253
private val pirRepository: PirRepository,
5354
) : PirFeature {
5455

55-
override suspend fun isPirBetaEnabled(): Boolean = withContext(dispatcherProvider.io()) {
56-
pirRemoteFeatures.pirBeta().isEnabled()
57-
}
56+
override suspend fun getPirFeatureState(): PirFeatureState = withContext(dispatcherProvider.io()) {
57+
val isEnabled = pirRemoteFeatures.pirBeta().isEnabled()
58+
if (!isEnabled) {
59+
return@withContext PirFeatureState.DISABLED
60+
}
61+
62+
val isRepositoryAvailable = pirRepository.isRepositoryAvailable()
63+
if (!isRepositoryAvailable) {
64+
return@withContext PirFeatureState.NOT_AVAILABLE
65+
}
5866

59-
override suspend fun isPirStorageAvailable(): Boolean = withContext(dispatcherProvider.io()) {
60-
pirRepository.isRepositoryAvailable()
67+
return@withContext PirFeatureState.ENABLED
6168
}
6269
}

subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/PirSettingView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class PirSettingView @JvmOverloads constructor(
131131
globalActivityStarter.start(context, PirDashboardWebViewScreen)
132132
}
133133

134-
Command.ShowPirStorageUnavailableDialog -> {
134+
Command.ShowPirUnavailableDialog -> {
135135
TextAlertDialogBuilder(context)
136136
.setTitle(R.string.pirStorageUnavailableDialogTitle)
137137
.setMessage(R.string.pirStorageUnavailableDialogMessage)

subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/PirSettingViewModel.kt

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import androidx.lifecycle.viewModelScope
2424
import com.duckduckgo.anvil.annotations.ContributesViewModel
2525
import com.duckduckgo.di.scopes.ViewScope
2626
import com.duckduckgo.pir.api.PirFeature
27+
import com.duckduckgo.pir.api.dashboard.PirFeatureState
2728
import com.duckduckgo.subscriptions.api.Product.PIR
2829
import com.duckduckgo.subscriptions.api.SubscriptionStatus
2930
import com.duckduckgo.subscriptions.api.Subscriptions
@@ -57,7 +58,7 @@ class PirSettingViewModel @Inject constructor(
5758
sealed class Command {
5859
data object OpenPirDesktop : Command()
5960
data object OpenPirDashboard : Command()
60-
data object ShowPirStorageUnavailableDialog : Command()
61+
data object ShowPirUnavailableDialog : Command()
6162
}
6263

6364
private val command = Channel<Command>(1, BufferOverflow.DROP_OLDEST)
@@ -88,10 +89,10 @@ class PirSettingViewModel @Inject constructor(
8889
val command = when (type) {
8990
DESKTOP -> OpenPirDesktop
9091
DASHBOARD -> {
91-
if (pirFeature.isPirStorageAvailable()) {
92-
Command.OpenPirDashboard
93-
} else {
94-
Command.ShowPirStorageUnavailableDialog
92+
when (pirFeature.getPirFeatureState()) {
93+
PirFeatureState.ENABLED -> Command.OpenPirDashboard
94+
PirFeatureState.DISABLED -> OpenPirDesktop
95+
PirFeatureState.NOT_AVAILABLE -> Command.ShowPirUnavailableDialog
9596
}
9697
}
9798
}
@@ -137,10 +138,12 @@ class PirSettingViewModel @Inject constructor(
137138
SubscriptionStatus.GRACE_PERIOD,
138139
-> {
139140
if (hasValidEntitlement) {
140-
val type = if (pirFeature.isPirBetaEnabled()) {
141-
DASHBOARD
142-
} else {
143-
DESKTOP
141+
val type = when (pirFeature.getPirFeatureState()) {
142+
PirFeatureState.ENABLED,
143+
PirFeatureState.NOT_AVAILABLE,
144+
-> DASHBOARD
145+
146+
PirFeatureState.DISABLED -> DESKTOP
144147
}
145148
PirState.Enabled(type)
146149
} else {

subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/settings/views/PirSettingViewModelTest.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.duckduckgo.subscriptions.impl.settings.views
1919
import app.cash.turbine.test
2020
import com.duckduckgo.common.test.CoroutineTestRule
2121
import com.duckduckgo.pir.api.PirFeature
22+
import com.duckduckgo.pir.api.dashboard.PirFeatureState
2223
import com.duckduckgo.subscriptions.api.Product
2324
import com.duckduckgo.subscriptions.api.SubscriptionStatus.AUTO_RENEWABLE
2425
import com.duckduckgo.subscriptions.api.SubscriptionStatus.EXPIRED
@@ -183,7 +184,7 @@ class PirSettingViewModelTest {
183184
fun `when subscription state is auto renewable and entitled then PirState is enabled and beta FF is false`() = runTest {
184185
whenever(subscriptions.getEntitlementStatus()).thenReturn(flowOf(listOf(Product.PIR)))
185186
whenever(subscriptions.getSubscriptionStatus()).thenReturn(AUTO_RENEWABLE)
186-
whenever(pirFeature.isPirBetaEnabled()).thenReturn(false)
187+
whenever(pirFeature.getPirFeatureState()).thenReturn(PirFeatureState.DISABLED)
187188

188189
pirSettingsViewModel.onCreate(mock())
189190

@@ -199,7 +200,7 @@ class PirSettingViewModelTest {
199200
fun `when subscription state is auto renewable and entitled then PirState is enabled and beta FF is true`() = runTest {
200201
whenever(subscriptions.getEntitlementStatus()).thenReturn(flowOf(listOf(Product.PIR)))
201202
whenever(subscriptions.getSubscriptionStatus()).thenReturn(AUTO_RENEWABLE)
202-
whenever(pirFeature.isPirBetaEnabled()).thenReturn(true)
203+
whenever(pirFeature.getPirFeatureState()).thenReturn(PirFeatureState.ENABLED)
203204

204205
pirSettingsViewModel.onCreate(mock())
205206

@@ -230,7 +231,7 @@ class PirSettingViewModelTest {
230231
fun `when subscription state is not auto renewable and entitled then PirState is enabled and beta FF is false`() = runTest {
231232
whenever(subscriptions.getEntitlementStatus()).thenReturn(flowOf(listOf(Product.PIR)))
232233
whenever(subscriptions.getSubscriptionStatus()).thenReturn(NOT_AUTO_RENEWABLE)
233-
whenever(pirFeature.isPirBetaEnabled()).thenReturn(false)
234+
whenever(pirFeature.getPirFeatureState()).thenReturn(PirFeatureState.DISABLED)
234235

235236
pirSettingsViewModel.onCreate(mock())
236237

@@ -246,7 +247,7 @@ class PirSettingViewModelTest {
246247
fun `when subscription state is not auto renewable and entitled then PirState is enabled and beta FF is true`() = runTest {
247248
whenever(subscriptions.getEntitlementStatus()).thenReturn(flowOf(listOf(Product.PIR)))
248249
whenever(subscriptions.getSubscriptionStatus()).thenReturn(NOT_AUTO_RENEWABLE)
249-
whenever(pirFeature.isPirBetaEnabled()).thenReturn(true)
250+
whenever(pirFeature.getPirFeatureState()).thenReturn(PirFeatureState.ENABLED)
250251

251252
pirSettingsViewModel.onCreate(mock())
252253

@@ -277,7 +278,7 @@ class PirSettingViewModelTest {
277278
fun `when subscription state is grace period and entitled then PirState is enabled and beta FF is false`() = runTest {
278279
whenever(subscriptions.getEntitlementStatus()).thenReturn(flowOf(listOf(Product.PIR)))
279280
whenever(subscriptions.getSubscriptionStatus()).thenReturn(GRACE_PERIOD)
280-
whenever(pirFeature.isPirBetaEnabled()).thenReturn(false)
281+
whenever(pirFeature.getPirFeatureState()).thenReturn(PirFeatureState.DISABLED)
281282

282283
pirSettingsViewModel.onCreate(mock())
283284

@@ -293,7 +294,7 @@ class PirSettingViewModelTest {
293294
fun `when subscription state is grace period and entitled then PirState is enabled and beta FF is true`() = runTest {
294295
whenever(subscriptions.getEntitlementStatus()).thenReturn(flowOf(listOf(Product.PIR)))
295296
whenever(subscriptions.getSubscriptionStatus()).thenReturn(GRACE_PERIOD)
296-
whenever(pirFeature.isPirBetaEnabled()).thenReturn(true)
297+
whenever(pirFeature.getPirFeatureState()).thenReturn(PirFeatureState.ENABLED)
297298

298299
pirSettingsViewModel.onCreate(mock())
299300

0 commit comments

Comments
 (0)