Merge "Only run search edu when enabled, also make code more generic." into 24D1-dev

This commit is contained in:
Saumya Prakash
2024-04-25 22:10:32 +00:00
committed by Android (Google) Code Review
10 changed files with 204 additions and 3 deletions
@@ -299,6 +299,8 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
*/
public void showEduOnAppLaunch() {
if (!shouldShowEduOnAppLaunch()) {
// Called in case the edu finishes and search edu is still pending
mControllers.taskbarEduTooltipController.maybeShowSearchEdu();
return;
}
@@ -299,7 +299,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
isDesktopMode
? new DesktopTaskbarRecentAppsController(this)
: TaskbarRecentAppsController.DEFAULT,
new TaskbarEduTooltipController(this),
TaskbarEduTooltipController.newInstance(this),
new KeyboardQuickSwitchController(),
new TaskbarPinningController(this),
bubbleControllersOptional);
@@ -15,7 +15,13 @@
*/
package com.android.launcher3.taskbar
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.SpannableString
import android.text.method.LinkMovementMethod
import android.text.style.URLSpan
import android.view.Gravity
import android.view.View
import android.view.View.GONE
@@ -24,10 +30,13 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.MarginLayoutParams
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.TextView
import androidx.annotation.IntDef
import androidx.annotation.LayoutRes
import androidx.core.text.HtmlCompat
import androidx.core.view.updateLayoutParams
import com.airbnb.lottie.LottieAnimationView
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning
@@ -35,6 +44,9 @@ import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOH
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
import com.android.launcher3.util.OnboardingPrefs.TASKBAR_SEARCH_EDU_SEEN
import com.android.launcher3.util.ResourceBasedOverride
import com.android.launcher3.views.ActivityContext
import com.android.launcher3.views.BaseDragLayer
import com.android.quickstep.util.LottieAnimationColorUtils
import java.io.PrintWriter
@@ -52,6 +64,10 @@ const val TOOLTIP_STEP_PINNING = 2
* This value should match the maximum count for [TASKBAR_EDU_TOOLTIP_STEP].
*/
const val TOOLTIP_STEP_NONE = 3
/** The base URL for the Privacy Policy that will later be localized. */
private const val PRIVACY_POLICY_BASE_URL = "https://policies.google.com/privacy/embedded?hl="
/** The base URL for the Terms of Service that will later be localized. */
private const val TOS_BASE_URL = "https://policies.google.com/terms?hl="
/** Current step in the tooltip EDU flow. */
@Retention(AnnotationRetention.SOURCE)
@@ -59,9 +75,11 @@ const val TOOLTIP_STEP_NONE = 3
annotation class TaskbarEduTooltipStep
/** Controls stepping through the Taskbar tooltip EDU. */
class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
LoggableTaskbarController {
open class TaskbarEduTooltipController(context: Context) :
ResourceBasedOverride, LoggableTaskbarController {
protected val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
open val shouldShowSearchEdu = false
private val isTooltipEnabled: Boolean
get() = !Utilities.isRunningInTestHarness() && !activityContext.isPhoneMode
private val isOpen: Boolean
@@ -70,6 +88,15 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
get() = isTooltipEnabled && tooltipStep <= TOOLTIP_STEP_FEATURES
private lateinit var controllers: TaskbarControllers
// Keep track of whether the user has seen the Search Edu
private var userHasSeenSearchEdu: Boolean
get() {
return TASKBAR_SEARCH_EDU_SEEN.get(activityContext)
}
private set(seen) {
LauncherPrefs.get(activityContext).put(TASKBAR_SEARCH_EDU_SEEN, seen)
}
@TaskbarEduTooltipStep
var tooltipStep: Int
get() {
@@ -83,6 +110,8 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
fun init(controllers: TaskbarControllers) {
this.controllers = controllers
// We want to show the Search Edu right after pinning the taskbar, so we post it here
activityContext.dragLayer.post { maybeShowSearchEdu() }
}
/** Shows swipe EDU tooltip if it is the current [tooltipStep]. */
@@ -112,6 +141,7 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
fun maybeShowFeaturesEdu() {
if (!isTooltipEnabled || tooltipStep > TOOLTIP_STEP_FEATURES) {
maybeShowPinningEdu()
maybeShowSearchEdu()
return
}
@@ -207,6 +237,96 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
}
}
/**
* Shows standalone Search EDU tooltip if this EDU has not been seen.
*
* We show this standalone edu for users to learn to how to trigger Search from the pinned
* taskbar
*/
fun maybeShowSearchEdu() {
if (
!enableTaskbarPinning() ||
!DisplayController.isPinnedTaskbar(activityContext) ||
!isTooltipEnabled ||
!shouldShowSearchEdu ||
userHasSeenSearchEdu
) {
return
}
userHasSeenSearchEdu = true
inflateTooltip(R.layout.taskbar_edu_search)
tooltip?.run {
requireViewById<LottieAnimationView>(R.id.search_edu_animation).supportLightTheme()
val eduSubtitle: TextView = requireViewById(R.id.search_edu_text)
showDisclosureText(eduSubtitle)
updateLayoutParams<BaseDragLayer.LayoutParams> {
if (DisplayController.isTransientTaskbar(activityContext)) {
bottomMargin += activityContext.deviceProfile.taskbarHeight
}
// Unlike other tooltips, we want to align with the all apps button rather than
// center.
gravity = Gravity.BOTTOM
marginStart = 0
width =
resources.getDimensionPixelSize(
R.dimen.taskbar_edu_features_tooltip_width_with_one_feature
)
}
// Calculate the amount the tooltip must be shifted by to align with the action key
val allAppsButtonView = controllers.taskbarViewController.allAppsButtonView
if (allAppsButtonView != null) {
val allAppsIconLocation = allAppsButtonView.x + allAppsButtonView.width / 2
x = allAppsIconLocation - layoutParams.width / 2
}
show()
}
}
/**
* Set up the provided TextView to display legal disclosures. The method takes locale into
* account to show the appropriate links to regional disclosures.
*/
private fun TaskbarEduTooltip.showDisclosureText(
textView: TextView,
stringId: Int = R.string.taskbar_edu_search_disclosure,
) {
val locale = resources.configuration.locales[0]
val text =
SpannableString(
HtmlCompat.fromHtml(
resources.getString(
stringId,
PRIVACY_POLICY_BASE_URL + locale.language,
TOS_BASE_URL + locale.language,
),
HtmlCompat.FROM_HTML_MODE_COMPACT,
)
)
// Directly process URLSpan clicks
text.getSpans(0, text.length, URLSpan::class.java).forEach { urlSpan ->
val url: URLSpan =
object : URLSpan(urlSpan.url) {
override fun onClick(widget: View) {
val uri = Uri.parse(urlSpan.url)
val context = widget.context
val intent =
Intent(Intent.ACTION_VIEW, uri).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
}
val spanStart = text.getSpanStart(urlSpan)
val spanEnd = text.getSpanEnd(urlSpan)
val spanFlags = text.getSpanFlags(urlSpan)
text.removeSpan(urlSpan)
text.setSpan(url, spanStart, spanEnd, spanFlags)
}
textView.text = text
textView.movementMethod = LinkMovementMethod.getInstance()
}
/** Closes the current [tooltip]. */
fun hide() = tooltip?.close(true)
@@ -280,6 +400,17 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
pw?.println("$prefix\tisOpen=$isOpen")
pw?.println("$prefix\ttooltipStep=$tooltipStep")
}
companion object {
@JvmStatic
fun newInstance(context: Context): TaskbarEduTooltipController {
return ResourceBasedOverride.Overrides.getObject(
TaskbarEduTooltipController::class.java,
context,
R.string.taskbar_edu_tooltip_controller_class
)
}
}
}
/**