Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix part of #5025: App and OS Deprecation Milestone 4 - Gate the new Deprecation Dialogs and Add Logic to Display Them #5249

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
695c2b2
feat: Add logic to tie together all pieces of the previous deprecatio…
kkmurerwa Nov 28, 2023
f218fec
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Nov 30, 2023
67f646b
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Dec 6, 2023
07ae734
fix: Fix failing tests
kkmurerwa Dec 6, 2023
23b176f
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Dec 6, 2023
cab5142
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Dec 6, 2023
53c5024
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Dec 8, 2023
216cebe
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Dec 14, 2023
3e186dd
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Dec 20, 2023
eb0fd34
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Dec 23, 2023
967b3c0
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Jan 4, 2024
9f82091
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Jan 15, 2024
3d34951
fix: Make changes and fixes requested after review
kkmurerwa Jan 17, 2024
5d2949e
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Jan 23, 2024
b723dca
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Jan 26, 2024
5fe98d2
feat: Temp code to ensure build works
kkmurerwa Jan 26, 2024
49c18f5
feat: Add ability to check previous responses before showing an updat…
kkmurerwa Jan 26, 2024
8af68a1
fix: Fix lint checks
kkmurerwa Jan 26, 2024
6e471d3
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Jan 29, 2024
472fe49
feat: Add tests for the new deprecation flow
kkmurerwa Jan 29, 2024
ca88493
Merge branch 'app-and-os-deprecation-milestone-4' of github.com:kkmur…
kkmurerwa Jan 29, 2024
d5d37fe
feat: Add tests for the app startup controller
kkmurerwa Jan 31, 2024
19ad9bd
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Feb 3, 2024
f38c87f
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Feb 12, 2024
1100c65
fix: Fix failing static checks
kkmurerwa Feb 12, 2024
45dbcc6
fix: Fix failing dialog tests
kkmurerwa Feb 12, 2024
eba9210
fix: Fix failing tests
kkmurerwa Feb 12, 2024
51ce11a
fix: Fix failing DeprecationController build
kkmurerwa Feb 12, 2024
5a9f03c
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Feb 13, 2024
31d6afe
test: Add tests to the DeprecationController and AppStartupStateContr…
kkmurerwa Feb 13, 2024
92d426c
chore: Add and improve tests on AppStartupStateControllerTest and Dep…
kkmurerwa Feb 13, 2024
b09e951
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Feb 19, 2024
e15d665
Merge branch 'develop' into app-and-os-deprecation-milestone-4
kkmurerwa Feb 20, 2024
427d69a
chore: Modified the test names and reduced repetition
kkmurerwa Feb 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package org.oppia.android.app.notice

import org.oppia.android.app.splash.DeprecationNoticeActionType

/** Listener for when an option on any deprecation dialog is clicked. */
interface DeprecationNoticeActionListener {
/** Called when a dialog button is clicked. */
fun onActionButtonClicked(noticeType: DeprecationNoticeActionType)
}

/** Enum class for the various deprecation notice actions available to the user. */
enum class DeprecationNoticeActionType {
/** Action for when the user presses the 'Close' option on a deprecation dialog. */
CLOSE,
/** Action for when the user presses the 'Dismiss' option on a deprecation dialog. */
DISMISS,
/** Action for when the user presses the 'Update' option on a deprecation dialog. */
UPDATE
}
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.app.Dialog
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import org.oppia.android.R
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.translation.AppLanguageResourceHandler
import javax.inject.Inject

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.app.Dialog
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import org.oppia.android.R
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.translation.AppLanguageResourceHandler
import javax.inject.Inject

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.app.Dialog
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import org.oppia.android.R
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.translation.AppLanguageResourceHandler
import javax.inject.Inject

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package org.oppia.android.app.notice.testing

import android.os.Bundle
import org.oppia.android.app.notice.DeprecationNoticeActionListener
import org.oppia.android.app.notice.DeprecationNoticeActionType
import org.oppia.android.app.notice.ForcedAppDeprecationNoticeDialogFragment
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.testing.activity.TestActivity

/** [TestActivity] for setting up a test environment for testing the beta notice dialog. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package org.oppia.android.app.notice.testing

import android.os.Bundle
import org.oppia.android.app.notice.DeprecationNoticeActionListener
import org.oppia.android.app.notice.DeprecationNoticeActionType
import org.oppia.android.app.notice.OptionalAppDeprecationNoticeDialogFragment
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.testing.activity.TestActivity

/** [TestActivity] for setting up a test environment for testing the beta notice dialog. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package org.oppia.android.app.notice.testing

import android.os.Bundle
import org.oppia.android.app.notice.DeprecationNoticeActionListener
import org.oppia.android.app.notice.DeprecationNoticeActionType
import org.oppia.android.app.notice.OsDeprecationNoticeDialogFragment
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.testing.activity.TestActivity

/** [TestActivity] for setting up a test environment for testing the beta notice dialog. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,13 @@ import org.oppia.android.app.fragment.FragmentComponentBuilderInjector
import org.oppia.android.app.fragment.FragmentComponentFactory
import org.oppia.android.app.model.ScreenName.SPLASH_ACTIVITY
import org.oppia.android.app.notice.BetaNoticeClosedListener
import org.oppia.android.app.notice.DeprecationNoticeActionListener
import org.oppia.android.app.notice.DeprecationNoticeActionType
import org.oppia.android.app.notice.DeprecationNoticeExitAppListener
import org.oppia.android.app.notice.GeneralAvailabilityUpgradeNoticeClosedListener
import org.oppia.android.util.logging.CurrentAppScreenNameIntentDecorator.decorateWithScreenName
import javax.inject.Inject

/** Enum class for the various deprecation notice actions available to the user. */
enum class DeprecationNoticeActionType {
/** Action for when the user presses the 'Close' option on a deprecation dialog. */
CLOSE,
/** Action for when the user presses the 'Dismiss' option on a deprecation dialog. */
DISMISS,
/** Action for when the user presses the 'Update' option on a deprecation dialog. */
UPDATE
}

/**
* An activity that shows a temporary loading page until the app is fully loaded then navigates to
* the profile selection screen.
Expand All @@ -38,6 +30,7 @@ class SplashActivity :
AppCompatActivity(),
FragmentComponentFactory,
DeprecationNoticeExitAppListener,
DeprecationNoticeActionListener,
BetaNoticeClosedListener,
GeneralAvailabilityUpgradeNoticeClosedListener {

Expand Down Expand Up @@ -69,4 +62,7 @@ class SplashActivity :

override fun onGaUpgradeNoticeOkayButtonClicked(permanentlyDismiss: Boolean) =
splashActivityPresenter.handleOnGaUpgradeNoticeOkayButtonClicked(permanentlyDismiss)

override fun onActionButtonClicked(noticeType: DeprecationNoticeActionType) =
splashActivityPresenter.handleOnDeprecationNoticeActionClicked(noticeType)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import org.oppia.android.app.model.AppStartupState.StartupMode
import org.oppia.android.app.model.BuildFlavor
import org.oppia.android.app.notice.AutomaticAppDeprecationNoticeDialogFragment
import org.oppia.android.app.notice.BetaNoticeDialogFragment
import org.oppia.android.app.notice.DeprecationNoticeActionType
import org.oppia.android.app.notice.ForcedAppDeprecationNoticeDialogFragment
import org.oppia.android.app.notice.GeneralAvailabilityUpgradeNoticeDialogFragment
import org.oppia.android.app.notice.OptionalAppDeprecationNoticeDialogFragment
import org.oppia.android.app.notice.OsDeprecationNoticeDialogFragment
import org.oppia.android.app.onboarding.OnboardingActivity
import org.oppia.android.app.profile.ProfileChooserActivity
import org.oppia.android.app.translation.AppLanguageLocaleHandler
Expand All @@ -31,11 +35,16 @@ import org.oppia.android.util.data.DataProvider
import org.oppia.android.util.data.DataProviders.Companion.combineWith
import org.oppia.android.util.data.DataProviders.Companion.toLiveData
import org.oppia.android.util.locale.OppiaLocale
import org.oppia.android.util.platformparameter.EnableAppAndOsDeprecation
import org.oppia.android.util.platformparameter.PlatformParameterValue
import javax.inject.Inject

private const val AUTO_DEPRECATION_NOTICE_DIALOG_FRAGMENT_TAG = "auto_deprecation_notice_dialog"
private const val FORCED_DEPRECATION_NOTICE_DIALOG_FRAGMENT_TAG = "forced_deprecation_notice_dialog"
private const val BETA_NOTICE_DIALOG_FRAGMENT_TAG = "beta_notice_dialog"
private const val GA_UPDATE_NOTICE_DIALOG_FRAGMENT_TAG = "general_availability_update_notice_dialog"
private const val OPTIONAL_UPDATE_NOTICE_DIALOG_FRAGMENT_TAG = "optional_update_notice_dialog"
private const val OS_UPDATE_NOTICE_DIALOG_FRAGMENT_TAG = "os_update_notice_dialog"
private const val SPLASH_INIT_STATE_DATA_PROVIDER_ID = "splash_init_state_data_provider"

/** The presenter for [SplashActivity]. */
Expand All @@ -49,7 +58,9 @@ class SplashActivityPresenter @Inject constructor(
private val localeController: LocaleController,
private val appLanguageLocaleHandler: AppLanguageLocaleHandler,
private val lifecycleSafeTimerFactory: LifecycleSafeTimerFactory,
private val currentBuildFlavor: BuildFlavor
private val currentBuildFlavor: BuildFlavor,
@EnableAppAndOsDeprecation
private val enableAppAndOsDeprecation: PlatformParameterValue<Boolean>,
) {
lateinit var startupMode: StartupMode

Expand All @@ -67,6 +78,14 @@ class SplashActivityPresenter @Inject constructor(
subscribeToOnboardingFlow()
}

fun handleOnDeprecationNoticeActionClicked(noticeType: DeprecationNoticeActionType) {
when (noticeType) {
DeprecationNoticeActionType.CLOSE -> handleOnDeprecationNoticeCloseAppButtonClicked()
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
DeprecationNoticeActionType.DISMISS -> handleOnDeprecationNoticeUpdateButtonClicked()
DeprecationNoticeActionType.UPDATE -> handleOnDeprecationNoticeDialogDismissed()
}
}
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved

/** Handles cases where the user clicks the close app option on a deprecation notice dialog. */
fun handleOnDeprecationNoticeCloseAppButtonClicked() {
// If the app close button is clicked for the deprecation notice, finish the activity to close
Expand All @@ -75,7 +94,7 @@ class SplashActivityPresenter @Inject constructor(
}

/** Handles cases where the user clicks the update option on a deprecation notice dialog. */
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
fun handleOnDeprecationNoticeUpdateButtonClicked() {
private fun handleOnDeprecationNoticeUpdateButtonClicked() {
// If the Update button is clicked for the deprecation notice, launch the Play Store and open
// the Oppia app's page.
val packageName = activity.packageName
Expand All @@ -100,7 +119,7 @@ class SplashActivityPresenter @Inject constructor(
}

/** Handles cases where the user dismisses the deprecation notice dialog. */
fun handleOnDeprecationNoticeDialogDismissed() {
private fun handleOnDeprecationNoticeDialogDismissed() {
// If the Dismiss button is clicked for the deprecation notice, the dialog is automatically
// dismissed. Navigate to profile chooser activity.
activity.startActivity(ProfileChooserActivity.createProfileChooserActivity(activity))
Expand Down Expand Up @@ -200,6 +219,43 @@ class SplashActivityPresenter @Inject constructor(
}

private fun processStartupMode() {
if (enableAppAndOsDeprecation.value) {
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
when (startupMode) {
StartupMode.USER_IS_ONBOARDED -> {
activity.startActivity(ProfileChooserActivity.createProfileChooserActivity(activity))
activity.finish()
}
StartupMode.APP_IS_DEPRECATED -> {
showDialog(
FORCED_DEPRECATION_NOTICE_DIALOG_FRAGMENT_TAG,
ForcedAppDeprecationNoticeDialogFragment::newInstance
)
}
StartupMode.OPTIONAL_UPDATE_AVAILABLE -> {
showDialog(
OPTIONAL_UPDATE_NOTICE_DIALOG_FRAGMENT_TAG,
OptionalAppDeprecationNoticeDialogFragment::newInstance
)
}
StartupMode.OS_IS_DEPRECATED -> {
showDialog(
OS_UPDATE_NOTICE_DIALOG_FRAGMENT_TAG,
OsDeprecationNoticeDialogFragment::newInstance
)
}
else -> {
// In all other cases (including errors when the startup state fails to load or is
// defaulted), assume the user needs to be onboarded.
activity.startActivity(OnboardingActivity.createOnboardingActivity(activity))
activity.finish()
}
}
} else {
processLegacyStartupMode()
}
}

private fun processLegacyStartupMode() {
when (startupMode) {
StartupMode.USER_IS_ONBOARDED -> {
activity.startActivity(ProfileChooserActivity.createProfileChooserActivity(activity))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule
import org.oppia.android.app.notice.testing.ForcedAppDeprecationNoticeDialogFragmentTestActivity
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.shim.ViewBindingShimModule
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule
import org.oppia.android.data.backends.gae.NetworkConfigProdModule
import org.oppia.android.data.backends.gae.NetworkModule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule
import org.oppia.android.app.notice.testing.OptionalAppDeprecationNoticeDialogFragmentTestActivity
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.shim.ViewBindingShimModule
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule
import org.oppia.android.data.backends.gae.NetworkConfigProdModule
import org.oppia.android.data.backends.gae.NetworkModule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule
import org.oppia.android.app.notice.testing.OsDeprecationNoticeDialogFragmentTestActivity
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.shim.ViewBindingShimModule
import org.oppia.android.app.splash.DeprecationNoticeActionType
import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule
import org.oppia.android.data.backends.gae.NetworkConfigProdModule
import org.oppia.android.data.backends.gae.NetworkModule
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package org.oppia.android.domain.onboarding

import android.os.Build
import kotlinx.coroutines.runBlocking
import org.oppia.android.app.model.AppStartupState
import org.oppia.android.app.model.AppStartupState.BuildFlavorNoticeMode
import org.oppia.android.app.model.AppStartupState.StartupMode
import org.oppia.android.app.model.BuildFlavor
import org.oppia.android.app.model.DeprecationResponseDatabase
import org.oppia.android.app.model.OnboardingState
import org.oppia.android.data.persistence.PersistentCacheStore
import org.oppia.android.domain.oppialogger.OppiaLogger
import org.oppia.android.util.data.DataProvider
import org.oppia.android.util.data.DataProviders.Companion.transform
import org.oppia.android.util.extensions.getStringFromBundle
import org.oppia.android.util.locale.OppiaLocale
import org.oppia.android.util.platformparameter.EnableAppAndOsDeprecation
import org.oppia.android.util.platformparameter.ForcedAppUpdateVersionCode
import org.oppia.android.util.platformparameter.LowestSupportedApiLevel
import org.oppia.android.util.platformparameter.OptionalAppUpdateVersionCode
import org.oppia.android.util.platformparameter.PlatformParameterValue
import javax.inject.Inject
import javax.inject.Singleton

Expand All @@ -23,7 +31,16 @@ class AppStartupStateController @Inject constructor(
private val oppiaLogger: OppiaLogger,
private val expirationMetaDataRetriever: ExpirationMetaDataRetriever,
private val machineLocale: OppiaLocale.MachineLocale,
private val currentBuildFlavor: BuildFlavor
private val currentBuildFlavor: BuildFlavor,
private val deprecationController: DeprecationController,
@EnableAppAndOsDeprecation
private val enableAppAndOsDeprecation: PlatformParameterValue<Boolean>,
@OptionalAppUpdateVersionCode
private val optionalAppUpdateVersionCode: PlatformParameterValue<Int>,
@ForcedAppUpdateVersionCode
private val forcedAppUpdateVersionCode: PlatformParameterValue<Int>,
@LowestSupportedApiLevel
private val lowestSupportedApiLevel: PlatformParameterValue<Int>
) {
private val onboardingFlowStore by lazy {
cacheStoreFactory.create("on_boarding_flow", OnboardingState.getDefaultInstance())
Expand Down Expand Up @@ -116,11 +133,51 @@ class AppStartupStateController @Inject constructor(
}

private fun computeAppStartupMode(onboardingState: OnboardingState): StartupMode {
return when {
hasAppExpired() -> StartupMode.APP_IS_DEPRECATED
onboardingState.alreadyOnboardedApp -> StartupMode.USER_IS_ONBOARDED
else -> StartupMode.USER_NOT_YET_ONBOARDED
// Return old logic if app and os feature flag is not enabled
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
if (!enableAppAndOsDeprecation.value) {
return when {
hasAppExpired() -> StartupMode.APP_IS_DEPRECATED
onboardingState.alreadyOnboardedApp -> StartupMode.USER_IS_ONBOARDED
else -> StartupMode.USER_NOT_YET_ONBOARDED
}
}

val deprecationDataProvider = deprecationController.getDeprecationDatabase()

var deprecationDatabase = DeprecationResponseDatabase.newBuilder().build()

runBlocking {
deprecationDataProvider.retrieveData().transform {
deprecationDatabase = it
}
}
adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved

val appVersionCode = Build.VERSION.SDK_INT

val osIsDeprecated = lowestSupportedApiLevel.value > appVersionCode &&
deprecationDatabase.osDeprecationResponse.deprecatedVersion != appVersionCode
val appUpdateIsAvailable = optionalAppUpdateVersionCode.value > appVersionCode ||
forcedAppUpdateVersionCode.value > appVersionCode

if (onboardingState.alreadyOnboardedApp) {
if (osIsDeprecated) {
return StartupMode.OS_IS_DEPRECATED
}

if (appUpdateIsAvailable) {
if (forcedAppUpdateVersionCode.value > appVersionCode) {
return StartupMode.APP_IS_DEPRECATED
}

if (deprecationDatabase.appDeprecationResponse.deprecatedVersion !=
optionalAppUpdateVersionCode.value
) {
return StartupMode.OPTIONAL_UPDATE_AVAILABLE
}
}

adhiamboperes marked this conversation as resolved.
Show resolved Hide resolved
return StartupMode.USER_IS_ONBOARDED
} else return StartupMode.USER_NOT_YET_ONBOARDED
}

private fun computeBuildNoticeMode(
Expand Down
Loading