| // Copyright 2020 The Chromium Authors |
| // 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_icons.css.js'; |
| import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; |
| import 'chrome://resources/cr_elements/cr_button/cr_button.js'; |
| import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; |
| import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.js'; |
| import 'chrome://resources/cr_elements/policy/cr_policy_indicator.js'; |
| |
| import {CrRadioButtonElement} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.js'; |
| import {DomRepeat, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import {getTemplate} from './customize_modules.html.js'; |
| import {I18nMixin, loadTimeData} from './i18n_setup.js'; |
| import {ChromeCartProxy} from './modules/cart/chrome_cart_proxy.js'; |
| import {ModuleIdName} from './new_tab_page.mojom-webui.js'; |
| import {NewTabPageProxy} from './new_tab_page_proxy.js'; |
| |
| interface ModuleSetting { |
| name: string; |
| id: string; |
| checked: boolean; |
| initiallyChecked: boolean; |
| disabled: boolean; |
| } |
| |
| |
| export interface CustomizeModulesElement { |
| $: { |
| container: HTMLElement, |
| customizeButton: CrRadioButtonElement, |
| hideButton: CrRadioButtonElement, |
| toggleRepeat: DomRepeat, |
| }; |
| } |
| |
| /** Element that lets the user configure modules settings. */ |
| export class CustomizeModulesElement extends I18nMixin |
| (PolymerElement) { |
| static get is() { |
| return 'ntp-customize-modules'; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| /** |
| * If true, modules are customizable. If false, all modules are hidden. |
| */ |
| show_: { |
| type: Boolean, |
| observer: 'onShowChange_', |
| }, |
| |
| showManagedByPolicy_: { |
| type: Boolean, |
| value: () => loadTimeData.getBoolean('modulesVisibleManagedByPolicy'), |
| }, |
| |
| modules_: Array, |
| |
| // Discount toggle is a workaround for crbug.com/1199465 and will be |
| // removed after module customization is better defined. Please avoid |
| // using similar pattern for other features. |
| discountToggle_: { |
| type: Object, |
| value: {enabled: false, initiallyEnabled: false}, |
| }, |
| |
| discountToggleEligible_: { |
| type: Boolean, |
| value: false, |
| }, |
| }; |
| } |
| |
| private show_: boolean; |
| private showManagedByPolicy_: boolean; |
| private modules_: ModuleSetting[]; |
| private discountToggle_: {enabled: boolean, initiallyEnabled: boolean}; |
| private discountToggleEligible_: boolean; |
| private setDisabledModulesListenerId_: number|null = null; |
| |
| override connectedCallback() { |
| super.connectedCallback(); |
| this.setDisabledModulesListenerId_ = |
| NewTabPageProxy.getInstance() |
| .callbackRouter.setDisabledModules.addListener( |
| (all: boolean, ids: string[]) => { |
| this.$.container.hidden = false; |
| this.show_ = !all; |
| this.modules_.forEach(({id}, i) => { |
| const checked = !all && !ids.includes(id); |
| this.set(`modules_.${i}.checked`, checked); |
| this.set(`modules_.${i}.initiallyChecked`, checked); |
| this.set(`modules_.${i}.disabled`, ids.includes(id)); |
| }); |
| }); |
| |
| NewTabPageProxy.getInstance().handler.getModulesIdNames().then(({data}) => { |
| this.modules_ = data.map((d: ModuleIdName) => ({ |
| name: d.name, |
| id: d.id, |
| checked: true, |
| } as ModuleSetting)); |
| |
| NewTabPageProxy.getInstance().handler.updateDisabledModules(); |
| |
| if (this.modules_.some(module => module.id === 'chrome_cart')) { |
| ChromeCartProxy.getHandler().getDiscountToggleVisible().then( |
| ({toggleVisible}) => { |
| this.set('discountToggleEligible_', toggleVisible); |
| }); |
| |
| ChromeCartProxy.getHandler().getDiscountEnabled().then(({enabled}) => { |
| this.set('discountToggle_.enabled', enabled); |
| this.discountToggle_.initiallyEnabled = enabled; |
| }); |
| } |
| }); |
| } |
| |
| override disconnectedCallback() { |
| super.disconnectedCallback(); |
| NewTabPageProxy.getInstance().callbackRouter.removeListener( |
| this.setDisabledModulesListenerId_!); |
| } |
| |
| override ready() { |
| // |window.CrPolicyStrings.controlledSettingPolicy| populates the tooltip |
| // text of <cr-policy-indicator indicator-type="devicePolicy" /> elements. |
| // Needs to be called before |super.ready()| so that the string is available |
| // when <cr-policy-indicator> gets instantiated. |
| window.CrPolicyStrings = { |
| controlledSettingPolicy: |
| loadTimeData.getString('controlledSettingPolicy'), |
| }; |
| super.ready(); |
| } |
| |
| apply() { |
| const handler = NewTabPageProxy.getInstance().handler; |
| handler.setModulesVisible(this.show_); |
| this.modules_ |
| .filter(({checked, initiallyChecked}) => checked !== initiallyChecked) |
| .forEach(({id, checked}) => { |
| // Don't set disabled status of a module if we are in hide all mode to |
| // preserve the status for the next time we go into customize mode. |
| if (this.show_) { |
| handler.setModuleDisabled(id, !checked); |
| } |
| const base = `NewTabPage.Modules.${checked ? 'Enabled' : 'Disabled'}`; |
| chrome.metricsPrivate.recordSparseValueWithPersistentHash(base, id); |
| chrome.metricsPrivate.recordSparseValueWithPersistentHash( |
| `${base}.Customize`, id); |
| }); |
| // Discount toggle is a workaround for crbug.com/1199465 and will be |
| // removed after module customization is better defined. Please avoid |
| // using similar pattern for other features. |
| if (this.discountToggleEligible_ && |
| this.discountToggle_.enabled !== |
| this.discountToggle_.initiallyEnabled) { |
| ChromeCartProxy.getHandler().setDiscountEnabled( |
| this.discountToggle_.enabled); |
| chrome.metricsPrivate.recordUserAction(`NewTabPage.Carts.${ |
| this.discountToggle_.enabled ? 'EnableDiscount' : |
| 'DisableDiscount'}`); |
| } |
| } |
| |
| private onShowRadioSelectionChanged_(e: CustomEvent<{value: string}>) { |
| this.show_ = e.detail.value === 'customize'; |
| } |
| |
| private onShowChange_() { |
| this.modules_.forEach( |
| (m, i) => this.set(`modules_.${i}.checked`, this.show_ && !m.disabled)); |
| } |
| |
| private radioSelection_(): string { |
| return this.show_ ? 'customize' : 'hide'; |
| } |
| |
| private moduleToggleDisabled_(): boolean { |
| return this.showManagedByPolicy_ || !this.show_; |
| } |
| |
| private showDiscountToggle_( |
| id: string, checked: boolean, eligible: boolean): boolean { |
| return id === 'chrome_cart' && checked && eligible; |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'ntp-customize-modules': CustomizeModulesElement; |
| } |
| } |
| |
| customElements.define(CustomizeModulesElement.is, CustomizeModulesElement); |