// Copyright 2022 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/ash/common/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/ash/common/cr_elements/cr_checkbox/cr_checkbox.js';
import 'chrome://resources/cros_components/lottie_renderer/lottie-renderer.js';
import type {CrCheckboxElement} from 'chrome://resources/ash/common/cr_elements/cr_checkbox/cr_checkbox.js';
import type {LottieRenderer} from 'chrome://resources/cros_components/lottie_renderer/lottie-renderer.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {MetricsRecordedSetupPage, OperationType, UserAction} from './cloud_upload.mojom-webui.js';
import {CloudUploadBrowserProxy} from './cloud_upload_browser_proxy.js';
import {getTemplate} from './move_confirmation_page.html.js';
export enum CloudProvider {
GOOGLE_DRIVE,
ONE_DRIVE,
}
/**
* The MoveConfirmationPageElement represents the dialog page shown when the
* user opens a file that needs to be moved first, and they haven't yet decided
* to always move files.
*/
export class MoveConfirmationPageElement extends HTMLElement {
private proxy: CloudUploadBrowserProxy =
CloudUploadBrowserProxy.getInstance();
private cloudProvider: CloudProvider|undefined;
private animationPlayer: LottieRenderer|undefined;
private playPauseButton: HTMLElement|undefined;
// Save reference to listener so it can be removed from the document in
// disconnectedCallback().
private boundKeyDownListener_: (e: KeyboardEvent) => void;
constructor() {
super();
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = getTemplate();
const actionButton = this.$('.action-button')!;
const cancelButton = this.$('.cancel-button')!;
this.playPauseButton = this.$('#playPauseIcon')!;
actionButton.addEventListener('click', () => this.onActionButtonClick());
cancelButton.addEventListener('click', () => this.onCancelButtonClick());
this.playPauseButton.addEventListener(
'click', () => this.onPlayPauseButtonClick());
this.boundKeyDownListener_ = this.onKeyDown.bind(this);
}
connectedCallback(): void {
document.addEventListener('keydown', this.boundKeyDownListener_);
}
disconnectedCallback(): void {
document.removeEventListener('keydown', this.boundKeyDownListener_);
}
$<T extends HTMLElement>(query: string): T {
return this.shadowRoot!.querySelector(query)!;
}
async setDialogAttributes(
numFiles: number, operationType: OperationType,
cloudProvider: CloudProvider) {
const [
{moveConfirmationShown: officeMoveConfirmationShownForDrive},
{alwaysMove: alwaysMoveToDrive},
{moveConfirmationShown: officeMoveConfirmationShownForOneDrive},
{alwaysMove: alwaysMoveToOneDrive},
] = await Promise.all([
this.proxy.handler.getOfficeMoveConfirmationShownForDrive(),
this.proxy.handler.getAlwaysMoveOfficeFilesToDrive(),
this.proxy.handler.getOfficeMoveConfirmationShownForOneDrive(),
this.proxy.handler.getAlwaysMoveOfficeFilesToOneDrive(),
]);
this.cloudProvider = cloudProvider;
const isCopyOperation = operationType === OperationType.kCopy;
const isPlural = numFiles > 1;
const providerName = this.getProviderName(this.cloudProvider);
// Animation.
this.updateAnimation();
// Title.
const titleElement = this.$<HTMLElement>('#title')!;
if (isCopyOperation) {
titleElement.innerText = loadTimeData.getStringF(
isPlural ? 'moveConfirmationCopyTitlePlural' :
'moveConfirmationCopyTitle',
providerName,
numFiles.toString(),
);
} else {
titleElement.innerText = loadTimeData.getStringF(
isPlural ? 'moveConfirmationMoveTitlePlural' :
'moveConfirmationMoveTitle',
providerName, numFiles.toString());
}
// Checkbox and Body.
const bodyText = this.$('#body-text');
const checkbox = this.$<CrCheckboxElement>('#always-copy-or-move-checkbox');
checkbox.innerText = loadTimeData.getString('moveConfirmationAlwaysMove');
if (this.cloudProvider === CloudProvider.ONE_DRIVE) {
bodyText.innerText =
loadTimeData.getString('moveConfirmationOneDriveBodyText');
// Only show checkbox if the confirmation has been shown before for
// OneDrive.
if (officeMoveConfirmationShownForOneDrive) {
checkbox.checked = alwaysMoveToOneDrive;
} else {
checkbox!.remove();
}
} else {
bodyText.innerText =
loadTimeData.getStringF('moveConfirmationGoogleDriveBodyText');
// Only show checkbox if the confirmation has been shown before for
// Drive.
if (officeMoveConfirmationShownForDrive) {
checkbox.checked = alwaysMoveToDrive;
} else {
checkbox!.remove();
}
}
// Action button.
const actionButton = this.$<HTMLElement>('.action-button')!;
actionButton.innerText =
loadTimeData.getString(isCopyOperation ? 'copyAndOpen' : 'moveAndOpen');
}
private getProviderName(cloudProvider: CloudProvider) {
if (cloudProvider === CloudProvider.ONE_DRIVE) {
return loadTimeData.getString('oneDrive');
}
return loadTimeData.getString('googleDrive');
}
private createAnimation(animationUrl: string) {
this.animationPlayer = document.createElement('cros-lottie-renderer');
this.animationPlayer.id = 'animation';
this.animationPlayer.setAttribute('asset-url', animationUrl);
this.animationPlayer.setAttribute('dynamic', 'true');
this.animationPlayer.setAttribute('aria-hidden', 'true');
this.animationPlayer.autoplay = true;
const animationWrapper = this.$<HTMLElement>('.animation-wrapper')!;
const playPauseIcon = this.$<HTMLElement>('#playPauseIcon')!;
animationWrapper.insertBefore(this.animationPlayer, playPauseIcon);
}
private updateAnimation() {
const provider =
this.cloudProvider === CloudProvider.ONE_DRIVE ? 'onedrive' : 'drive';
const animationUrl = `animations/move_confirmation_${provider}.json`;
if (!this.animationPlayer) {
this.createAnimation(animationUrl);
} else {
this.animationPlayer.setAttribute('asset-url', animationUrl);
}
}
private onActionButtonClick(): void {
const checkbox = this.$<CrCheckboxElement>('#always-copy-or-move-checkbox');
const setAlwaysMove = !!(checkbox && checkbox.checked);
if (this.cloudProvider === CloudProvider.ONE_DRIVE) {
this.proxy.handler.setAlwaysMoveOfficeFilesToOneDrive(setAlwaysMove);
this.proxy.handler.respondWithUserActionAndClose(
UserAction.kUploadToOneDrive);
} else {
this.proxy.handler.setAlwaysMoveOfficeFilesToDrive(setAlwaysMove);
this.proxy.handler.respondWithUserActionAndClose(
UserAction.kUploadToGoogleDrive);
}
}
private onCancelButtonClick(): void {
if (this.cloudProvider === CloudProvider.ONE_DRIVE) {
this.proxy.handler.recordCancel(
MetricsRecordedSetupPage.kMoveConfirmationOneDrive);
this.proxy.handler.respondWithUserActionAndClose(
UserAction.kCancelOneDrive);
} else {
this.proxy.handler.recordCancel(
MetricsRecordedSetupPage.kMoveConfirmationGoogleDrive);
this.proxy.handler.respondWithUserActionAndClose(
UserAction.kCancelGoogleDrive);
}
}
private onPlayPauseButtonClick(): void {
const animation = this.$<LottieRenderer>('#animation')!;
const shouldPlay = this.playPauseButton!.className === 'play';
if (shouldPlay) {
animation.play();
// Update button to Pause.
this.playPauseButton!.className = 'pause';
this.playPauseButton!.ariaLabel =
loadTimeData.getString('animationPauseText');
} else {
animation.pause();
// Update button to Play.
this.playPauseButton!.className = 'play';
this.playPauseButton!.ariaLabel =
loadTimeData.getString('animationPlayText');
}
}
private onKeyDown(e: KeyboardEvent) {
if (e.key === 'Escape') {
// Handle Escape as a "cancel".
e.stopImmediatePropagation();
e.preventDefault();
this.onCancelButtonClick();
return;
}
}
}
declare global {
interface HTMLElementTagNameMap {
'move-confirmation-page': MoveConfirmationPageElement;
}
}
customElements.define('move-confirmation-page', MoveConfirmationPageElement);