Commit c65348fe authored by Yunke Zhou's avatar Yunke Zhou Committed by Commit Bot

Oobe: add related info screen for better assistant flow

Bug: 1141307
Change-Id: I6a5499592dccc9a3eaffb35fe15e7c194cd8dc04
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2490005Reviewed-by: default avatarDenis Kuznetsov [CET] <antrim@chromium.org>
Commit-Queue: Yunke Zhou <yunkez@google.com>
Cr-Commit-Position: refs/heads/master@{#822099}
parent c1b2c196
......@@ -4321,6 +4321,18 @@
<message name="IDS_ASSISTANT_READY_SCREEN_MESSAGE" desc="Message for Assistant ready screen.">
When your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> is set up, press the Assistant button or say "Ok Google" to get help anytime. Go to Assistant settings to make changes.
</message>
<message name="IDS_ASSISTANT_RELATED_INFO_SCREEN_TITLE" desc="Title for assistant related info screen.">
Just say or type what you need
</message>
<message name="IDS_ASSISTANT_RELATED_INFO_SCREEN_MESSAGE" desc="Message for assistant related info screen.">
Get better, quicker answers with Assistant
</message>
<message name="IDS_ASSISTANT_RELATED_INFO_SCREEN_RETURNED_USER_TITLE" desc="Title for assistant related info screen for returned users.">
Your Google Assistant works here too
</message>
<message name="IDS_ASSISTANT_RELATED_INFO_SCREEN_RETURNED_USER_MESSAGE" desc="Message for assistant related info screen for returned users.">
Looks like you've already set up Assistant on a different device. Get even more out of your Assistant by turning on the following setting.
</message>
<message name="IDS_ASSISTANT_CONTINUE_BUTTON" desc="Continue button for asssitant optin flow.">
Continue
</message>
......
ab5449f73f222c00cf6a066be0135931c9f4f36c
\ No newline at end of file
561f81d42a789c58d3dd416a6ad10f59a15247f4
\ No newline at end of file
561f81d42a789c58d3dd416a6ad10f59a15247f4
\ No newline at end of file
ab5449f73f222c00cf6a066be0135931c9f4f36c
\ No newline at end of file
......@@ -62,10 +62,10 @@ constexpr char kAssistantUiAuditKey[] = "ui_audit_key";
constexpr char kAssistantOptInId[] = "assistant-optin-flow";
constexpr char kAssistantOptInFlowCard[] = "card";
constexpr char kLoading[] = "loading";
constexpr char kValueProp[] = "value-prop";
constexpr char kVoiceMatch[] = "voice-match";
constexpr char kThirdParty[] = "third-party";
constexpr char kGetMore[] = "get-more";
constexpr char kValueProp[] = "valueProp";
constexpr char kVoiceMatch[] = "voiceMatch";
constexpr char kThirdParty[] = "thirdParty";
constexpr char kGetMore[] = "getMore";
const test::UIPath kAssistantLoading = {kAssistantOptInId,
kAssistantOptInFlowCard, kLoading};
......
......@@ -4,6 +4,7 @@
<include src="assistant_get_more.html">
<include src="assistant_loading.html">
<include src="assistant_related_info.html">
<include src="assistant_third_party.html">
<include src="assistant_value_prop.html">
<include src="assistant_voice_match.html">
......@@ -20,13 +21,15 @@
<link rel="stylesheet" href="assistant_value_prop.css">
<assistant-loading id="loading" hidden>
</assistant-loading>
<assistant-value-prop id="value-prop" hidden>
<assistant-value-prop id="valueProp" hidden>
</assistant-value-prop>
<assistant-third-party id="third-party" hidden>
<assistant-related-info id="relatedInfo" hidden>
</assistant-related-info>
<assistant-third-party id="thirdParty" hidden>
</assistant-third-party>
<assistant-voice-match id="voice-match" hidden>
<assistant-voice-match id="voiceMatch" hidden>
</assistant-voice-match>
<assistant-get-more id="get-more" hidden>
<assistant-get-more id="getMore" hidden>
</assistant-get-more>
</template>
</dom-module>
......@@ -8,6 +8,7 @@
// <include src="browser_proxy.js">
// <include src="assistant_get_more.js">
// <include src="assistant_loading.js">
// <include src="assistant_related_info.js">
// <include src="assistant_third_party.js">
// <include src="assistant_value_prop.js">
// <include src="assistant_voice_match.js">
......@@ -70,18 +71,18 @@ Polymer({
this.boundOnScreenLoadingError = this.onScreenLoadingError.bind(this);
this.boundOnScreenLoaded = this.onScreenLoaded.bind(this);
this.$['loading'].onBeforeShow();
this.$['loading'].addEventListener('reload', this.onReload.bind(this));
this.$.loading.onBeforeShow();
this.$.loading.addEventListener('reload', this.onReload.bind(this));
switch (this.flowType) {
case this.FlowType.SPEAKER_ID_ENROLLMENT:
case this.FlowType.SPEAKER_ID_RETRAIN:
this.$['value-prop'].hidden = true;
this.$['voice-match'].isFirstScreen = true;
this.showScreen(this.$['voice-match']);
this.$.valueProp.hidden = true;
this.$.voiceMatch.isFirstScreen = true;
this.showScreen(this.$.voiceMatch);
break;
default:
this.showScreen(this.$['value-prop']);
this.showScreen(this.$.valueProp);
}
this.browserProxy_.initialized([this.flowType]);
},
......@@ -93,10 +94,13 @@ Polymer({
reloadContent(data) {
this.voiceMatchEnforcedOff = data['voiceMatchEnforcedOff'];
this.voiceMatchDisabled = loadTimeData.getBoolean('voiceMatchDisabled');
this.betterAssistantEnabled =
loadTimeData.getBoolean('betterAssistantEnabled');
data['flowType'] = this.flowType;
this.$['value-prop'].reloadContent(data);
this.$['third-party'].reloadContent(data);
this.$['get-more'].reloadContent(data);
this.$.valueProp.reloadContent(data);
this.$.relatedInfo.reloadContent(data);
this.$.thirdParty.reloadContent(data);
this.$.getMore.reloadContent(data);
},
/**
......@@ -107,13 +111,13 @@ Polymer({
addSettingZippy(type, data) {
switch (type) {
case 'settings':
this.$['value-prop'].addSettingZippy(data);
this.$.valueProp.addSettingZippy(data);
break;
case 'disclosure':
this.$['third-party'].addSettingZippy(data);
this.$.thirdParty.addSettingZippy(data);
break;
case 'get-more':
this.$['get-more'].addSettingZippy(data);
this.$.getMore.addSettingZippy(data);
break;
default:
console.error('Undefined zippy data type: ' + type);
......@@ -125,26 +129,38 @@ Polymer({
*/
showNextScreen() {
switch (this.currentScreen) {
case this.$['value-prop']:
this.showScreen(this.$['third-party']);
case this.$.valueProp:
if (this.betterAssistantEnabled) {
this.showScreen(this.$.relatedInfo);
} else {
this.showScreen(this.$.thirdParty);
}
break;
case this.$.relatedInfo:
if (this.voiceMatchEnforcedOff || this.voiceMatchDisabled) {
this.browserProxy_.flowFinished();
} else {
this.showScreen(this.$.voiceMatch);
}
break;
case this.$['third-party']:
case this.$.thirdParty:
if (this.voiceMatchEnforcedOff || this.voiceMatchDisabled) {
this.showScreen(this.$['get-more']);
this.showScreen(this.$.getMore);
} else {
this.showScreen(this.$['voice-match']);
this.showScreen(this.$.voiceMatch);
}
break;
case this.$['voice-match']:
case this.$.voiceMatch:
if (this.flowType == this.FlowType.SPEAKER_ID_ENROLLMENT ||
this.flowType == this.FlowType.SPEAKER_ID_RETRAIN) {
this.flowType == this.FlowType.SPEAKER_ID_RETRAIN ||
this.betterAssistantEnabled) {
this.browserProxy_.flowFinished();
} else {
this.showScreen(this.$['get-more']);
this.showScreen(this.$.getMore);
}
break;
case this.$['get-more']:
this.showScreen(this.$['ready']);
case this.$.getMore:
this.browserProxy_.flowFinished();
break;
default:
console.error('Undefined');
......@@ -157,18 +173,18 @@ Polymer({
* @param {string} state the voice match state.
*/
onVoiceMatchUpdate(state) {
if (!this.currentScreen == this.$['voice-match']) {
if (!this.currentScreen == this.$.voiceMatch) {
return;
}
switch (state) {
case 'listen':
this.$['voice-match'].listenForHotword();
this.$.voiceMatch.listenForHotword();
break;
case 'process':
this.$['voice-match'].processingHotword();
this.$.voiceMatch.processingHotword();
break;
case 'done':
this.$['voice-match'].voiceMatchDone();
this.$.voiceMatch.voiceMatchDone();
break;
case 'failure':
this.onScreenLoadingError();
......@@ -188,7 +204,7 @@ Polymer({
return;
}
this.$['loading'].hidden = true;
this.$.loading.hidden = true;
screen.hidden = false;
screen.addEventListener('loading', this.boundShowLoadingScreen);
screen.addEventListener('error', this.boundOnScreenLoadingError);
......@@ -211,18 +227,18 @@ Polymer({
* Show the loading screen.
*/
showLoadingScreen() {
this.$['loading'].hidden = false;
this.$.loading.hidden = false;
this.currentScreen.hidden = true;
this.$['loading'].onShow();
this.$.loading.onShow();
},
/**
* Called when the screen failed to load.
*/
onScreenLoadingError() {
this.$['loading'].hidden = false;
this.$.loading.hidden = false;
this.currentScreen.hidden = true;
this.$['loading'].onErrorOccurred();
this.$.loading.onErrorOccurred();
},
/**
......@@ -230,8 +246,8 @@ Polymer({
*/
onScreenLoaded() {
this.currentScreen.hidden = false;
this.$['loading'].hidden = true;
this.$['loading'].onPageLoaded();
this.$.loading.hidden = true;
this.$.loading.onPageLoaded();
},
/**
......
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<dom-module id="assistant-related-info">
<template>
<style include="oobe-dialog-host">
oobe-dialog {
--oobe-dialog-content-padding-top: 48px;
}
#image {
display: block;
height: 186px;
margin: auto;
}
.vertical-line {
background-color: var(--google-grey-300);
height: 186px;
margin: 0 24px 0 24px;
width: 1px;
}
</style>
<link rel="stylesheet" href="assistant_shared_styles.css">
<oobe-dialog id="related-info-dialog" role="dialog" has-buttons hide-shadow
title-key="[[titleKey]]" subtitle-key="[[contentKey]]"
aria-label$="[[i18nDynamic(locale, titleKey)]]">
<img id="logo" slot="oobe-icon" src="assistant_logo.png"
aria-label$="[[i18nDynamic(locale, 'assistantLogo')]]">
<div slot="footer" class="layout horizontal">
<div id="image-container" class="flex">
<img id="image" class="oobe-illustration" aria-hidden="true"
src="assistant_ready.svg">
</div>
<div class="vertical-line"></div>
<div id="contents-container" class="flex">
<setting-zippy id="zippy-context" hide-line popup-style>
<div id="title-context" slot="title" aria-hidden="true">
[[i18nDynamic(locale, 'assistantScreenContextTitle')]]
</div>
<div id="description-context" slot="content" aria-hidden="true">
[[i18nDynamic(locale, 'assistantScreenContextDesc')]]
</div>
</setting-zippy>
</div>
</div>
<div slot="bottom-buttons" class="layout horizontal end-justified">
<oobe-text-button id="skip-button" disabled="[[loading]]"
text-key="assistantOptinNoThanksButton" on-click="onSkipTap_">
</oobe-text-button>
<oobe-text-button id="next-button" inverse disabled="[[loading]]"
text-key="assistantOptinAgreeButton" on-click="onNextTap_">
</oobe-text-button>
</div>
</oobe-dialog>
</template>
</dom-module>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Polymer element for displaying material design assistant
* related info screen.
*
* Event 'loading' will be fired when the page is loading/reloading.
* Event 'loaded' will be fired when the page has been successfully loaded.
*/
/**
* Name of the screen.
* @type {string}
*/
const RELATED_INFO_SCREEN_ID = 'RelatedInfoScreen';
Polymer({
is: 'assistant-related-info',
behaviors: [OobeI18nBehavior, OobeDialogHostBehavior],
properties: {
/**
* Whether page content is loading.
*/
loading: {
type: Boolean,
value: true,
},
/**
* Title key of the screen.
*/
titleKey: {
type: String,
value: 'assistantRelatedInfoTitle',
},
/**
* Content key of the screen.
*/
contentKey: {
type: String,
value: 'assistantRelatedInfoMessage',
},
},
/**
* Whether all the consent text strings has been successfully loaded.
* @type {boolean}
* @private
*/
consentStringLoaded_: false,
/**
* Whether the screen has been shown to the user.
* @type {boolean}
* @private
*/
screenShown_: false,
/** @private {?assistant.BrowserProxy} */
browserProxy_: null,
/**
* On-tap event handler for next button.
*
* @private
*/
onNextTap_() {
if (this.loading) {
return;
}
this.loading = true;
this.browserProxy_.userActed(RELATED_INFO_SCREEN_ID, ['next-pressed']);
},
/**
* On-tap event handler for skip button.
*
* @private
*/
onSkipTap_() {
if (this.loading) {
return;
}
this.loading = true;
this.browserProxy_.userActed(RELATED_INFO_SCREEN_ID, ['skip-pressed']);
},
/** @override */
created() {
this.browserProxy_ = assistant.BrowserProxyImpl.getInstance();
},
/**
* Reloads the page.
*/
reloadPage() {
this.fire('loading');
this.loading = true;
},
/**
* Reload the page with the given consent string text data.
*/
reloadContent(data) {
this.titleKey = data['activityControlNeeded'] ?
'assistantRelatedInfoTitle' :
'assistantRelatedInfoReturnedUserTitle';
this.contentKey = data['activityControlNeeded'] ?
'assistantRelatedInfoMessage' :
'assistantRelatedInfoReturnedUserMessage';
this.consentStringLoaded_ = true;
this.onPageLoaded();
},
/**
* Handles event when all the page content has been loaded.
*/
onPageLoaded() {
this.fire('loaded');
this.loading = false;
this.$['next-button'].focus();
if (!this.hidden && !this.screenShown_) {
this.browserProxy_.screenShown(RELATED_INFO_SCREEN_ID);
this.screenShown_ = true;
}
},
/**
* Signal from host to show the screen.
*/
onShow() {
if (!this.consentStringLoaded_) {
this.reloadPage();
} else {
Polymer.RenderStatus.afterNextRender(
this, () => this.$['next-button'].focus());
this.browserProxy_.screenShown(RELATED_INFO_SCREEN_ID);
this.screenShown_ = true;
}
},
});
......@@ -184,6 +184,9 @@ base::Value GetSettingsUiStrings(const assistant::SettingsUi& settings_ui,
auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui();
base::Value dictionary(base::Value::Type::DICTIONARY);
dictionary.SetKey("activityControlNeeded",
base::Value(activity_control_needed));
// Add activity control string constants.
if (activity_control_needed) {
scoped_refptr<base::RefCountedMemory> image =
......
......@@ -37,6 +37,9 @@ enum AssistantOptInFlowStatus {
VOICE_MATCH_ENROLLMENT_DONE = 13,
VOICE_MATCH_ENROLLMENT_SKIPPED = 14,
VOICE_MATCH_ENROLLMENT_ERROR = 15,
RELATED_INFO_SHOWN = 16,
RELATED_INFO_ACCEPTED = 17,
RELATED_INFO_SKIPPED = 18,
// Magic constant used by the histogram macros.
kMaxValue = VOICE_MATCH_ENROLLMENT_ERROR
};
......
......@@ -74,6 +74,17 @@ void AssistantOptInFlowScreenHandler::DeclareLocalizedValues(
builder->Add("assistantOptinSkipButton", IDS_ASSISTANT_OPT_IN_SKIP_BUTTON);
builder->Add("assistantOptinRetryButton", IDS_ASSISTANT_OPT_IN_RETRY_BUTTON);
builder->Add("assistantUserImage", IDS_ASSISTANT_OOBE_USER_IMAGE);
builder->Add("assistantRelatedInfoTitle",
IDS_ASSISTANT_RELATED_INFO_SCREEN_TITLE);
builder->Add("assistantRelatedInfoMessage",
IDS_ASSISTANT_RELATED_INFO_SCREEN_MESSAGE);
builder->Add("assistantRelatedInfoReturnedUserTitle",
IDS_ASSISTANT_RELATED_INFO_SCREEN_RETURNED_USER_TITLE);
builder->Add("assistantRelatedInfoReturnedUserMessage",
IDS_ASSISTANT_RELATED_INFO_SCREEN_RETURNED_USER_MESSAGE);
builder->Add("assistantScreenContextTitle",
IDS_ASSISTANT_SCREEN_CONTEXT_TITLE);
builder->Add("assistantScreenContextDesc", IDS_ASSISTANT_SCREEN_CONTEXT_DESC);
builder->Add("assistantVoiceMatchTitle", IDS_ASSISTANT_VOICE_MATCH_TITLE);
builder->Add("assistantVoiceMatchMessage", IDS_ASSISTANT_VOICE_MATCH_MESSAGE);
builder->Add("assistantVoiceMatchNoDspMessage",
......@@ -121,6 +132,9 @@ void AssistantOptInFlowScreenHandler::RegisterMessages() {
AddCallback(
"login.AssistantOptInFlowScreen.ValuePropScreen.userActed",
&AssistantOptInFlowScreenHandler::HandleValuePropScreenUserAction);
AddCallback(
"login.AssistantOptInFlowScreen.RelatedInfoScreen.userActed",
&AssistantOptInFlowScreenHandler::HandleRelatedInfoScreenUserAction);
AddCallback(
"login.AssistantOptInFlowScreen.ThirdPartyScreen.userActed",
&AssistantOptInFlowScreenHandler::HandleThirdPartyScreenUserAction);
......@@ -131,6 +145,8 @@ void AssistantOptInFlowScreenHandler::RegisterMessages() {
&AssistantOptInFlowScreenHandler::HandleGetMoreScreenUserAction);
AddCallback("login.AssistantOptInFlowScreen.ValuePropScreen.screenShown",
&AssistantOptInFlowScreenHandler::HandleValuePropScreenShown);
AddCallback("login.AssistantOptInFlowScreen.RelatedInfoScreen.screenShown",
&AssistantOptInFlowScreenHandler::HandleRelatedInfoScreenShown);
AddCallback("login.AssistantOptInFlowScreen.ThirdPartyScreen.screenShown",
&AssistantOptInFlowScreenHandler::HandleThirdPartyScreenShown);
AddCallback("login.AssistantOptInFlowScreen.VoiceMatchScreen.screenShown",
......@@ -151,6 +167,8 @@ void AssistantOptInFlowScreenHandler::GetAdditionalParameters(
dict->SetBoolean("deviceHasNoBattery", !DeviceHasBattery());
dict->SetBoolean("voiceMatchDisabled",
chromeos::assistant::features::IsVoiceMatchDisabled());
dict->SetBoolean("betterAssistantEnabled",
chromeos::assistant::features::IsBetterAssistantEnabled());
BaseScreenHandler::GetAdditionalParameters(dict);
}
......@@ -254,6 +272,14 @@ void AssistantOptInFlowScreenHandler::OnActivityControlOptInResult(
}
}
void AssistantOptInFlowScreenHandler::OnScreenContextOptInResult(
bool opted_in) {
RecordAssistantOptInStatus(opted_in ? RELATED_INFO_ACCEPTED
: RELATED_INFO_SKIPPED);
PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs();
prefs->SetBoolean(assistant::prefs::kAssistantContextEnabled, opted_in);
}
void AssistantOptInFlowScreenHandler::OnEmailOptInResult(bool opted_in) {
if (!email_optin_needed_) {
DCHECK(!opted_in);
......@@ -499,6 +525,17 @@ void AssistantOptInFlowScreenHandler::HandleValuePropScreenUserAction(
}
}
void AssistantOptInFlowScreenHandler::HandleRelatedInfoScreenUserAction(
const std::string& action) {
if (action == kSkipPressed) {
OnScreenContextOptInResult(false);
ShowNextScreen();
} else if (action == kNextPressed) {
OnScreenContextOptInResult(true);
ShowNextScreen();
}
}
void AssistantOptInFlowScreenHandler::HandleThirdPartyScreenUserAction(
const std::string& action) {
if (action == kNextPressed) {
......@@ -550,6 +587,10 @@ void AssistantOptInFlowScreenHandler::HandleValuePropScreenShown() {
RecordAssistantOptInStatus(ACTIVITY_CONTROL_SHOWN);
}
void AssistantOptInFlowScreenHandler::HandleRelatedInfoScreenShown() {
RecordAssistantOptInStatus(RELATED_INFO_SHOWN);
}
void AssistantOptInFlowScreenHandler::HandleThirdPartyScreenShown() {
RecordAssistantOptInStatus(THIRD_PARTY_SHOWN);
}
......
......@@ -86,6 +86,7 @@ class AssistantOptInFlowScreenHandler
// Handle user opt-in result.
void OnActivityControlOptInResult(bool opted_in);
void OnScreenContextOptInResult(bool opted_in);
void OnEmailOptInResult(bool opted_in);
// Called when the UI dialog is closed.
......@@ -116,11 +117,13 @@ class AssistantOptInFlowScreenHandler
// Handler for JS WebUI message.
void HandleValuePropScreenUserAction(const std::string& action);
void HandleRelatedInfoScreenUserAction(const std::string& action);
void HandleThirdPartyScreenUserAction(const std::string& action);
void HandleVoiceMatchScreenUserAction(const std::string& action);
void HandleGetMoreScreenUserAction(const bool screen_context,
const bool email_opted_in);
void HandleValuePropScreenShown();
void HandleRelatedInfoScreenShown();
void HandleThirdPartyScreenShown();
void HandleVoiceMatchScreenShown();
void HandleGetMoreScreenShown();
......
......@@ -41,6 +41,9 @@ const base::Feature kAssistantTimersV2{"AssistantTimersV2",
const base::Feature kAssistantWaitScheduling{"AssistantWaitScheduling",
base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kEnableBetterAssistant{"EnableBetterAssistant",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kEnableBloom{"EnableBloom",
base::FEATURE_DISABLED_BY_DEFAULT};
......@@ -84,6 +87,10 @@ bool IsAudioEraserEnabled() {
return base::FeatureList::IsEnabled(kAssistantAudioEraser);
}
bool IsBetterAssistantEnabled() {
return base::FeatureList::IsEnabled(kEnableBetterAssistant);
}
bool IsBetterOnboardingEnabled() {
return base::FeatureList::IsEnabled(kAssistantBetterOnboarding);
}
......
......@@ -58,6 +58,10 @@ extern const base::Feature kAssistantWaitScheduling;
COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
extern const base::Feature kEnableAmbientAssistant;
// Enables Better Assistant.
COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
extern const base::Feature kEnableBetterAssistant;
// Enables Bloom integration.
COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
extern const base::Feature kEnableBloom;
......@@ -93,6 +97,8 @@ COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsAppSupportEnabled();
COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsAudioEraserEnabled();
COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsBetterAssistantEnabled();
COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsBetterOnboardingEnabled();
COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsBloomEnabled();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment