blob: 08b4b4b7ce1af64fe8de65c7cbe3a1f2e4a41e3d [file] [log] [blame]
// Copyright 2017 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_dialog/cr_dialog.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.js';
import '/strings.m.js';
import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
import type {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
import {getCss as getSharedStyleCss} from 'chrome://resources/cr_elements/cr_shared_style_lit.css.js';
import {assert} from 'chrome://resources/js/assert.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
import {highlightUpdatedItems, trackUpdatedItems} from './api_listener.js';
import {BookmarksApiProxyImpl} from './bookmarks_api_proxy.js';
import {DialogFocusManager} from './dialog_focus_manager.js';
import {getHtml} from './edit_dialog.html.js';
import type {BookmarkNode} from './types.js';
export interface BookmarksEditDialogElement {
$: {
dialog: CrDialogElement,
saveButton: HTMLElement,
url: CrInputElement,
name: CrInputElement,
};
}
export class BookmarksEditDialogElement extends CrLitElement {
static get is() {
return 'bookmarks-edit-dialog';
}
static override get styles() {
return getSharedStyleCss();
}
override render() {
return getHtml.bind(this)();
}
static override get properties() {
return {
isFolder_: {type: Boolean},
isEdit_: {type: Boolean},
/**
* Item that is being edited, or null when adding.
*/
editItem_: {type: Object},
/**
* Parent node for the item being added, or null when editing.
*/
parentId_: {type: String},
titleValue_: {type: String},
urlValue_: {type: String},
};
}
protected accessor isFolder_: boolean = false;
private accessor isEdit_: boolean = false;
private accessor editItem_: BookmarkNode|null = null;
private accessor parentId_: string|null = null;
protected accessor titleValue_: string = '';
protected accessor urlValue_: string = '';
/**
* Show the dialog to add a new folder (if |isFolder|) or item, which will be
* inserted into the tree as a child of |parentId|.
*/
showAddDialog(isFolder: boolean, parentId: string) {
this.reset_();
this.isEdit_ = false;
this.isFolder_ = isFolder;
this.parentId_ = parentId;
DialogFocusManager.getInstance().showDialog(this.$.dialog);
}
/** Show the edit dialog for |editItem|. */
showEditDialog(editItem: BookmarkNode) {
this.reset_();
this.isEdit_ = true;
this.isFolder_ = !editItem.url;
this.editItem_ = editItem;
this.titleValue_ = editItem.title;
if (!this.isFolder_) {
assert(editItem.url);
this.urlValue_ = editItem.url;
}
DialogFocusManager.getInstance().showDialog(this.$.dialog);
}
/**
* Clear out existing values from the dialog, allowing it to be reused.
*/
private reset_() {
this.editItem_ = null;
this.parentId_ = null;
this.$.url.invalid = false;
this.titleValue_ = '';
this.urlValue_ = '';
}
protected getDialogTitle_(): string {
let title;
if (this.isEdit_) {
title = this.isFolder_ ? 'renameFolderTitle' : 'editBookmarkTitle';
} else {
title = this.isFolder_ ? 'addFolderTitle' : 'addBookmarkTitle';
}
return loadTimeData.getString(title);
}
protected onTitleValueChanged_(e: CustomEvent<{value: string}>) {
this.titleValue_ = e.detail.value;
}
protected onUrlValueChanged_(e: CustomEvent<{value: string}>) {
this.urlValue_ = e.detail.value;
}
/**
* Validates the value of the URL field, returning true if it is a valid URL.
* May modify the value by prepending 'http://' in order to make it valid.
* Note: Made public only for the purposes of testing.
*/
validateUrl(): boolean {
const urlInput = this.$.url;
if (urlInput.validate()) {
return true;
}
const originalValue = this.urlValue_;
this.urlValue_ = 'http://' + originalValue;
// Force an update to propagate this to the cr-input synchronously. This is
// not best for performance, but validate() already forces an update to
// the cr-input by calling performUpdate() on that element below, and this
// method is not expected to be frequently called.
this.performUpdate();
if (urlInput.validate()) {
return true;
}
this.urlValue_ = originalValue;
return false;
}
protected onSaveButtonClick_() {
const edit: { title: string, url?: string, parentId?: string|null } =
{ 'title': this.titleValue_ };
if (!this.isFolder_) {
if (!this.validateUrl()) {
return;
}
edit['url'] = this.urlValue_;
}
if (this.isEdit_) {
chrome.bookmarks.update(this.editItem_!.id, edit);
} else {
edit['parentId'] = this.parentId_;
trackUpdatedItems();
BookmarksApiProxyImpl.getInstance().create(edit).then(
highlightUpdatedItems);
}
this.$.dialog.close();
}
protected onCancelButtonClick_() {
this.$.dialog.cancel();
}
}
declare global {
interface HTMLElementTagNameMap {
'bookmarks-edit-dialog': BookmarksEditDialogElement;
}
}
customElements.define(
BookmarksEditDialogElement.is, BookmarksEditDialogElement);