// Copyright 2021 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_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_page_selector/cr_page_selector.js';
import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
import './data_collectors.js';
import './issue_details.js';
import './spinner_page.js';
import './pii_selection.js';
import './data_export_done.js';
import './support_tool_shared.css.js';
import type {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import type {BrowserProxy, PiiDataItem, StartDataCollectionResult} from './browser_proxy.js';
import {BrowserProxyImpl} from './browser_proxy.js';
import type {DataCollectorsElement} from './data_collectors.js';
import type {DataExportDoneElement} from './data_export_done.js';
import type {IssueDetailsElement} from './issue_details.js';
import type {PiiSelectionElement} from './pii_selection.js';
import type {SpinnerPageElement} from './spinner_page.js';
import {getTemplate} from './support_tool.html.js';
export enum SupportToolPageIndex {
ISSUE_DETAILS,
DATA_COLLECTOR_SELECTION,
SPINNER,
PII_SELECTION,
EXPORT_SPINNER,
DATA_EXPORT_DONE,
}
export interface DataExportResult {
success: boolean;
path: string;
error: string;
}
export interface SupportToolElement {
$: {
issueDetails: IssueDetailsElement,
dataCollectors: DataCollectorsElement,
spinnerPage: SpinnerPageElement,
piiSelection: PiiSelectionElement,
exportSpinner: SpinnerPageElement,
dataExportDone: DataExportDoneElement,
errorMessageToast: CrToastElement,
};
}
const SupportToolElementBase = WebUiListenerMixin(PolymerElement);
export class SupportToolElement extends SupportToolElementBase {
static get is() {
return 'support-tool';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
selectedPage_: {
type: SupportToolPageIndex,
value: SupportToolPageIndex.ISSUE_DETAILS,
observer: 'onSelectedPageChange_',
},
supportToolPageIndex_: {
readonly: true,
type: Object,
value: SupportToolPageIndex,
},
// The error message shown in errorMessageToast element when it's shown.
errorMessage_: {
type: String,
value: '',
},
};
}
private errorMessage_: string;
private selectedPage_: SupportToolPageIndex;
private browserProxy_: BrowserProxy = BrowserProxyImpl.getInstance();
override connectedCallback() {
super.connectedCallback();
this.addWebUiListener(
'screenshot-received', this.onScreenshotReceived_.bind(this));
this.addWebUiListener(
'data-collection-completed',
this.onDataCollectionCompleted_.bind(this));
this.addWebUiListener(
'data-collection-cancelled',
this.onDataCollectionCancelled_.bind(this));
this.addWebUiListener(
'support-data-export-started', this.onDataExportStarted_.bind(this));
this.addWebUiListener(
'data-export-completed', this.onDataExportCompleted_.bind(this));
}
private onScreenshotReceived_(screenshotBase64: string) {
if (screenshotBase64 !== 'CANCELED') {
// Only continues if the user didn't cancel the screenshot.
this.$.dataCollectors.setScreenshotData(screenshotBase64);
}
}
private onDataExportStarted_() {
this.selectedPage_ = SupportToolPageIndex.EXPORT_SPINNER;
}
private onDataCollectionCompleted_(piiItems: PiiDataItem[]) {
this.$.piiSelection.updateDetectedPiiItems(piiItems);
this.selectedPage_ = SupportToolPageIndex.PII_SELECTION;
}
private onDataCollectionCancelled_() {
// Change the selected page into issue details page so they user can restart
// data collection if they want.
this.selectedPage_ = SupportToolPageIndex.ISSUE_DETAILS;
}
private displayError_(errorMessage: string) {
this.errorMessage_ = errorMessage;
this.$.errorMessageToast.show();
}
private onDataExportCompleted_(result: DataExportResult) {
if (result.success) {
// Show the exported data path to user in data export page if the data
// export is successful.
this.$.dataExportDone.setPath(result.path);
this.selectedPage_ = SupportToolPageIndex.DATA_EXPORT_DONE;
} else {
// Show a toast with error message and turn back to the PII selection page
// so the user can retry exporting their data.
this.selectedPage_ = SupportToolPageIndex.PII_SELECTION;
this.displayError_(result.error);
}
}
private onDataCollectionStart_(result: StartDataCollectionResult) {
if (result.success) {
this.selectedPage_ = SupportToolPageIndex.SPINNER;
} else {
this.displayError_(result.errorMessage);
}
}
private onErrorMessageToastCloseClicked_() {
this.$.errorMessageToast.hide();
}
private onContinueClick_() {
// If we are currently on data collectors selection page, send signal to
// start data collection.
if (this.selectedPage_ === SupportToolPageIndex.DATA_COLLECTOR_SELECTION) {
this.browserProxy_
.startDataCollection(
this.$.issueDetails.getIssueDetails(),
this.$.dataCollectors.getDataCollectors(),
this.$.dataCollectors.getEditedScreenshotBase64())
.then(this.onDataCollectionStart_.bind(this));
} else {
this.selectedPage_ = this.selectedPage_ + 1;
}
}
private onBackClick_() {
this.selectedPage_ = this.selectedPage_ - 1;
}
private shouldHideBackButton_(): boolean {
// Back button will only be shown on data collectors selection page.
return this.selectedPage_ !== SupportToolPageIndex.DATA_COLLECTOR_SELECTION;
}
private shouldHideContinueButtonContainer_(): boolean {
// Continue button container will only be shown in issue details page and
// data collectors selection page.
return this.selectedPage_ >= SupportToolPageIndex.SPINNER;
}
private onSelectedPageChange_() {
// On every selected page change, the focus will be moved to each page's
// header to ensure a smooth experience in terms of accessibility.
switch (this.selectedPage_) {
case SupportToolPageIndex.ISSUE_DETAILS:
this.$.issueDetails.ensureFocusOnPageHeader();
break;
case SupportToolPageIndex.DATA_COLLECTOR_SELECTION:
this.$.dataCollectors.ensureFocusOnPageHeader();
break;
case SupportToolPageIndex.SPINNER:
this.$.spinnerPage.ensureFocusOnPageHeader();
break;
case SupportToolPageIndex.PII_SELECTION:
this.$.piiSelection.ensureFocusOnPageHeader();
break;
case SupportToolPageIndex.EXPORT_SPINNER:
this.$.exportSpinner.ensureFocusOnPageHeader();
break;
case SupportToolPageIndex.DATA_EXPORT_DONE:
this.$.dataExportDone.ensureFocusOnPageHeader();
break;
default:
break;
}
}
}
declare global {
interface HTMLElementTagNameMap {
'support-tool': SupportToolElement;
}
}
customElements.define(SupportToolElement.is, SupportToolElement);