Skip to content

Instantly share code, notes, and snippets.

@biodunalfet
Forked from PurpleBooth/README-Template.md
Last active March 10, 2020 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save biodunalfet/e172278960447e90e35038db7695c400 to your computer and use it in GitHub Desktop.
Save biodunalfet/e172278960447e90e35038db7695c400 to your computer and use it in GitHub Desktop.
A template to make good README.md

Owners

Upseller

This module helps coordinate upsell flows on different pages across the app

The Problem

To upsell a feature on a certain page, one has to be aware of all the other features that are also being tried to be "upsold" on that same page and their timing and implementation logic behind it. In order to reduce this complexity and to prevent the user from being in states where multiple features are being shown to the users at the same time, this module was created

Solution

The upseller module encapsulates the timing and implementation logic into UpSells. Each UpSell contains the following properties and functions:

id - A unique identifier for each UpSell

active - The current internal state of the UpSell. It could be true or false.

becomesInActiveOnceShown - This flag is used for "weak" UpSells that only need to be shown once and set to inactive immediately after.

source - This suspend function defines the external condition which must be fulfilled for an UpSell to be eligible for running. For example, a Biometrics UpSell would have a source = { isFingerprintOnboardingRequired() }

fun shouldRun - defines if an UpSell should be run (based on timing strategy)

fun preCheckUpdateState - before a shouldRun check is run, this function is called to update the state of the UpSell, if necessary. For example, in a LaunchCountUpSell, you want to increment the current launch counter before you do a shouldRun check.

fun postCheckUpdateState - after a shouldRun check is run, this function can be used to update the state of the UpSell, if necessary. For example, in a PeriodicUntilSoldUpSell, you want to update the lastChecked property.

fun setActive(active: Boolean) - used to activate/deactivate an UpSell

Types of UpSell

There are currently 4 types of UpSells based on timing strategy and implementation logic

  1. LaunchCountUpSell - used when you want to upsell a feature after a fixed number of screen launch
  2. ElapsedTimeUpSell - used when you want to upsell a feature a defined number of milliseconds (timeAfterRegistration) from a stated timeOfRegistration also in milliseconds
  3. FixedDateUpSell - used to upsell a feature on a defined executionDate
  4. PeriodicUntilSoldUpSell - used to upsell a feature periodically after period milliseconds

How to use

  1. Create a sealed class that defines the possible up-sells there are on a screen. See here for an full example
sealed class LoggedInScreenUpSell{
    object BiometricsUpSell : LoggedInScreenUpSell()
    class SpoUpSell(val socialProvider : String) : LoggedInScreenUpSell()
    object OneTouchUpSell : LoggedInScreenUpSell()
}
  1. Create a class e.g GetLoggedInMainActivityUpSells which gets an aggregated list of up-sells to be run on the LoggedInMainActivity screen.

  2. In the ViewModel of your screen, make a call to the aforementioned class GetLoggedInMainActivityUpSells to get the List. Pass this into the getNextUpSellInteractor(List<UpSell>) to fetch the next UpSell sealed class (defined in step 1) for the up-sell that's ready to be run. See here for a full example

viewModelScope.launch(coroutineContextProvider.main) {
   val upSellToRun = getLoggedInMainActivityUpSells(profilesInteractor)
   checkUpSells(upSellToRun)
}

private suspend fun checkUpSells(upSells: List<UpSell<out LoggedInScreenUpSell>>) {
       val upSellToRun = upNextUpSellInteractor(upSells)
       upSellToRun?.let {
           when (it) {
               is LoggedInScreenUpSell.BiometricsUpSell -> mutableActionState.value = ActionState.ShowBiometricsEnrol
               is LoggedInScreenUpSell.SpoUpSell -> mutableActionState.value = ActionState.ShowSocialPasswordOnboarding(it.socialProvider)
               is LoggedInScreenUpSell.OneTouchUpSell -> mutableActionState.value = ActionState.ShowOneTouchOnBoarding
           }
       }
   }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment