blob: 45894d0b1949ab7d9eaba0d7782a461cb773e730 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '//resources/cr_elements/cr_button/cr_button.js';
import '//resources/cr_elements/cr_icon_button/cr_icon_button.js';
import '//resources/cr_elements/icons.html.js';
import '/strings.m.js';
import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';
import {ColorChangeUpdater} from 'chrome://resources/cr_components/color_change_listener/colors_css_updater.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {getCss} from './app.css.js';
import {getHtml} from './app.html.js';
import {BrowserProxyImpl} from './browser_proxy.js';
import type {BrowserProxy} from './browser_proxy.js';
import {MetricsRecorder} from './metrics_recorder.js';
const RELOAD_BUTTON_TOOLTIP_RELOAD_WITH_MENU =
'reloadButtonTooltipReloadWithMenu';
const RELOAD_BUTTON_TOOLTIP_RELOAD = 'reloadButtonTooltipReload';
const RELOAD_BUTTON_TOOLTIP_STOP = 'reloadButtonTooltipStop';
const LONG_PRESS_TIMER_THRESHOLD_MS = 500;
export class ReloadButtonAppElement extends CrLitElement {
private browserProxy_: BrowserProxy;
private metricsRecorder_: MetricsRecorder;
constructor() {
super();
this.browserProxy_ = BrowserProxyImpl.getInstance();
this.metricsRecorder_ = new MetricsRecorder(this.browserProxy_);
const callbackRouter = this.browserProxy_.callbackRouter;
callbackRouter.setReloadButtonState.addListener(
(isLoading: boolean, isMenuEnabled: boolean) => {
this.metricsRecorder_.onChangeVisibleMode(
MetricsRecorder.getVisibleMode(this.isLoading_),
MetricsRecorder.getVisibleMode(isLoading));
this.isLoading_ = isLoading;
this.isMenuEnabled_ = isMenuEnabled;
this.tooltip_ = loadTimeData.getString(
isLoading ?
RELOAD_BUTTON_TOOLTIP_STOP :
(isMenuEnabled ? RELOAD_BUTTON_TOOLTIP_RELOAD_WITH_MENU :
RELOAD_BUTTON_TOOLTIP_RELOAD));
});
ColorChangeUpdater.forDocument().start();
}
static get is() {
return 'reload-button-app';
}
static override get styles() {
return getCss();
}
override render() {
return getHtml.bind(this)();
}
static override get properties() {
return {
isLoading_: {state: true, type: Boolean},
tooltip_: {state: true, type: String},
};
}
protected accessor isLoading_: boolean = false;
protected accessor tooltip_: string =
loadTimeData.getString(RELOAD_BUTTON_TOOLTIP_RELOAD);
private isLongPressed_: boolean = false;
private longPressTimer_: number = 0;
private isMenuEnabled_: boolean = false;
/**
* Sets up event listeners and the PerformanceObserver when the element is
* added to the DOM.
*/
override connectedCallback() {
super.connectedCallback();
this.metricsRecorder_.startObserving();
}
/**
* Cleans up event listeners and the PerformanceObserver when the element is
* removed from the DOM.
*/
override disconnectedCallback() {
super.disconnectedCallback();
this.metricsRecorder_.stopObserving();
}
protected onReloadButtonPointerDown_(e: MouseEvent) {
if (e.button !== 0) {
// The TypeScript code should only handle the left-click.
return;
}
// Reset the long press tracker.
this.isLongPressed_ = false;
clearTimeout(this.longPressTimer_);
if (this.isLoading_) {
// No long press handler for the "stop loading" case.
return;
}
this.longPressTimer_ = setTimeout(() => {
// When the long press is triggered and handled, mark `isLongPressed_`
// as true, so that it won't be treated as a normal click.
this.isLongPressed_ = true;
if (this.isMenuEnabled_) {
BrowserProxyImpl.getInstance().handler.showContextMenu(
e.offsetX, e.offsetY);
}
}, LONG_PRESS_TIMER_THRESHOLD_MS);
}
protected onReloadButtonPointerUp_(e: MouseEvent) {
this.metricsRecorder_.onButtonPressedStart(e);
if (this.isLongPressed_) {
// If the long press is already handled, skip the rest.
this.isLongPressed_ = false;
return;
}
this.metricsRecorder_.onChangeVisibleMode(
MetricsRecorder.getVisibleMode(this.isLoading_),
MetricsRecorder.getVisibleMode(!this.isLoading_));
clearTimeout(this.longPressTimer_);
if (this.isLoading_) {
BrowserProxyImpl.getInstance().handler.stopReload();
} else {
// If the shift or ctrl key is pressed, we should reload with cache
// ignored.
BrowserProxyImpl.getInstance().handler.reload(e.shiftKey || e.ctrlKey);
}
// Update the renderer in advance to avoid the delay.
this.isLoading_ = !this.isLoading_;
}
}
declare global {
interface HTMLElementTagNameMap {
'reload-button-app': ReloadButtonAppElement;
}
}
customElements.define(ReloadButtonAppElement.is, ReloadButtonAppElement);