Skip to content

Commit

Permalink
feat: Add logic to tie together all pieces of the previous deprecatio…
Browse files Browse the repository at this point in the history
…n milestones
  • Loading branch information
kkmurerwa committed Nov 28, 2023
1 parent 6fec2e2 commit 695c2b2
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 26 deletions.
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
}
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
16 changes: 6 additions & 10 deletions app/src/main/java/org/oppia/android/app/splash/SplashActivity.kt
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()
DeprecationNoticeActionType.DISMISS -> handleOnDeprecationNoticeUpdateButtonClicked()
DeprecationNoticeActionType.UPDATE -> handleOnDeprecationNoticeDialogDismissed()
}
}

/** 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. */
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) {
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
@@ -1,16 +1,25 @@
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.BuildConfig
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 +32,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 +134,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
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
}
}

val appVersionCode = BuildConfig.VERSION_CODE

val osIsDeprecated = lowestSupportedApiLevel.value > Build.VERSION.SDK_INT &&
deprecationDatabase.osDeprecationResponse.deprecatedVersion != Build.VERSION.SDK_INT
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
}
}

return StartupMode.USER_IS_ONBOARDED
} else return StartupMode.USER_NOT_YET_ONBOARDED
}

private fun computeBuildNoticeMode(
Expand Down

0 comments on commit 695c2b2

Please sign in to comment.