You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/components/ReviewPromptController.kt

89 lines
3.1 KiB
Kotlin

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.components
import android.app.Activity
import android.content.Context
import androidx.annotation.VisibleForTesting
import org.mozilla.fenix.utils.Settings
/**
* Interface that describes the settings needed to track the Review Prompt.
*/
interface ReviewSettings {
var numberOfAppLaunches: Int
val isDefaultBrowser: Boolean
var lastReviewPromptTimeInMillis: Long
}
/**
* Wraps `Settings` to conform to `ReviewSettings`.
*/
class FenixReviewSettings(
val settings: Settings
) : ReviewSettings {
override var numberOfAppLaunches: Int
get() = settings.numberOfAppLaunches
set(value) { settings.numberOfAppLaunches = value }
override val isDefaultBrowser: Boolean
get() = settings.isDefaultBrowser()
override var lastReviewPromptTimeInMillis: Long
get() = settings.lastReviewPromptTimeInMillis
set(value) { settings.lastReviewPromptTimeInMillis = value }
}
/**
* Controls the Review Prompt behavior.
*/
class ReviewPromptController(
private val context: Context,
private val reviewSettings: ReviewSettings,
private val timeNowInMillis: () -> Long = { System.currentTimeMillis() },
private val tryPromptReview: suspend (Activity) -> Unit = { _ ->
}
) {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@Volatile var reviewPromptIsReady = false
suspend fun promptReview(activity: Activity) {
if (shouldShowPrompt()) {
tryPromptReview(activity)
reviewSettings.lastReviewPromptTimeInMillis = timeNowInMillis()
}
}
fun trackApplicationLaunch() {
reviewSettings.numberOfAppLaunches = reviewSettings.numberOfAppLaunches + 1
// We only want to show the the prompt after we've finished "launching" the application.
reviewPromptIsReady = true
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
fun shouldShowPrompt(): Boolean {
if (!reviewPromptIsReady) {
return false
} else {
// We only want to try to show it once to avoid unnecessary disk reads
reviewPromptIsReady = false
}
if (!reviewSettings.isDefaultBrowser) { return false }
val hasOpenedFiveTimes = reviewSettings.numberOfAppLaunches >= NUMBER_OF_LAUNCHES_REQUIRED
val now = timeNowInMillis()
val apprxFourMonthsAgo = now - (APPRX_MONTH_IN_MILLIS * NUMBER_OF_MONTHS_TO_PASS)
val lastPrompt = reviewSettings.lastReviewPromptTimeInMillis
val hasNotBeenPromptedLastFourMonths = lastPrompt == 0L || lastPrompt <= apprxFourMonthsAgo
return hasOpenedFiveTimes && hasNotBeenPromptedLastFourMonths
}
companion object {
private const val APPRX_MONTH_IN_MILLIS: Long = 1000L * 60L * 60L * 24L * 30L
private const val NUMBER_OF_LAUNCHES_REQUIRED = 5
private const val NUMBER_OF_MONTHS_TO_PASS = 4
}
}