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
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.TaskbarEduTooltip.Title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/taskbar_search_edu_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/search_edu_animation" />
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/search_edu_animation"
|
||||
android:layout_width="@dimen/taskbar_edu_swipe_lottie_width"
|
||||
android:layout_height="@dimen/taskbar_edu_swipe_lottie_height"
|
||||
android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
|
||||
app:layout_constraintBottom_toTopOf="@id/search_edu_text"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:lottie_rawRes="@raw/taskbar_edu_search"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_loop="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/search_edu_text"
|
||||
style="@style/TextAppearance.TaskbarEduTooltip.Subtext"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/taskbar_edu_search_subtitle_text_size"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/search_edu_animation"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
File diff suppressed because one or more lines are too long
@@ -26,6 +26,7 @@
|
||||
<string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
|
||||
<string name="window_manager_proxy_class" translatable="false">com.android.quickstep.util.SystemWindowManagerProxy</string>
|
||||
<string name="widget_holder_factory_class" translatable="false">com.android.launcher3.uioverrides.QuickstepWidgetHolder$QuickstepHolderFactory</string>
|
||||
<string name="taskbar_edu_tooltip_controller_class" translatable="false">com.android.launcher3.taskbar.TaskbarEduTooltipController</string>
|
||||
|
||||
<!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
|
||||
determines how many thumbnails will be fetched in the background. -->
|
||||
|
||||
@@ -400,6 +400,7 @@
|
||||
<dimen name="taskbar_edu_features_tooltip_width_with_one_feature">412dp</dimen>
|
||||
<dimen name="taskbar_edu_features_tooltip_width_with_two_features">428dp</dimen>
|
||||
<dimen name="taskbar_edu_features_tooltip_width_with_three_features">624dp</dimen>
|
||||
<dimen name="taskbar_edu_search_subtitle_text_size">12sp</dimen>
|
||||
|
||||
<!--- Taskbar Pinning -->
|
||||
<dimen name="taskbar_pinning_popup_menu_width">300dp</dimen>
|
||||
|
||||
@@ -273,6 +273,10 @@
|
||||
<string name="taskbar_edu_pinning_title">Always show the Taskbar</string>
|
||||
<!-- Text in dialog that shows a user how to pin the Taskbar. [CHAR_LIMIT 150] -->
|
||||
<string name="taskbar_edu_pinning_standalone">To always show the Taskbar on the bottom of your screen, touch & hold the divider</string>
|
||||
<!-- Title in dialog that shows a user how to invoke the Search feature. [CHAR_LIMIT 150] -->
|
||||
<string name="taskbar_search_edu_title">Touch & hold the action key to search what\'s on your screen</string>
|
||||
<!-- Message showed to user to disclose privacy information they need to accept in order to access the app. [CHAR LIMIT=200]-->
|
||||
<string name="taskbar_edu_search_disclosure">This product uses the selected part of your screen to search. Google\'s <xliff:g example="https://policies.google.com/privacy/embedded" id="begin_privacy_link"><a href=\"%1$s\"></xliff:g>Privacy Policy<xliff:g id="end_privacy_link"></a></xliff:g> and <xliff:g example="https://policies.google.com/terms" id="begin_tos_link"><a href=\"%2$s\"></xliff:g>Terms of Service<xliff:g id="end_tos_link"></a></xliff:g> apply.</string>
|
||||
<!-- Text on button to exit a tutorial [CHAR_LIMIT=16] -->
|
||||
<string name="taskbar_edu_close">Close</string>
|
||||
<!-- Text on button to finish a tutorial [CHAR_LIMIT=16] -->
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
<!-- Menu id for feature flags -->
|
||||
<item type="id" name="menu_apply_flags" />
|
||||
|
||||
<string name="taskbar_edu_tooltip_controller_class" translatable="false"></string>
|
||||
|
||||
<!-- Default packages -->
|
||||
<string name="wallpaper_picker_package" translatable="false"></string>
|
||||
<string name="local_colors_extraction_class" translatable="false"></string>
|
||||
|
||||
@@ -75,4 +75,6 @@ object OnboardingPrefs {
|
||||
|
||||
@JvmField
|
||||
val HOTSEAT_LONGPRESS_TIP_SEEN = backedUpItem("launcher.hotseat_longpress_tip_seen", false)
|
||||
|
||||
@JvmField val TASKBAR_SEARCH_EDU_SEEN = backedUpItem("launcher.taskbar_search_edu_seen", false)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user