// 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_action_menu/cr_action_menu.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
import 'chrome://resources/cr_elements/icons_lit.html.js';
import type {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
import {AnchorAlignment} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
import type {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js';
import {SaveRequestType} from '../constants.js';
import {getCss} from './viewer_download_controls.css.js';
import {getHtml} from './viewer_download_controls.html.js';
export interface ViewerDownloadControlsElement {
$: {
download: CrIconButtonElement,
menu: CrActionMenuElement,
};
}
export class ViewerDownloadControlsElement extends CrLitElement {
static get is() {
return 'viewer-download-controls';
}
static override get styles() {
return getCss();
}
override render() {
return getHtml.bind(this)();
}
static override get properties() {
return {
hasEdits: {type: Boolean},
hasEnteredAnnotationMode: {type: Boolean},
// <if expr="enable_pdf_ink2">
hasInk2Edits: {type: Boolean},
// </if>
isFormFieldFocused: {type: Boolean},
menuOpen_: {
type: Boolean,
reflect: true,
},
};
}
hasEdits: boolean = false;
hasEnteredAnnotationMode: boolean = false;
// <if expr="enable_pdf_ink2">
hasInk2Edits: boolean = false;
// </if>
isFormFieldFocused: boolean = false;
private menuOpen_: boolean = false;
private waitForFormFocusChange_: PromiseResolver<boolean>|null = null;
override updated(changedProperties: PropertyValues<this>) {
super.updated(changedProperties);
if (changedProperties.has('isFormFieldFocused') &&
this.waitForFormFocusChange_ !== null) {
// Resolving the promise in updated(), since this can trigger
// showDownloadMenu_() which accesses the element's DOM.
this.waitForFormFocusChange_.resolve(this.hasEdits);
this.waitForFormFocusChange_ = null;
}
}
isMenuOpen(): boolean {
return this.menuOpen_;
}
closeMenu() {
this.$.menu.close();
}
protected onOpenChanged_(e: CustomEvent<{value: boolean}>) {
this.menuOpen_ = e.detail.value;
}
private hasEditsToSave_(): boolean {
// <if expr="enable_pdf_ink2">
return this.hasEnteredAnnotationMode || this.hasEdits || this.hasInk2Edits;
// </if>
// <if expr="not enable_pdf_ink2">
return this.hasEnteredAnnotationMode || this.hasEdits;
// </if>
}
/**
* @return The value for the aria-haspopup attribute for the download button.
*/
protected downloadHasPopup_(): string {
return this.hasEditsToSave_() ? 'menu' : 'false';
}
private showDownloadMenu_() {
this.$.menu.showAt(this.$.download, {
anchorAlignmentX: AnchorAlignment.CENTER,
});
// For tests
this.dispatchEvent(new CustomEvent(
'download-menu-shown-for-testing', {bubbles: true, composed: true}));
}
protected onDownloadClick_() {
this.waitForEdits_().then(hasEdits => {
if (hasEdits) {
this.showDownloadMenu_();
} else {
this.dispatchSaveEvent_(SaveRequestType.ORIGINAL);
}
});
}
/**
* @return Promise that resolves with true if the PDF has edits and/or
* annotations, and false otherwise.
*/
private waitForEdits_(): Promise<boolean> {
if (this.hasEditsToSave_()) {
return Promise.resolve(true);
}
if (!this.isFormFieldFocused) {
return Promise.resolve(false);
}
this.waitForFormFocusChange_ = new PromiseResolver();
return this.waitForFormFocusChange_.promise;
}
private dispatchSaveEvent_(type: SaveRequestType) {
this.dispatchEvent(
new CustomEvent('save', {detail: type, bubbles: true, composed: true}));
}
protected onDownloadOriginalClick_() {
this.dispatchSaveEvent_(SaveRequestType.ORIGINAL);
this.$.menu.close();
}
protected onDownloadEditedClick_() {
this.dispatchSaveEvent_(
this.hasEnteredAnnotationMode ? SaveRequestType.ANNOTATION :
SaveRequestType.EDITED);
this.$.menu.close();
}
}
declare global {
interface HTMLElementTagNameMap {
'viewer-download-controls': ViewerDownloadControlsElement;
}
}
customElements.define(
ViewerDownloadControlsElement.is, ViewerDownloadControlsElement);