diff --git a/app/src/main/java/com/duckduckgo/app/settings/NewSettingsActivity.kt b/app/src/main/java/com/duckduckgo/app/settings/NewSettingsActivity.kt index 23c911930f0b..acded73d4e11 100644 --- a/app/src/main/java/com/duckduckgo/app/settings/NewSettingsActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/settings/NewSettingsActivity.kt @@ -153,7 +153,7 @@ class NewSettingsActivity : DuckDuckGoActivity() { get() = binding.includeSettings.contentSettingsInternal private val viewsPro - get() = binding.includeSettings.settingsSectionPro + get() = binding.includeSettings.contentSettingsPrivacyPro override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/res/layout/content_settings_new.xml b/app/src/main/res/layout/content_settings_new.xml index 4b0f1d6b3cd4..d8c6f6803545 100644 --- a/app/src/main/res/layout/content_settings_new.xml +++ b/app/src/main/res/layout/content_settings_new.xml @@ -36,13 +36,14 @@ android:layout_marginTop="@dimen/keyline_4" /> + android:id="@+id/contentSettingsPrivacyPro" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" > + + android:layout_width="match_parent" + android:layout_height="wrap_content" /> Small @@ -306,7 +313,7 @@ abstract class DaxListItem( } } - fun dimension(size: LeadingIconSize): Int { + fun dimension(size: IconSize): Int { return when (size) { Small -> R.dimen.listItemImageSmallSize Medium -> R.dimen.listItemImageMediumSize diff --git a/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/OneLineListItem.kt b/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/OneLineListItem.kt index 9971561f021f..f26fc192ffc3 100644 --- a/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/OneLineListItem.kt +++ b/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/OneLineListItem.kt @@ -21,7 +21,7 @@ import android.util.AttributeSet import android.view.View import android.widget.ImageView import com.duckduckgo.common.ui.view.DaxSwitch -import com.duckduckgo.common.ui.view.listitem.DaxListItem.LeadingIconSize.Medium +import com.duckduckgo.common.ui.view.listitem.DaxListItem.IconSize.Medium import com.duckduckgo.common.ui.view.text.DaxTextView import com.duckduckgo.common.ui.viewbinding.viewBinding import com.duckduckgo.mobile.android.R @@ -93,13 +93,13 @@ class OneLineListItem @JvmOverloads constructor( ImageBackground.None } - val leadingIconSize = if (hasValue(R.styleable.OneLineListItem_leadingIconSize)) { - LeadingIconSize.from(getInt(R.styleable.OneLineListItem_leadingIconSize, 1)) + val iconSize = if (hasValue(R.styleable.OneLineListItem_leadingIconSize)) { + IconSize.from(getInt(R.styleable.OneLineListItem_leadingIconSize, 1)) } else { Medium } - setLeadingIconSize(leadingIconSize, leadingIconBackground) + setLeadingIconSize(iconSize, leadingIconBackground) val showTrailingIcon = hasValue(R.styleable.OneLineListItem_trailingIcon) val showSwitch = getBoolean(R.styleable.OneLineListItem_showSwitch, false) diff --git a/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/SettingsListItem.kt b/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/SettingsListItem.kt index cd354bba2d9f..a9352c8aa72f 100644 --- a/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/SettingsListItem.kt +++ b/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/SettingsListItem.kt @@ -19,6 +19,7 @@ package com.duckduckgo.common.ui.view.listitem import android.content.Context import android.util.AttributeSet import android.widget.ImageView +import androidx.annotation.DrawableRes import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import com.duckduckgo.common.ui.view.StatusIndicatorView @@ -38,13 +39,13 @@ class SettingsListItem @JvmOverloads constructor( private val binding: ViewSettingsListItemBinding by viewBinding() - val primaryText: DaxTextView + private val primaryText: DaxTextView get() = binding.primaryText - val leadingIcon: ImageView + private val leadingIcon: ImageView get() = binding.leadingIcon - val betaPill: ImageView + private val betaPill: ImageView get() = binding.betaPill - val statusIndicator: StatusIndicatorView + private val statusIndicator: StatusIndicatorView get() = binding.statusIndicator init { @@ -65,9 +66,9 @@ class SettingsListItem @JvmOverloads constructor( leadingIcon.gone() } - setPillVisible(getBoolean(R.styleable.SettingsListItem_showBetaPill, false)) + betaPill.isVisible = getBoolean(R.styleable.SettingsListItem_showBetaPill, false) - val indicatorStatus = Status.from(getInt(R.styleable.SettingsListItem_indicatorStatus, 0)) + val indicatorStatus = Status.from(getInt(R.styleable.SettingsListItem_indicatorStatus, 2)) statusIndicator.setStatus(indicatorStatus) recycle() @@ -79,11 +80,13 @@ class SettingsListItem @JvmOverloads constructor( binding.root.setOnClickListener { onClick() } } + /** Sets whether the status indicator is on or off */ fun setStatus(isOn: Boolean) { statusIndicator.setStatus(if (isOn) Status.ON else Status.OFF) } - private fun setPillVisible(isVisible: Boolean) { - betaPill.isVisible = isVisible + /** Sets the leading icon image resource */ + fun setLeadingIconResource(@DrawableRes idRes: Int) { + leadingIcon.setImageResource(idRes) } } diff --git a/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/TwoLineListItem.kt b/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/TwoLineListItem.kt index da88bf0c09c9..8ca55b8564f6 100644 --- a/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/TwoLineListItem.kt +++ b/common/common-ui/src/main/java/com/duckduckgo/common/ui/view/listitem/TwoLineListItem.kt @@ -23,7 +23,7 @@ import android.util.AttributeSet import android.view.View import android.widget.ImageView import com.duckduckgo.common.ui.view.DaxSwitch -import com.duckduckgo.common.ui.view.listitem.DaxListItem.LeadingIconSize.Medium +import com.duckduckgo.common.ui.view.listitem.DaxListItem.IconSize.Medium import com.duckduckgo.common.ui.view.text.DaxTextView import com.duckduckgo.common.ui.viewbinding.viewBinding import com.duckduckgo.mobile.android.R @@ -100,7 +100,7 @@ class TwoLineListItem @JvmOverloads constructor( } val leadingIconSize = if (hasValue(R.styleable.TwoLineListItem_leadingIconSize)) { - LeadingIconSize.from(getInt(R.styleable.TwoLineListItem_leadingIconSize, 1)) + IconSize.from(getInt(R.styleable.TwoLineListItem_leadingIconSize, 1)) } else { Medium } @@ -114,6 +114,10 @@ class TwoLineListItem @JvmOverloads constructor( setPillVisible(getBoolean(R.styleable.TwoLineListItem_showBetaPill, false)) val showTrailingIcon = hasValue(R.styleable.TwoLineListItem_trailingIcon) + + val trailingIconSize = IconSize.from(getInt(R.styleable.TwoLineListItem_trailingIconSize, Medium.ordinal)) + setTrailingIconSize(trailingIconSize) + val showSwitch = getBoolean(R.styleable.TwoLineListItem_showSwitch, false) when { showSwitch -> showSwitch() diff --git a/common/common-ui/src/main/res/layout/component_two_line_item.xml b/common/common-ui/src/main/res/layout/component_two_line_item.xml index ef9c4dff9d80..6884d1f403fb 100644 --- a/common/common-ui/src/main/res/layout/component_two_line_item.xml +++ b/common/common-ui/src/main/res/layout/component_two_line_item.xml @@ -171,13 +171,37 @@ app:trailingIcon="@drawable/ic_menu_vertical_24" /> + + + + diff --git a/common/common-ui/src/main/res/values/attrs-lists.xml b/common/common-ui/src/main/res/values/attrs-lists.xml index d61b6e549644..d5520e29d512 100644 --- a/common/common-ui/src/main/res/values/attrs-lists.xml +++ b/common/common-ui/src/main/res/values/attrs-lists.xml @@ -54,6 +54,12 @@ + + + + + + @@ -87,6 +93,7 @@ + diff --git a/common/common-ui/src/main/res/drawable/ic_vpn_color_24.xml b/network-protection/network-protection-impl/src/main/res/drawable/ic_vpn_color_24.xml similarity index 81% rename from common/common-ui/src/main/res/drawable/ic_vpn_color_24.xml rename to network-protection/network-protection-impl/src/main/res/drawable/ic_vpn_color_24.xml index 5cc01cc7fc4b..78af318a96f4 100644 --- a/common/common-ui/src/main/res/drawable/ic_vpn_color_24.xml +++ b/network-protection/network-protection-impl/src/main/res/drawable/ic_vpn_color_24.xml @@ -1,3 +1,19 @@ + + + { + binding.subscriptionBuyContainer.gone() + binding.subscriptionRestoreContainer.gone() + binding.subscriptionWaitingContainer.gone() + binding.subscriptionSettingContainer.show() + } + WAITING -> { + binding.subscriptionBuyContainer.gone() + binding.subscriptionWaitingContainer.show() + binding.subscriptionSettingContainer.gone() + binding.subscriptionRestoreContainer.show() + } + EXPIRED, INACTIVE -> { + binding.subscriptionBuy.setPrimaryText(context.getString(R.string.subscriptionSettingExpired)) + binding.subscriptionBuy.setSecondaryText(context.getString(R.string.subscriptionSettingExpiredSubtitle)) + binding.subscriptionBuy.setItemStatus(ALERT) + binding.subscriptionGet.setText(R.string.subscriptionSettingExpiredViewPlans) + binding.subscriptionBuyContainer.show() + binding.subscriptionSettingContainer.show() + binding.subscriptionWaitingContainer.gone() + binding.subscriptionRestoreContainer.gone() + } + else -> { + binding.subscriptionBuy.setPrimaryText(context.getString(R.string.subscriptionSettingSubscribe)) + binding.subscriptionBuy.setSecondaryText( + when (viewState.region) { + ROW -> context.getString(R.string.subscriptionSettingSubscribeSubtitleRow) + US -> context.getString(R.string.subscriptionSettingSubscribeSubtitle) + else -> "" + }, + ) + binding.subscriptionBuy.setItemStatus(DISABLED) + binding.subscriptionGet.setText(R.string.subscriptionSettingGet) + binding.subscriptionBuyContainer.show() + binding.subscriptionSettingContainer.gone() + binding.subscriptionWaitingContainer.gone() + binding.subscriptionRestoreContainer.show() + } + } + } + + private fun processCommands(command: Command) { + when (command) { + is OpenSettings -> { + globalActivityStarter.start(context, SubscriptionsSettingsScreenWithEmptyParams) + } + is OpenBuyScreen -> { + globalActivityStarter.start( + context, + SubscriptionsWebViewActivityWithParams( + url = SubscriptionsConstants.BUY_URL, + ), + ) + } + is OpenRestoreScreen -> { + globalActivityStarter.start(context, RestoreSubscriptionScreenWithParams(isOriginWeb = false)) + } + } + } +} diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/LegacyProSettingViewModel.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/LegacyProSettingViewModel.kt new file mode 100644 index 000000000000..a824f85d7e50 --- /dev/null +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/LegacyProSettingViewModel.kt @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.subscriptions.impl.settings.views + +import android.annotation.SuppressLint +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.duckduckgo.anvil.annotations.ContributesViewModel +import com.duckduckgo.di.scopes.ViewScope +import com.duckduckgo.subscriptions.api.SubscriptionStatus +import com.duckduckgo.subscriptions.api.SubscriptionStatus.UNKNOWN +import com.duckduckgo.subscriptions.impl.SubscriptionsConstants.MONTHLY_PLAN_ROW +import com.duckduckgo.subscriptions.impl.SubscriptionsConstants.MONTHLY_PLAN_US +import com.duckduckgo.subscriptions.impl.SubscriptionsManager +import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender +import com.duckduckgo.subscriptions.impl.settings.views.LegacyProSettingViewModel.Command.OpenBuyScreen +import com.duckduckgo.subscriptions.impl.settings.views.LegacyProSettingViewModel.Command.OpenRestoreScreen +import com.duckduckgo.subscriptions.impl.settings.views.LegacyProSettingViewModel.Command.OpenSettings +import com.duckduckgo.subscriptions.impl.settings.views.LegacyProSettingViewModel.ViewState.SubscriptionRegion +import javax.inject.Inject +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.launch + +@SuppressLint("NoLifecycleObserver") // we don't observe app lifecycle +@ContributesViewModel(ViewScope::class) +class LegacyProSettingViewModel @Inject constructor( + private val subscriptionsManager: SubscriptionsManager, + private val pixelSender: SubscriptionPixelSender, +) : ViewModel(), DefaultLifecycleObserver { + + sealed class Command { + data object OpenSettings : Command() + data object OpenBuyScreen : Command() + data object OpenRestoreScreen : Command() + } + + private val command = Channel(1, BufferOverflow.DROP_OLDEST) + internal fun commands(): Flow = command.receiveAsFlow() + data class ViewState( + val status: SubscriptionStatus = UNKNOWN, + val region: SubscriptionRegion? = null, + ) { + enum class SubscriptionRegion { US, ROW } + } + + private val _viewState = MutableStateFlow(ViewState()) + val viewState = _viewState.asStateFlow() + + fun onSettings() { + sendCommand(OpenSettings) + } + + fun onBuy() { + sendCommand(OpenBuyScreen) + } + + fun onRestore() { + pixelSender.reportAppSettingsRestorePurchaseClick() + sendCommand(OpenRestoreScreen) + } + + override fun onCreate(owner: LifecycleOwner) { + super.onCreate(owner) + subscriptionsManager.subscriptionStatus + .distinctUntilChanged() + .onEach { subscriptionStatus -> + val region = when (subscriptionsManager.getSubscriptionOffer()?.monthlyPlanId) { + MONTHLY_PLAN_ROW -> SubscriptionRegion.ROW + MONTHLY_PLAN_US -> SubscriptionRegion.US + else -> null + } + _viewState.emit(viewState.value.copy(status = subscriptionStatus, region = region)) + }.launchIn(viewModelScope) + } + + private fun sendCommand(newCommand: Command) { + viewModelScope.launch { + command.send(newCommand) + } + } +} diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ProSettingView.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ProSettingView.kt index 75c91092e91f..4ce3f911ae70 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ProSettingView.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/settings/views/ProSettingView.kt @@ -20,18 +20,17 @@ import android.annotation.SuppressLint import android.content.Context import android.util.AttributeSet import android.widget.FrameLayout +import androidx.core.view.isGone +import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.findViewTreeViewModelStoreOwner import com.duckduckgo.anvil.annotations.InjectWith -import com.duckduckgo.common.ui.view.gone -import com.duckduckgo.common.ui.view.listitem.CheckListItem.CheckItemStatus.ALERT -import com.duckduckgo.common.ui.view.listitem.CheckListItem.CheckItemStatus.DISABLED -import com.duckduckgo.common.ui.view.show import com.duckduckgo.common.ui.viewbinding.viewBinding import com.duckduckgo.common.utils.ConflatedJob import com.duckduckgo.common.utils.ViewViewModelFactory import com.duckduckgo.di.scopes.ViewScope +import com.duckduckgo.mobile.android.R as CommonR import com.duckduckgo.navigation.api.GlobalActivityStarter import com.duckduckgo.subscriptions.api.SubscriptionStatus.AUTO_RENEWABLE import com.duckduckgo.subscriptions.api.SubscriptionStatus.EXPIRED @@ -135,42 +134,53 @@ class ProSettingView @JvmOverloads constructor( private fun renderView(viewState: ViewState) { when (viewState.status) { AUTO_RENEWABLE, NOT_AUTO_RENEWABLE, GRACE_PERIOD -> { - binding.subscriptionBuyContainer.gone() - binding.subscriptionRestoreContainer.gone() - binding.subscriptionWaitingContainer.gone() - binding.subscriptionSettingContainer.show() + with(binding) { + subscriptionBuyContainer.isGone = true + subscriptionRestoreContainer.isGone = true + subscriptionSetting.isGone = true + + subscribedSubscriptionSetting.isVisible = true + subscriptionSettingContainer.isVisible = true + } } WAITING -> { - binding.subscriptionBuyContainer.gone() - binding.subscriptionWaitingContainer.show() - binding.subscriptionSettingContainer.gone() - binding.subscriptionRestoreContainer.show() + with(binding) { + subscriptionBuyContainer.isGone = true + subscriptionRestoreContainer.isGone = true + subscribedSubscriptionSetting.isGone = true + + subscriptionSettingContainer.isVisible = true + subscriptionSetting.setSecondaryText(context.getString(R.string.subscriptionSettingActivating)) + } } EXPIRED, INACTIVE -> { - binding.subscriptionBuy.setPrimaryText(context.getString(R.string.subscriptionSettingExpired)) - binding.subscriptionBuy.setSecondaryText(context.getString(R.string.subscriptionSettingExpiredSubtitle)) - binding.subscriptionBuy.setItemStatus(ALERT) - binding.subscriptionGet.setText(R.string.subscriptionSettingExpiredViewPlans) - binding.subscriptionBuyContainer.show() - binding.subscriptionSettingContainer.show() - binding.subscriptionWaitingContainer.gone() - binding.subscriptionRestoreContainer.gone() + with(binding) { + subscriptionBuyContainer.isGone = true + subscriptionRestoreContainer.isGone = true + subscribedSubscriptionSetting.isGone = true + + subscriptionSettingContainer.isVisible = true + subscriptionSetting.setSecondaryText(context.getString(R.string.subscriptionSettingExpired)) + subscriptionSetting.setTrailingIconResource(CommonR.drawable.ic_exclamation_red_16) + } } else -> { - binding.subscriptionBuy.setPrimaryText(context.getString(R.string.subscriptionSettingSubscribe)) - binding.subscriptionBuy.setSecondaryText( - when (viewState.region) { - ROW -> context.getString(R.string.subscriptionSettingSubscribeSubtitleRow) - US -> context.getString(R.string.subscriptionSettingSubscribeSubtitle) - else -> "" - }, - ) - binding.subscriptionBuy.setItemStatus(DISABLED) - binding.subscriptionGet.setText(R.string.subscriptionSettingGet) - binding.subscriptionBuyContainer.show() - binding.subscriptionSettingContainer.gone() - binding.subscriptionWaitingContainer.gone() - binding.subscriptionRestoreContainer.show() + with(binding) { + subscriptionBuy.setPrimaryText(context.getString(R.string.subscriptionSettingSubscribe)) + subscriptionBuy.setSecondaryText( + when (viewState.region) { + ROW -> context.getString(R.string.subscriptionSettingSubscribeSubtitleRow) + US -> context.getString(R.string.subscriptionSettingSubscribeSubtitle) + else -> "" + }, + ) + subscriptionGet.setText(R.string.subscriptionSettingGet) + + subscriptionBuyContainer.isVisible = true + subscriptionRestoreContainer.isVisible = true + + subscriptionSettingContainer.isGone = true + } } } } diff --git a/common/common-ui/src/main/res/drawable/ic_identity_blocked_pir_color_24.xml b/subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_blocked_pir_color_24.xml similarity index 100% rename from common/common-ui/src/main/res/drawable/ic_identity_blocked_pir_color_24.xml rename to subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_blocked_pir_color_24.xml diff --git a/common/common-ui/src/main/res/drawable/ic_identity_blocked_pir_grayscale_color_24.xml b/subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_blocked_pir_grayscale_color_24.xml similarity index 100% rename from common/common-ui/src/main/res/drawable/ic_identity_blocked_pir_grayscale_color_24.xml rename to subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_blocked_pir_grayscale_color_24.xml diff --git a/common/common-ui/src/main/res/drawable/ic_identity_theft_restoration_color_24.xml b/subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_theft_restoration_color_24.xml similarity index 100% rename from common/common-ui/src/main/res/drawable/ic_identity_theft_restoration_color_24.xml rename to subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_theft_restoration_color_24.xml diff --git a/common/common-ui/src/main/res/drawable/ic_identity_theft_restoration_grayscale_color_24.xml b/subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_theft_restoration_grayscale_color_24.xml similarity index 100% rename from common/common-ui/src/main/res/drawable/ic_identity_theft_restoration_grayscale_color_24.xml rename to subscriptions/subscriptions-impl/src/main/res/drawable/ic_identity_theft_restoration_grayscale_color_24.xml diff --git a/common/common-ui/src/main/res/drawable/ic_privacy_pro_color_24.xml b/subscriptions/subscriptions-impl/src/main/res/drawable/ic_privacy_pro_color_24.xml similarity index 100% rename from common/common-ui/src/main/res/drawable/ic_privacy_pro_color_24.xml rename to subscriptions/subscriptions-impl/src/main/res/drawable/ic_privacy_pro_color_24.xml diff --git a/subscriptions/subscriptions-impl/src/main/res/layout/legacy_view_settings.xml b/subscriptions/subscriptions-impl/src/main/res/layout/legacy_view_settings.xml new file mode 100644 index 000000000000..24b69b96fa8b --- /dev/null +++ b/subscriptions/subscriptions-impl/src/main/res/layout/legacy_view_settings.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/subscriptions/subscriptions-impl/src/main/res/layout/view_settings.xml b/subscriptions/subscriptions-impl/src/main/res/layout/view_settings.xml index 24b69b96fa8b..e77bd974cb82 100644 --- a/subscriptions/subscriptions-impl/src/main/res/layout/view_settings.xml +++ b/subscriptions/subscriptions-impl/src/main/res/layout/view_settings.xml @@ -31,10 +31,11 @@ android:visibility="gone" tools:visibility="visible"> - @@ -42,7 +43,7 @@ android:id="@+id/subscriptionGet" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="48dp" + android:layout_marginStart="56dp" android:layout_marginTop="@dimen/keyline_3" android:layout_marginBottom="@dimen/keyline_3" app:textType="primary" @@ -60,33 +61,25 @@ tools:visibility="visible"> - - - - + tools:visibility="visible" + tools:ignore="RtlSymmetry" /> - + diff --git a/subscriptions/subscriptions-impl/src/main/res/values/donottranslate.xml b/subscriptions/subscriptions-impl/src/main/res/values/donottranslate.xml new file mode 100644 index 000000000000..f002ba80c3d9 --- /dev/null +++ b/subscriptions/subscriptions-impl/src/main/res/values/donottranslate.xml @@ -0,0 +1,22 @@ + + + + + + Activating + + diff --git a/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/settings/views/LegacyLegacyProSettingViewModelTest.kt b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/settings/views/LegacyLegacyProSettingViewModelTest.kt new file mode 100644 index 000000000000..f1587dca900b --- /dev/null +++ b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/settings/views/LegacyLegacyProSettingViewModelTest.kt @@ -0,0 +1,82 @@ +package com.duckduckgo.subscriptions.impl.settings.views + +import app.cash.turbine.test +import com.duckduckgo.common.test.CoroutineTestRule +import com.duckduckgo.subscriptions.api.SubscriptionStatus +import com.duckduckgo.subscriptions.impl.SubscriptionsManager +import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender +import com.duckduckgo.subscriptions.impl.settings.views.LegacyProSettingViewModel.Command.OpenBuyScreen +import com.duckduckgo.subscriptions.impl.settings.views.LegacyProSettingViewModel.Command.OpenRestoreScreen +import com.duckduckgo.subscriptions.impl.settings.views.LegacyProSettingViewModel.Command.OpenSettings +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runTest +import org.junit.Assert.* +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyNoMoreInteractions +import org.mockito.kotlin.whenever + +class LegacyLegacyProSettingViewModelTest { + @get:Rule + val coroutineTestRule: CoroutineTestRule = CoroutineTestRule() + + private val subscriptionsManager: SubscriptionsManager = mock() + private val pixelSender: SubscriptionPixelSender = mock() + private lateinit var viewModel: LegacyProSettingViewModel + + @Before + fun before() { + viewModel = LegacyProSettingViewModel(subscriptionsManager, pixelSender) + } + + @Test + fun whenOnSettingsThenCommandSent() = runTest { + viewModel.commands().test { + viewModel.onSettings() + assertTrue(awaitItem() is OpenSettings) + cancelAndConsumeRemainingEvents() + } + } + + @Test + fun whenOnBuyThenCommandSent() = runTest { + viewModel.commands().test { + viewModel.onBuy() + assertTrue(awaitItem() is OpenBuyScreen) + cancelAndConsumeRemainingEvents() + } + } + + @Test + fun whenOnRestoreThenCommandSent() = runTest { + viewModel.commands().test { + viewModel.onRestore() + assertTrue(awaitItem() is OpenRestoreScreen) + cancelAndConsumeRemainingEvents() + } + } + + @Test + fun whenOnResumeEmitViewState() = runTest { + whenever(subscriptionsManager.subscriptionStatus).thenReturn(flowOf(SubscriptionStatus.EXPIRED)) + + viewModel.onCreate(mock()) + viewModel.viewState.test { + assertEquals(SubscriptionStatus.EXPIRED, awaitItem().status) + cancelAndConsumeRemainingEvents() + } + } + + @Test + fun whenOnRestoreThenPixelSent() = runTest { + viewModel.commands().test { + viewModel.onRestore() + verify(pixelSender).reportAppSettingsRestorePurchaseClick() + verifyNoMoreInteractions(pixelSender) + cancelAndConsumeRemainingEvents() + } + } +}