Commit e1653a48 authored by Monica Basta's avatar Monica Basta Committed by Chromium LUCI CQ

[LocalProfileCreation]: Implement select avatar dialog.

This CL implements the select avatar dialog for the local profile
creation in the profile picker.

Change-Id: I6a4fb4e49fbd2e5fc25af5b1c0045a529c416d6c
Bug: 1162443
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2606353
Commit-Queue: Monica Basta <msalama@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Reviewed-by: default avatarEsmael Elmoslimany <aee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842988}
parent c5331482
...@@ -788,11 +788,8 @@ ...@@ -788,11 +788,8 @@
<message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_DONE" desc="Label of a button to finish the profile creation."> <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_DONE" desc="Label of a button to finish the profile creation.">
Done Done
</message> </message>
<message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_OK" desc="Label of a button to confirm avatar selection."> <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_DONE" desc="Label of a button to close avatar selection.">
OK Done
</message>
<message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_CANCEL" desc="Label of a button to cancel avatar selection.">
Cancel
</message> </message>
<message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_INPUT_NAME" desc="Name of the input to configure the profile name in the profile customization window."> <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_INPUT_NAME" desc="Name of the input to configure the profile name in the profile customization window.">
Add a name or a label like Work, Personal, or Kids Add a name or a label like Work, Personal, or Kids
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {AvatarIcon} from 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.m.js';
import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js'; import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
/** /**
...@@ -112,16 +113,20 @@ export class ManageProfilesBrowserProxy { ...@@ -112,16 +113,20 @@ export class ManageProfilesBrowserProxy {
*/ */
loadSignInProfileCreationFlow(profileColor) {} loadSignInProfileCreationFlow(profileColor) {}
/**
* Retrieves custom avatar list for the select avatar dialog.
* * @return {!Promise<!Array<!AvatarIcon>>}
*/
getAvailableIcons() {}
/** /**
* Creates local profile * Creates local profile
* @param {string} profileName * @param {string} profileName
* @param {number} profileColor * @param {number} profileColor
* @param {string} avatarUrl * @param {number} avatarIndex
* @param {boolean} isGeneric
* @param {boolean} createShortcut * @param {boolean} createShortcut
*/ */
createProfile( createProfile(profileName, profileColor, avatarIndex, createShortcut) {}
profileName, profileColor, avatarUrl, isGeneric, createShortcut) {}
/** /**
* Sets the local profile name. * Sets the local profile name.
...@@ -187,11 +192,15 @@ export class ManageProfilesBrowserProxyImpl { ...@@ -187,11 +192,15 @@ export class ManageProfilesBrowserProxyImpl {
} }
/** @override */ /** @override */
createProfile( getAvailableIcons() {
profileName, profileColor, avatarUrl, isGeneric, createShortcut) { return sendWithPromise('getAvailableIcons');
}
/** @override */
createProfile(profileName, profileColor, avatarIndex, createShortcut) {
chrome.send( chrome.send(
'createProfile', 'createProfile',
[profileName, profileColor, avatarUrl, isGeneric, createShortcut]); [profileName, profileColor, avatarIndex, createShortcut]);
} }
/** @override */ /** @override */
......
...@@ -34,8 +34,10 @@ js_library("local_profile_customization") { ...@@ -34,8 +34,10 @@ js_library("local_profile_customization") {
"//ui/webui/resources/cr_components/customize_themes", "//ui/webui/resources/cr_components/customize_themes",
"//ui/webui/resources/cr_elements/cr_button:cr_button.m", "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
"//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m", "//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m",
"//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
"//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m", "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
"//ui/webui/resources/cr_elements/cr_input:cr_input.m", "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
"//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector.m",
"//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js:load_time_data.m",
"//ui/webui/resources/js:web_ui_listener_behavior.m", "//ui/webui/resources/js:web_ui_listener_behavior.m",
] ]
......
<style include="profile-creation-shared"> <style include="profile-creation-shared profile-picker-shared">
:host { :host {
--vertical-gap: 24px; --vertical-gap: 24px;
} }
...@@ -65,21 +65,6 @@ ...@@ -65,21 +65,6 @@
overflow: auto; overflow: auto;
} }
#wrapperContainer::-webkit-scrollbar {
width: var(--scrollbar-width);
}
/* Track */
#wrapperContainer::-webkit-scrollbar-track {
border-radius: var(--scrollbar-width);
}
/* Handle */
#wrapperContainer::-webkit-scrollbar-thumb {
background: var(--scrollbar-background);
border-radius: var(--scrollbar-width);
}
#wrapper > * { #wrapper > * {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;
...@@ -143,6 +128,32 @@ ...@@ -143,6 +128,32 @@
width: 111px; width: 111px;
} }
cr-profile-avatar-selector {
--avatar-size: 72px;
--avatar-spacing: 18px;
--avatar-grid-columns: 5;
height: fit-content;
padding-bottom: 15px;
padding-inline-start: 15px;
padding-top: 15px;
width: fit-content;
}
#selectAvatarWrapper {
height: 394px;
overflow-x: hidden;
overflow-y: auto;
}
#buttonContainer {
display: flex;
justify-content: flex-end;
}
#doneButton {
width : 32px;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
#nameInput { #nameInput {
--cr-input-placeholder-color: rgba(var(--google-grey-200-rgb), .5); --cr-input-placeholder-color: rgba(var(--google-grey-200-rgb), .5);
...@@ -164,11 +175,11 @@ ...@@ -164,11 +175,11 @@
--theme-shape-color:[[profileThemeInfo.themeShapeColor]]"> --theme-shape-color:[[profileThemeInfo.themeShapeColor]]">
<iron-icon class="banner" icon="profiles:customize-banner"></iron-icon> <iron-icon class="banner" icon="profiles:customize-banner"></iron-icon>
<cr-icon-button id="backButton" class="icon-arrow-back" <cr-icon-button id="backButton" class="icon-arrow-back"
on-click="onClickBack_" aria-label="$i18n{backButtonLabel}"> on-click="onClickBack_" aria-label="$i18n{backButtonLabel}">
</cr-icon-button> </cr-icon-button>
<h2 id="title">$i18n{localProfileCreationTitle}</h2> <h2 id="title">$i18n{localProfileCreationTitle}</h2>
<div id="avatarContainer"> <div id="avatarContainer">
<img class="avatar" alt="" src$="[[profileThemeInfo.themeGenericAvatar]]"> <img class="avatar" alt="" src$="[[selectedAvatar_.url]]">
<div id="customizeAvatarEllipse"></div> <div id="customizeAvatarEllipse"></div>
<cr-icon-button id="customizeAvatarIcon" <cr-icon-button id="customizeAvatarIcon"
iron-icon="profiles:create" on-click="onCustomizeAvatarClick_" iron-icon="profiles:create" on-click="onCustomizeAvatarClick_"
...@@ -177,7 +188,7 @@ ...@@ -177,7 +188,7 @@
</div> </div>
</div> </div>
<div id="wrapperContainer"> <div id="wrapperContainer" class="custom-scrollbar">
<div id="wrapper"> <div id="wrapper">
<cr-input id="nameInput" value="{{profileName_}}" pattern="[[pattern_]]" <cr-input id="nameInput" value="{{profileName_}}" pattern="[[pattern_]]"
placeholder="$i18n{createProfileNamePlaceholder}" placeholder="$i18n{createProfileNamePlaceholder}"
...@@ -198,11 +209,28 @@ ...@@ -198,11 +209,28 @@
<div class="footer"> <div class="footer">
<cr-checkbox checked="{{createShortcut_}}" <cr-checkbox checked="{{createShortcut_}}"
hidden="[[!isProfileShortcutsEnabled_]]"> hidden="[[!isProfileShortcutsEnabled_]]">
$i18n{createDesktopShortcutLabel} $i18n{createDesktopShortcutLabel}
</cr-checkbox> </cr-checkbox>
<cr-button id="save" class="action-button" on-click="onSaveClick_" <cr-button id="save" class="action-button" on-click="onSaveClick_"
disabled="[[isSaveDisabled_(createInProgress_, profileName_)]]"> disabled="[[isSaveDisabled_(createInProgress_, profileName_)]]">
$i18n{createProfileConfirm} $i18n{createProfileConfirm}
</cr-button> </cr-button>
</div> </div>
<cr-dialog id="selectAvatarDialog">
<div slot="title">$i18n{selectAnAvatarDialogTitle}</div>
<div slot="body">
<div id="selectAvatarWrapper" class="custom-scrollbar">
<cr-profile-avatar-selector avatars="[[availableIcons_]]"
selected-avatar="{{selectedAvatar_}}">
</cr-profile-avatar-selector>
</div>
</div>
<div id="buttonContainer" slot="button-container">
<cr-button id="doneButton" class="action-button"
on-click="onDoneSelectAvatarClick_">
$i18n{selectAvatarDoneButtonLabel}
</cr-button>
</div>
</cr-dialog>
...@@ -3,15 +3,20 @@ ...@@ -3,15 +3,20 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js'; import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/cr_components/customize_themes/customize_themes.js'; import 'chrome://resources/cr_components/customize_themes/customize_themes.js';
import 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.m.js';
import './shared_css.js'; import './shared_css.js';
import '../icons.js'; import '../icons.js';
import '../profile_picker_shared_css.js';
import {Theme, ThemeType} from 'chrome://resources/cr_components/customize_themes/customize_themes.mojom-webui.js'; import {Theme, ThemeType} from 'chrome://resources/cr_components/customize_themes/customize_themes.mojom-webui.js';
import {AvatarIcon} from 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.m.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
...@@ -25,7 +30,7 @@ Polymer({ ...@@ -25,7 +30,7 @@ Polymer({
_template: html`{__html_template__}`, _template: html`{__html_template__}`,
behaviors: [WebUIListenerBehavior], behaviors: [I18nBehavior, WebUIListenerBehavior],
properties: { properties: {
/** /**
...@@ -57,6 +62,34 @@ Polymer({ ...@@ -57,6 +62,34 @@ Polymer({
value: false, value: false,
}, },
/**
* Colored default generic avatar in the format expected by
* 'cr-profile-avatar-selector'
* @private {AvatarIcon}
*/
genericDefaultAvatar_: {
type: Object,
computed: 'getGenericDefaultAvatar_(profileThemeInfo.themeGenericAvatar)',
observer: 'onGenericDefaultAvatarChange_',
},
/**
* List of available profile icon Urls and labels.
* @private {!Array<!AvatarIcon>}
*/
availableIcons_: {
type: Array,
value() {
return [];
},
},
/**
* The currently selected profile avatar, if any.
* @private {?AvatarIcon}
*/
selectedAvatar_: Object,
/** /**
* The current profile name. * The current profile name.
* @private {string} * @private {string}
...@@ -98,6 +131,12 @@ Polymer({ ...@@ -98,6 +131,12 @@ Polymer({
type: String, type: String,
value: '.*\\S.*', value: '.*\\S.*',
}, },
/** @private */
defaultAvatarIndex_: {
type: Number,
value: () => loadTimeData.getInteger('placeholderAvatarIndex'),
},
}, },
listeners: { listeners: {
...@@ -118,6 +157,8 @@ Polymer({ ...@@ -118,6 +157,8 @@ Polymer({
this.sanityCheck_(); this.sanityCheck_();
this.addWebUIListener( this.addWebUIListener(
'create-profile-finished', () => this.handleCreateProfileFinished_()); 'create-profile-finished', () => this.handleCreateProfileFinished_());
this.manageProfilesBrowserProxy_.getAvailableIcons().then(
icons => this.setAvailableIcons_(icons));
}, },
/** @private */ /** @private */
...@@ -172,10 +213,9 @@ Polymer({ ...@@ -172,10 +213,9 @@ Polymer({
this.createInProgress_ = true; this.createInProgress_ = true;
const createShortcut = const createShortcut =
this.isProfileShortcutsEnabled_ && this.createShortcut_; this.isProfileShortcutsEnabled_ && this.createShortcut_;
// TODO(crbug.com/1115056): Support avatar selection.
this.manageProfilesBrowserProxy_.createProfile( this.manageProfilesBrowserProxy_.createProfile(
this.profileName_, this.profileThemeInfo.color, '', true, this.profileName_, this.profileThemeInfo.color,
createShortcut); this.selectedAvatar_.index, createShortcut);
}, },
/** @private */ /** @private */
...@@ -185,7 +225,49 @@ Polymer({ ...@@ -185,7 +225,49 @@ Polymer({
/** @private */ /** @private */
onCustomizeAvatarClick_() { onCustomizeAvatarClick_() {
// TODO(msalama): Open select avatar dialog. this.$.selectAvatarDialog.showModal();
},
/** @private */
onDoneSelectAvatarClick_() {
this.$.selectAvatarDialog.close();
},
/**
* @return {AvatarIcon}
* @private
*/
getGenericDefaultAvatar_() {
return /** @type {!AvatarIcon} */ ({
url: this.profileThemeInfo.themeGenericAvatar,
label: this.i18n('defaultAvatarLabel'),
index: this.defaultAvatarIndex_,
isGaiaAvatar: false,
selected: false,
});
},
/** @private */
onGenericDefaultAvatarChange_() {
this.setAvailableIcons_([...this.availableIcons_]);
if (!this.selectedAvatar_ ||
this.selectedAvatar_.index === this.defaultAvatarIndex_) {
this.selectedAvatar_ = this.genericDefaultAvatar_;
}
},
/**
* @param {!Array<!AvatarIcon>} icons
* @private
*/
setAvailableIcons_(icons) {
if (!this.genericDefaultAvatar_) {
this.availableIcons_ = icons;
return;
}
const offset =
icons.length > 0 && icons[0].index === this.defaultAvatarIndex_ ? 1 : 0;
this.availableIcons_ = [this.genericDefaultAvatar_, ...icons.slice(offset)];
}, },
/** @private */ /** @private */
......
...@@ -72,21 +72,6 @@ ...@@ -72,21 +72,6 @@
width: 100%; width: 100%;
} }
.profiles-container::-webkit-scrollbar {
width: var(--scrollbar-width);
}
/* Track */
.profiles-container::-webkit-scrollbar-track {
border-radius: var(--scrollbar-width);
}
/* Handle */
.profiles-container::-webkit-scrollbar-thumb {
background: var(--scrollbar-background);
border-radius: var(--scrollbar-width);
}
.profile-item { .profile-item {
align-items: center; align-items: center;
border-radius: 12px; border-radius: 12px;
...@@ -168,7 +153,7 @@ ...@@ -168,7 +153,7 @@
<h3>$i18n{mainViewSubtitle}</h3> <h3>$i18n{mainViewSubtitle}</h3>
</div> </div>
<div id="wrapper" hidden$="[[!profilesListLoaded_]]"> <div id="wrapper" hidden$="[[!profilesListLoaded_]]">
<div class="profiles-container"> <div class="profiles-container custom-scrollbar">
<template is="dom-repeat" items="[[profilesList_]]"> <template is="dom-repeat" items="[[profilesList_]]">
<profile-card <profile-card
class="profile-item" profile-state="[[item]]"> class="profile-item" profile-state="[[item]]">
......
...@@ -51,5 +51,20 @@ ...@@ -51,5 +51,20 @@
position: absolute; position: absolute;
width: 100%; width: 100%;
} }
.custom-scrollbar::-webkit-scrollbar {
width: var(--scrollbar-width);
}
/* Track */
.custom-scrollbar::-webkit-scrollbar-track {
border-radius: var(--scrollbar-width);
}
/* Handle */
.custom-scrollbar::-webkit-scrollbar-thumb {
background: var(--scrollbar-background);
border-radius: var(--scrollbar-width);
}
</style> </style>
</template> </template>
...@@ -208,6 +208,10 @@ void ProfilePickerHandler::RegisterMessages() { ...@@ -208,6 +208,10 @@ void ProfilePickerHandler::RegisterMessages() {
base::Unretained(this))); base::Unretained(this)));
// TODO(crbug.com/1115056): Consider renaming this message to // TODO(crbug.com/1115056): Consider renaming this message to
// 'createLocalProfile' as this is only used for local profiles. // 'createLocalProfile' as this is only used for local profiles.
web_ui()->RegisterMessageCallback(
"getAvailableIcons",
base::BindRepeating(&ProfilePickerHandler::HandleGetAvailableIcons,
base::Unretained(this)));
web_ui()->RegisterMessageCallback( web_ui()->RegisterMessageCallback(
"createProfile", "createProfile",
base::BindRepeating(&ProfilePickerHandler::HandleCreateProfile, base::BindRepeating(&ProfilePickerHandler::HandleCreateProfile,
...@@ -356,31 +360,33 @@ void ProfilePickerHandler::HandleGetProfileThemeInfo( ...@@ -356,31 +360,33 @@ void ProfilePickerHandler::HandleGetProfileThemeInfo(
ResolveJavascriptCallback(callback_id, std::move(dict)); ResolveJavascriptCallback(callback_id, std::move(dict));
} }
void ProfilePickerHandler::HandleGetAvailableIcons(
const base::ListValue* args) {
AllowJavascript();
CHECK_EQ(1U, args->GetSize());
const base::Value& callback_id = args->GetList()[0];
ResolveJavascriptCallback(callback_id,
*profiles::GetCustomProfileAvatarIconsAndLabels());
}
void ProfilePickerHandler::HandleCreateProfile(const base::ListValue* args) { void ProfilePickerHandler::HandleCreateProfile(const base::ListValue* args) {
// profileName, profileColor, avatarUrl, isGeneric, createShortcut CHECK_EQ(4U, args->GetList().size());
CHECK_EQ(5U, args->GetList().size());
base::string16 profile_name = base::string16 profile_name =
base::UTF8ToUTF16(args->GetList()[0].GetString()); base::UTF8ToUTF16(args->GetList()[0].GetString());
// profileColor is undefined for the default theme. // profileColor is undefined for the default theme.
base::Optional<SkColor> profile_color; base::Optional<SkColor> profile_color;
if (args->GetList()[1].is_int()) if (args->GetList()[1].is_int())
profile_color = args->GetList()[1].GetInt(); profile_color = args->GetList()[1].GetInt();
std::string avatar_url = args->GetList()[2].GetString(); size_t avatar_index = args->GetList()[2].GetInt();
bool is_generic = args->GetList()[3].GetBool(); bool create_shortcut = args->GetList()[3].GetBool();
bool create_shortcut = args->GetList()[4].GetBool();
DCHECK(base::IsStringASCII(avatar_url));
base::TrimWhitespace(profile_name, base::TRIM_ALL, &profile_name); base::TrimWhitespace(profile_name, base::TRIM_ALL, &profile_name);
CHECK(!profile_name.empty()); CHECK(!profile_name.empty());
if (is_generic) {
avatar_url = profiles::GetDefaultAvatarIconUrl(
profiles::GetPlaceholderAvatarIndex());
}
#ifndef NDEBUG #ifndef NDEBUG
size_t icon_index; DCHECK(profiles::IsDefaultAvatarIconIndex(avatar_index));
DCHECK(profiles::IsDefaultAvatarIconUrl(avatar_url, &icon_index));
#endif #endif
std::string avatar_url = profiles::GetDefaultAvatarIconUrl(avatar_index);
ProfileMetrics::LogProfileAddNewUser( ProfileMetrics::LogProfileAddNewUser(
ProfileMetrics::ADD_NEW_PROFILE_PICKER_LOCAL); ProfileMetrics::ADD_NEW_PROFILE_PICKER_LOCAL);
ProfileManager::CreateMultiProfileAsync( ProfileManager::CreateMultiProfileAsync(
......
...@@ -47,6 +47,7 @@ class ProfilePickerHandler : public content::WebUIMessageHandler, ...@@ -47,6 +47,7 @@ class ProfilePickerHandler : public content::WebUIMessageHandler,
void HandleLoadSignInProfileCreationFlow(const base::ListValue* args); void HandleLoadSignInProfileCreationFlow(const base::ListValue* args);
void HandleGetNewProfileSuggestedThemeInfo(const base::ListValue* args); void HandleGetNewProfileSuggestedThemeInfo(const base::ListValue* args);
void HandleGetProfileThemeInfo(const base::ListValue* args); void HandleGetProfileThemeInfo(const base::ListValue* args);
void HandleGetAvailableIcons(const base::ListValue* args);
void HandleCreateProfile(const base::ListValue* args); void HandleCreateProfile(const base::ListValue* args);
// |args| is unused. // |args| is unused.
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/policy/browser_signin_policy_handler.h" #include "chrome/browser/policy/browser_signin_policy_handler.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profile_shortcut_manager.h" #include "chrome/browser/profiles/profile_shortcut_manager.h"
#include "chrome/browser/signin/signin_util.h" #include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/ui/profile_picker.h" #include "chrome/browser/ui/profile_picker.h"
...@@ -117,6 +118,11 @@ void AddStrings(content::WebUIDataSource* html_source) { ...@@ -117,6 +118,11 @@ void AddStrings(content::WebUIDataSource* html_source) {
IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_SHORTCUT_TEXT}, IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_SHORTCUT_TEXT},
{"createProfileConfirm", {"createProfileConfirm",
IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_DONE}, IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_DONE},
{"defaultAvatarLabel", IDS_DEFAULT_AVATAR_LABEL_26},
{"selectAnAvatarDialogTitle",
IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_TEXT},
{"selectAvatarDoneButtonLabel",
IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_DONE},
// Color picker. // Color picker.
{"colorPickerLabel", IDS_NTP_CUSTOMIZE_COLOR_PICKER_LABEL}, {"colorPickerLabel", IDS_NTP_CUSTOMIZE_COLOR_PICKER_LABEL},
...@@ -144,6 +150,9 @@ void AddStrings(content::WebUIDataSource* html_source) { ...@@ -144,6 +150,9 @@ void AddStrings(content::WebUIDataSource* html_source) {
html_source->AddString("minimumPickerSize", html_source->AddString("minimumPickerSize",
base::StringPrintf("%ipx", kMinimumPickerSizePx)); base::StringPrintf("%ipx", kMinimumPickerSizePx));
html_source->AddInteger("placeholderAvatarIndex",
profiles::GetPlaceholderAvatarIndex());
// Add policies. // Add policies.
html_source->AddBoolean("isBrowserSigninAllowed", IsBrowserSigninAllowed()); html_source->AddBoolean("isBrowserSigninAllowed", IsBrowserSigninAllowed());
html_source->AddBoolean("isForceSigninEnabled", html_source->AddBoolean("isForceSigninEnabled",
...@@ -153,7 +162,6 @@ void AddStrings(content::WebUIDataSource* html_source) { ...@@ -153,7 +162,6 @@ void AddStrings(content::WebUIDataSource* html_source) {
IsProfileCreationAllowed()); IsProfileCreationAllowed());
html_source->AddBoolean("profileShortcutsEnabled", html_source->AddBoolean("profileShortcutsEnabled",
ProfileShortcutManager::IsFeatureEnabled()); ProfileShortcutManager::IsFeatureEnabled());
// TODO(crbug.com/1063856): Check if |BrowserSignin| device policy exists.
} }
} // namespace } // namespace
......
...@@ -20,9 +20,9 @@ suite('cr-profile-avatar-selector', function() { ...@@ -20,9 +20,9 @@ suite('cr-profile-avatar-selector', function() {
const avatarSelector = /** @type {!CrProfileAvatarSelectorElement} */ ( const avatarSelector = /** @type {!CrProfileAvatarSelectorElement} */ (
document.createElement('cr-profile-avatar-selector')); document.createElement('cr-profile-avatar-selector'));
avatarSelector.avatars = [ avatarSelector.avatars = [
{url: 'chrome://avatar1.png', label: 'avatar1'}, {url: 'chrome://avatar1.png', label: 'avatar1', index: '1'},
{url: 'chrome://avatar2.png', label: 'avatar2'}, {url: 'chrome://avatar2.png', label: 'avatar2', index: '2'},
{url: 'chrome://avatar3.png', label: 'avatar3'} {url: 'chrome://avatar3.png', label: 'avatar3', index: '3'}
]; ];
return avatarSelector; return avatarSelector;
} }
......
...@@ -21,6 +21,8 @@ suite('LocalProfileCustomizationTest', function() { ...@@ -21,6 +21,8 @@ suite('LocalProfileCustomizationTest', function() {
/** @type {!TestManageProfilesBrowserProxy} */ /** @type {!TestManageProfilesBrowserProxy} */
let browserProxy; let browserProxy;
const defaultAvatarIndex = 26;
async function resetCustomizeProfileElement() { async function resetCustomizeProfileElement() {
document.body.innerHTML = ''; document.body.innerHTML = '';
customizeProfileElement = /** @type {!LocalProfileCustomizationElement} */ ( customizeProfileElement = /** @type {!LocalProfileCustomizationElement} */ (
...@@ -52,18 +54,16 @@ suite('LocalProfileCustomizationTest', function() { ...@@ -52,18 +54,16 @@ suite('LocalProfileCustomizationTest', function() {
/** /**
* @param {string} profileName * @param {string} profileName
* @param {number} profileColor * @param {number} profileColor
* @param {string} avatarUrl * @param {number} avatarIndex
* @param {boolean} isGeneric
* @param {boolean} createShortcut * @param {boolean} createShortcut
*/ */
async function verifyCreateProfileCalledWithParams( async function verifyCreateProfileCalledWithParams(
profileName, profileColor, avatarUrl, isGeneric, createShortcut) { profileName, profileColor, avatarIndex, createShortcut) {
const args = await browserProxy.whenCalled('createProfile'); const args = await browserProxy.whenCalled('createProfile');
assertEquals(args[0], profileName); assertEquals(args[0], profileName);
assertEquals(args[1], profileColor); assertEquals(args[1], profileColor);
assertEquals(args[2], avatarUrl); assertEquals(args[2], avatarIndex);
assertEquals(args[3], isGeneric); assertEquals(args[3], createShortcut);
assertEquals(args[4], createShortcut);
browserProxy.resetResolver('createProfile'); browserProxy.resetResolver('createProfile');
} }
...@@ -86,7 +86,7 @@ suite('LocalProfileCustomizationTest', function() { ...@@ -86,7 +86,7 @@ suite('LocalProfileCustomizationTest', function() {
assertFalse(customizeProfileElement.$$('#save').disabled); assertFalse(customizeProfileElement.$$('#save').disabled);
customizeProfileElement.$$('#save').click(); customizeProfileElement.$$('#save').click();
await verifyCreateProfileCalledWithParams( await verifyCreateProfileCalledWithParams(
'Work', browserProxy.profileThemeInfo.color, '', true, false); 'Work', browserProxy.profileThemeInfo.color, defaultAvatarIndex, false);
}); });
test('ThemeSelectionChanges', async function() { test('ThemeSelectionChanges', async function() {
...@@ -122,7 +122,8 @@ suite('LocalProfileCustomizationTest', function() { ...@@ -122,7 +122,8 @@ suite('LocalProfileCustomizationTest', function() {
customizeProfileElement.$$('#nameInput').value = 'Personal'; customizeProfileElement.$$('#nameInput').value = 'Personal';
customizeProfileElement.$$('#save').click(); customizeProfileElement.$$('#save').click();
await verifyCreateProfileCalledWithParams( await verifyCreateProfileCalledWithParams(
'Personal', browserProxy.profileThemeInfo.color, '', true, false); 'Personal', browserProxy.profileThemeInfo.color, defaultAvatarIndex,
false);
}); });
test('createShortcut', async function() { test('createShortcut', async function() {
...@@ -142,7 +143,8 @@ suite('LocalProfileCustomizationTest', function() { ...@@ -142,7 +143,8 @@ suite('LocalProfileCustomizationTest', function() {
customizeProfileElement.$$('#nameInput').value = 'Personal'; customizeProfileElement.$$('#nameInput').value = 'Personal';
customizeProfileElement.$$('#save').click(); customizeProfileElement.$$('#save').click();
await verifyCreateProfileCalledWithParams( await verifyCreateProfileCalledWithParams(
'Personal', browserProxy.profileThemeInfo.color, '', true, false); 'Personal', browserProxy.profileThemeInfo.color, defaultAvatarIndex,
false);
// Profile creation in progress should disable the save button. // Profile creation in progress should disable the save button.
assertTrue(customizeProfileElement.$$('#save').disabled); assertTrue(customizeProfileElement.$$('#save').disabled);
// Fire profile creation finished. // Fire profile creation finished.
...@@ -153,6 +155,7 @@ suite('LocalProfileCustomizationTest', function() { ...@@ -153,6 +155,7 @@ suite('LocalProfileCustomizationTest', function() {
assertTrue(createShortcut.checked); assertTrue(createShortcut.checked);
customizeProfileElement.$$('#save').click(); customizeProfileElement.$$('#save').click();
await verifyCreateProfileCalledWithParams( await verifyCreateProfileCalledWithParams(
'Personal', browserProxy.profileThemeInfo.color, '', true, true); 'Personal', browserProxy.profileThemeInfo.color, defaultAvatarIndex,
true);
}); });
}); });
...@@ -23,6 +23,7 @@ export class TestManageProfilesBrowserProxy extends TestBrowserProxy { ...@@ -23,6 +23,7 @@ export class TestManageProfilesBrowserProxy extends TestBrowserProxy {
'createProfile', 'createProfile',
'setProfileName', 'setProfileName',
'recordSignInPromoImpression', 'recordSignInPromoImpression',
'getAvailableIcons',
]); ]);
/** @type {!AutogeneratedThemeColorInfo} */ /** @type {!AutogeneratedThemeColorInfo} */
...@@ -106,11 +107,10 @@ export class TestManageProfilesBrowserProxy extends TestBrowserProxy { ...@@ -106,11 +107,10 @@ export class TestManageProfilesBrowserProxy extends TestBrowserProxy {
} }
/** @override */ /** @override */
createProfile( createProfile(profileName, profileColor, avatarIndex, createShortcut) {
profileName, profileColor, avatarUrl, isGeneric, createShortcut) {
this.methodCalled( this.methodCalled(
'createProfile', 'createProfile',
[profileName, profileColor, avatarUrl, isGeneric, createShortcut]); [profileName, profileColor, avatarIndex, createShortcut]);
} }
/** @override */ /** @override */
...@@ -122,4 +122,14 @@ export class TestManageProfilesBrowserProxy extends TestBrowserProxy { ...@@ -122,4 +122,14 @@ export class TestManageProfilesBrowserProxy extends TestBrowserProxy {
recordSignInPromoImpression() { recordSignInPromoImpression() {
this.methodCalled('recordSignInPromoImpression'); this.methodCalled('recordSignInPromoImpression');
} }
/** @override */
getAvailableIcons() {
this.methodCalled('getAvailableIcons');
return Promise.resolve([
{url: 'fake-icon-1.png', label: 'fake-icon-1', index: 1, selected: false},
{url: 'fake-icon-2.png', label: 'fake-icon-2', index: 2, selected: false},
{url: 'fake-icon-3.png', label: 'fake-icon-3', index: 3, selected: false},
]);
}
} }
...@@ -75,11 +75,11 @@ ...@@ -75,11 +75,11 @@
<template is="dom-repeat" items="[[avatars]]"> <template is="dom-repeat" items="[[avatars]]">
<cr-button id="[[getAvatarId_(index)]]" <cr-button id="[[getAvatarId_(index)]]"
aria-label="[[item.label]]" aria-label="[[item.label]]"
class$="avatar [[getSelectedClass_(item.selected)]]" class$="avatar [[getSelectedClass_(item, selectedAvatar)]]"
style$="background-image: [[getIconImageSet_(item.url)]]" style$="background-image: [[getIconImageSet_(item.url)]]"
on-click="onAvatarTap_" on-click="onAvatarTap_"
role="radio" role="radio"
aria-checked$="[[getCheckedAttribute_(item.selected)]]"> aria-checked$="[[getCheckedAttribute_(item, selectedAvatar)]]">
</cr-button> </cr-button>
<paper-tooltip for="[[getAvatarId_(index)]]" <paper-tooltip for="[[getAvatarId_(index)]]"
offset="-12" fit-to-visible-bounds> offset="-12" fit-to-visible-bounds>
......
...@@ -40,9 +40,6 @@ Polymer({ ...@@ -40,9 +40,6 @@ Polymer({
notify: true, notify: true,
}, },
/** @private {?HTMLElement} */
selectedAvatarElement_: Object,
ignoreModifiedKeyEvents: { ignoreModifiedKeyEvents: {
type: Boolean, type: Boolean,
value: false, value: false,
...@@ -59,19 +56,31 @@ Polymer({ ...@@ -59,19 +56,31 @@ Polymer({
}, },
/** @private */ /** @private */
getSelectedClass_(isSelected) { getSelectedClass_(avatarItem) {
// TODO(dpapad): Rename 'iron-selected' to 'selected' now that this CSS // TODO(dpapad): Rename 'iron-selected' to 'selected' now that this CSS
// class is not assigned by any iron-* behavior. // class is not assigned by any iron-* behavior.
return isSelected ? 'iron-selected' : ''; return this.isAvatarSelected(avatarItem) ? 'iron-selected' : '';
}, },
/** /**
* @param {boolean} isSelected * @param {AvatarIcon} avatarItem
* @return {string} * @return {string}
* @private * @private
*/ */
getCheckedAttribute_(isSelected) { getCheckedAttribute_(avatarItem) {
return isSelected ? 'true' : 'false'; return this.isAvatarSelected(avatarItem) ? 'true' : 'false';
},
/**
* @param {AvatarIcon} avatarItem
* @return {boolean}
* @private
*/
isAvatarSelected(avatarItem) {
return !!avatarItem &&
(avatarItem.selected ||
(!!this.selectedAvatar &&
this.selectedAvatar.index === avatarItem.index));
}, },
/** /**
...@@ -88,13 +97,6 @@ Polymer({ ...@@ -88,13 +97,6 @@ Polymer({
* @private * @private
*/ */
onAvatarTap_(e) { onAvatarTap_(e) {
// Manual selection for profile creation
if (this.selectedAvatarElement_) {
this.selectedAvatarElement_.classList.remove('iron-selected');
}
this.selectedAvatarElement_ = /** @type {!HTMLElement} */ (e.target);
this.selectedAvatarElement_.classList.add('iron-selected');
// |selectedAvatar| is set to pass back selection to the owner of this // |selectedAvatar| is set to pass back selection to the owner of this
// component. // component.
this.selectedAvatar = this.selectedAvatar =
......
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