blob: d3e6a906dfe585df74d9847cc0ad5d9257e08308 [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/hidden_style_css.m.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/js/util.m.js';
import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js';
import './destination_dropdown_cros.js';
import './destination_select_style.css.js';
import './icons.html.js';
import './print_preview_shared.css.js';
import './throbber.css.js';
import '../strings.m.js';
import { I18nMixin } from 'chrome://resources/js/i18n_mixin.js';
import { PolymerElement } from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import { DestinationOrigin, GooglePromotedDestinationId, PDF_DESTINATION_KEY } from '../data/destination.js';
import { ERROR_STRING_KEY_MAP, getPrinterStatusIcon, PrinterStatusReason } from '../data/printer_status_cros.js';
import { getTemplate } from './destination_select_cros.html.js';
import { SelectMixin } from './select_mixin.js';
const PrintPreviewDestinationSelectCrosElementBase = I18nMixin(SelectMixin(PolymerElement));
export class PrintPreviewDestinationSelectCrosElement extends PrintPreviewDestinationSelectCrosElementBase {
static get is() {
return 'print-preview-destination-select-cros';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
activeUser: String,
dark: Boolean,
destination: Object,
disabled: Boolean,
driveDestinationKey: String,
loaded: Boolean,
noDestinations: Boolean,
pdfPrinterDisabled: Boolean,
recentDestinationList: {
type: Array,
observer: 'onRecentDestinationListChanged_',
},
pdfDestinationKey_: {
type: String,
value: PDF_DESTINATION_KEY,
},
statusText_: {
type: String,
computed: 'computeStatusText_(destination, destination.printerStatusReason)',
observer: 'onStatusTextSet_',
},
destinationIcon_: {
type: String,
computed: 'computeDestinationIcon_(' +
'selectedValue, destination, destination.printerStatusReason,' +
'isDarkModeActive_)',
},
isCurrentDestinationCrosLocal_: {
type: Boolean,
computed: 'computeIsCurrentDestinationCrosLocal_(destination)',
reflectToAttribute: true,
},
// Holds status of iron-media-query (prefers-color-scheme: dark).
isDarkModeActive_: Boolean,
};
}
focus() {
this.shadowRoot.querySelector('print-preview-destination-dropdown-cros').focus();
}
/** Sets the select to the current value of |destination|. */
updateDestination() {
this.selectedValue = this.destination.key;
}
/**
* Returns the iconset and icon for the selected printer. If printer details
* have not yet been retrieved from the backend, attempts to return an
* appropriate icon early based on the printer's sticky information.
* @return The iconset and icon for the current selection.
*/
computeDestinationIcon_() {
if (!this.selectedValue) {
return '';
}
// If the destination matches the selected value, pull the icon from the
// destination.
if (this.destination && this.destination.key === this.selectedValue) {
if (this.isCurrentDestinationCrosLocal_) {
return getPrinterStatusIcon(this.destination.printerStatusReason, this.destination.isEnterprisePrinter, this.isDarkModeActive_);
}
return this.destination.icon;
}
// Check for the Docs or Save as PDF ids first.
const keyParams = this.selectedValue.split('/');
if (keyParams[0] === GooglePromotedDestinationId.SAVE_TO_DRIVE_CROS) {
return 'print-preview:save-to-drive';
}
if (keyParams[0] === GooglePromotedDestinationId.SAVE_AS_PDF) {
return 'cr:insert-drive-file';
}
// Otherwise, must be in the recent list.
const recent = this.recentDestinationList.find(d => {
return d.key === this.selectedValue;
});
if (recent && recent.icon) {
return recent.icon;
}
// The key/recent destinations don't have information about what icon to
// use, so just return the generic print icon for now. It will be updated
// when the destination is set.
return 'print-preview:print';
}
fireSelectedOptionChange_(value) {
this.dispatchEvent(new CustomEvent('selected-option-change', { bubbles: true, composed: true, detail: value }));
}
onProcessSelectChange(value) {
this.fireSelectedOptionChange_(value);
}
onDropdownValueSelected_(e) {
const selectedItem = e.detail;
if (!selectedItem || selectedItem.value === this.destination.key) {
return;
}
this.fireSelectedOptionChange_(selectedItem.value);
}
/**
* Send a printer status request for any new destination in the dropdown.
*/
onRecentDestinationListChanged_() {
for (const destination of this.recentDestinationList) {
if (!destination || destination.origin !== DestinationOrigin.CROS) {
continue;
}
destination.requestPrinterStatus().then(destinationKey => this.onPrinterStatusReceived_(destinationKey));
}
}
/**
* Check if the printer is currently in the dropdown then update its status
* icon if it's present.
*/
onPrinterStatusReceived_(destinationKey) {
const indexFound = this.recentDestinationList.findIndex(destination => {
return destination.key === destinationKey;
});
if (indexFound === -1) {
return;
}
// Use notifyPath to trigger the matching printer located in the dropdown to
// recalculate its status icon.
this.notifyPath(`recentDestinationList.${indexFound}.printerStatusReason`);
// If |destinationKey| matches the currently selected printer, use
// notifyPath to trigger the destination to recalculate its status icon and
// error status text.
if (this.destination && this.destination.key === destinationKey) {
this.notifyPath(`destination.printerStatusReason`);
}
}
/**
* @return An error status for the current destination. If no error
* status exists, an empty string.
*/
computeStatusText_() {
// |destination| can be either undefined, or null here.
if (!this.destination) {
return '';
}
// Non-local printers do not show an error status.
if (this.destination.origin !== DestinationOrigin.CROS) {
return '';
}
const printerStatusReason = this.destination.printerStatusReason;
if (printerStatusReason === null ||
printerStatusReason === PrinterStatusReason.NO_ERROR ||
printerStatusReason === PrinterStatusReason.UNKNOWN_REASON) {
return '';
}
return this.getErrorString_(printerStatusReason);
}
onStatusTextSet_() {
this.shadowRoot.querySelector('#statusText').innerHTML = this.statusText_;
}
getErrorString_(printerStatusReason) {
const errorStringKey = ERROR_STRING_KEY_MAP.get(printerStatusReason);
return errorStringKey ? this.i18n(errorStringKey) : '';
}
/**
* True when the currently selected destination is a CrOS local printer.
*/
computeIsCurrentDestinationCrosLocal_() {
return this.destination &&
this.destination.origin === DestinationOrigin.CROS;
}
/**
* Return the options currently visible to the user for testing purposes.
*/
getVisibleItemsForTest() {
return this.shadowRoot.querySelector('#dropdown').shadowRoot
.querySelectorAll('.list-item:not([hidden])');
}
}
customElements.define(PrintPreviewDestinationSelectCrosElement.is, PrintPreviewDestinationSelectCrosElement);