blob: 622e70ca62b15a2a48f25ba33bf93d737e2d8627 [file] [log] [blame]
// 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.
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/cr_elements/shared_style_css.m.js';
import 'chrome://resources/cr_components/customize_themes/customize_themes.js';
import './profile_creation_shared.css.js';
import '../icons.js';
import '../profile_picker_shared.css.js';
import {Theme, ThemeInfo, ThemeType} from 'chrome://resources/cr_components/customize_themes/customize_themes.mojom-webui.js';
import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import {AvatarIcon} from 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js';
import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {AutogeneratedThemeColorInfo, ManageProfilesBrowserProxy, ManageProfilesBrowserProxyImpl, UserThemeChoice} from '../manage_profiles_browser_proxy.js';
import {navigateTo, navigateToPreviousRoute, Routes} from '../navigation_mixin.js';
import {isProfileCreationAllowed} from '../policy_helper.js';
import {getTemplate} from './local_profile_customization.html.js';
export interface LocalProfileCustomizationElement {
$: {
backButton: HTMLElement,
doneButton: CrButtonElement,
nameInput: CrInputElement,
save: CrButtonElement,
selectAvatarDialog: CrDialogElement,
wrapperContainer: HTMLElement,
wrapper: HTMLElement,
};
}
const LocalProfileCustomizationElementBase =
WebUIListenerMixin(I18nMixin(PolymerElement));
export class LocalProfileCustomizationElement extends
LocalProfileCustomizationElementBase {
static get is() {
return 'local-profile-customization';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
/**
* The theme info used to display colored UI elements.
*/
profileThemeInfo: {
type: Object,
observer: 'onProfileThemeInfoChange_',
notify: true,
},
/**
* The currently selected theme in the color picker.
*/
selectedTheme_: {
type: Object,
observer: 'onSelectedThemeChange_',
},
/**
* True if `selectedTheme_` doesn't need to be updated when
* `profileThemeInfo` changes.
*/
disableSelectedThemeUpdates_: {
type: Boolean,
value: false,
},
/**
* Colored default generic avatar in the format expected by
* 'cr-profile-avatar-selector'
*/
genericDefaultAvatar_: {
type: Object,
computed:
'getGenericDefaultAvatar_(profileThemeInfo.themeGenericAvatar)',
observer: 'onGenericDefaultAvatarChange_',
},
/**
* List of available profile icon Urls and labels.
*/
availableIcons_: {
type: Array,
value() {
return [];
},
},
/**
* The currently selected profile avatar, if any.
*/
selectedAvatar_: Object,
/**
* The current profile name.
*/
profileName_: {
type: String,
value: '',
},
/**
* if true, a desktop shortcut will be created for the new profile.
*/
createShortcut_: {
type: Boolean,
value: true,
},
/**
* True if the profile shortcuts feature is enabled.
*/
isProfileShortcutsEnabled_: {
type: Boolean,
value: () => loadTimeData.getBoolean('profileShortcutsEnabled'),
},
/**
* True if a profile is being created or imported.
*/
createInProgress_: {
type: Boolean,
value: false,
},
pattern_: {
type: String,
value: '.*\\S.*',
},
defaultAvatarIndex_: {
type: Number,
value: () => loadTimeData.getInteger('placeholderAvatarIndex'),
},
};
}
profileThemeInfo: AutogeneratedThemeColorInfo;
private selectedTheme_: Theme;
private disableSelectedThemeUpdates_: boolean;
private genericDefaultAvatar_: AvatarIcon;
private availableIcons_: AvatarIcon[];
private selectedAvatar_: AvatarIcon|null;
private profileName_: string;
private createShortcut_: boolean;
private isProfileShortcutsEnabled_: boolean;
private createInProgress_: boolean;
private pattern_: string;
private defaultAvatarIndex_: number;
private manageProfilesBrowserProxy_: ManageProfilesBrowserProxy =
ManageProfilesBrowserProxyImpl.getInstance();
private resizeObserver_: ResizeObserver|null = null;
override ready() {
super.ready();
this.sanityCheck_();
this.addWebUIListener(
'create-profile-finished', () => this.handleCreateProfileFinished_());
this.manageProfilesBrowserProxy_.getAvailableIcons().then(
icons => this.setAvailableIcons_(icons));
this.addEventListener('view-enter-start', this.onViewEnterStart_);
}
override connectedCallback() {
super.connectedCallback();
this.addResizeObserver_();
}
override disconnectedCallback() {
super.disconnectedCallback();
this.resizeObserver_!.disconnect();
}
private addResizeObserver_() {
const wrapperContainer = this.$.wrapperContainer;
this.resizeObserver_ = new ResizeObserver(() => {
this.shadowRoot!.querySelector('.footer')!.classList.toggle(
'division-line',
wrapperContainer.scrollHeight > wrapperContainer.clientHeight);
});
this.resizeObserver_.observe(wrapperContainer);
}
private onViewEnterStart_() {
if (this.profileName_.length === 0) {
this.$.nameInput.invalid = false;
}
this.$.nameInput.focusInput();
this.$.wrapper.scrollTop = 0;
}
private getBackButtonAriaLabel_(): string {
return this.i18n(
'backButtonAriaLabel', this.i18n('localProfileCreationTitle'));
}
private sanityCheck_(): boolean {
if (!isProfileCreationAllowed()) {
this.onBackClick_();
return false;
}
return true;
}
/**
* Handler for profile name blur.
*/
private onProfileNameInputBlur_() {
this.$.nameInput.validate();
}
/**
* Determining whether 'Save' button is disabled.
*/
private isSaveDisabled_(): boolean {
return this.createInProgress_ || !this.profileName_ ||
!this.$.nameInput.validate();
}
/**
* Handler for the 'Save' button click event.
*/
private onSaveClick_() {
if (!this.sanityCheck_()) {
return;
}
if (this.createInProgress_) {
return;
}
this.createInProgress_ = true;
const createShortcut =
this.isProfileShortcutsEnabled_ && this.createShortcut_;
this.manageProfilesBrowserProxy_.createProfile(
this.profileName_, this.profileThemeInfo.color,
this.selectedAvatar_!.index, createShortcut);
}
private onBackClick_() {
navigateToPreviousRoute();
}
private onCustomizeAvatarClick_() {
this.$.selectAvatarDialog.showModal();
}
private onDoneSelectAvatarClick_() {
this.$.selectAvatarDialog.close();
}
private getGenericDefaultAvatar_(): AvatarIcon {
return {
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_;
}
}
private setAvailableIcons_(icons: AvatarIcon[]) {
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 onProfileThemeInfoChange_() {
if (this.disableSelectedThemeUpdates_) {
return;
}
this.selectedTheme_ = {
type: ThemeType.kChrome,
info: {
chromeThemeId: this.profileThemeInfo.colorId,
} as ThemeInfo,
isForced: false,
};
}
private async onSelectedThemeChange_() {
let theme: UserThemeChoice|null = null;
if (this.selectedTheme_.type === ThemeType.kAutogenerated) {
theme = {
colorId: 0,
color: this.selectedTheme_.info.autogeneratedThemeColors!.frame.value,
};
} else if (this.selectedTheme_.type === ThemeType.kChrome) {
theme = {
colorId: this.selectedTheme_.info.chromeThemeId!,
};
} else if (this.selectedTheme_.type === ThemeType.kDefault) {
theme = {
colorId: -1,
};
}
const newThemeInfo =
await this.manageProfilesBrowserProxy_.getProfileThemeInfo(theme!);
this.disableSelectedThemeUpdates_ = true;
this.profileThemeInfo = newThemeInfo;
this.disableSelectedThemeUpdates_ = false;
}
private handleCreateProfileFinished_() {
// On profile creation, the picker window is closed.
// 'navigateTo' is meaningful if the picker is shown in a tab.
navigateTo(Routes.MAIN);
this.createInProgress_ = false;
}
}
declare global {
interface HTMLElementTagNameMap {
'local-profile-customization': LocalProfileCustomizationElement;
}
}
customElements.define(
LocalProfileCustomizationElement.is, LocalProfileCustomizationElement);