Merge "Only run search edu when enabled, also make code more generic." into 24D1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
436f342b5a
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user