/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
import { html } from "chrome://global/content/vendor/lit.all.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://global/content/elements/moz-toggle.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://browser/content/ipprotection/bandwidth-usage.mjs";
/**
* Custom element that implements a status card for IP protection.
*/
export default class IPProtectionStatusCard extends MozLitElement {
TOGGLE_ON_EVENT = "ipprotection-status-card:user-toggled-on";
TOGGLE_OFF_EVENT = "ipprotection-status-card:user-toggled-off";
static queries = {
statusBoxEl: "ipprotection-status-box",
actionButtonEl: 'moz-button[slot="action"]',
};
static shadowRootOptions = {
...MozLitElement.shadowRootOptions,
delegatesFocus: true,
};
static properties = {
protectionEnabled: { type: Boolean },
enabledSince: { type: Object },
location: { type: Object },
bandwidthUsage: { type: Object },
hasExclusion: { type: Boolean },
isActivating: { type: Boolean },
};
constructor() {
super();
this.keyListener = this.#keyListener.bind(this);
}
connectedCallback() {
super.connectedCallback();
this.addEventListener("keydown", this.keyListener, { capture: true });
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener("keydown", this.keyListener, { capture: true });
}
handleButtonClick() {
if (!this.protectionEnabled) {
this.dispatchEvent(
new CustomEvent(this.TOGGLE_ON_EVENT, {
bubbles: true,
composed: true,
})
);
} else {
this.dispatchEvent(
new CustomEvent(this.TOGGLE_OFF_EVENT, {
bubbles: true,
composed: true,
})
);
}
}
focus() {
const button = this.shadowRoot.querySelector(`moz-button[slot="action"]`);
button?.focus();
}
#keyListener(event) {
let keyCode = event.code;
switch (keyCode) {
case "ArrowUp":
// Intentional fall-through
case "ArrowDown": {
event.stopPropagation();
event.preventDefault();
let direction =
keyCode == "ArrowDown"
? Services.focus.MOVEFOCUS_FORWARD
: Services.focus.MOVEFOCUS_BACKWARD;
Services.focus.moveFocus(
window,
null,
direction,
Services.focus.FLAG_BYKEY
);
break;
}
}
}
bandwidthUsageTemplate() {
return this.bandwidthUsage
? html``
: null;
}
locationTemplate() {
return this.location
? html`
${this.location.name}`
: null;
}
statusTemplate({
type,
headerL10nId,
buttonL10nId,
buttonType = "default",
buttonDisabled = false,
iconSrc = null,
}) {
return html`
${iconSrc
? html`
`
: null}
${this.bandwidthUsageTemplate()} ${this.locationTemplate()}
`;
}
render() {
if (this.isActivating) {
return html`
${this.statusTemplate({
type: "connecting",
headerL10nId: "ipprotection-connection-status-connecting",
buttonL10nId: "ipprotection-button-connecting",
iconSrc: "chrome://global/skin/icons/loading.svg",
buttonType: "primary",
buttonDisabled: true,
})}
`;
}
if (this.hasExclusion && this.protectionEnabled) {
return html`
${this.statusTemplate({
type: "excluded",
headerL10nId: "ipprotection-connection-status-excluded",
buttonL10nId: "ipprotection-button-turn-vpn-off-excluded-site",
iconSrc:
"chrome://browser/content/ipprotection/assets/states/ipprotection-excluded.svg",
})}
`;
}
if (this.protectionEnabled) {
return html`
${this.statusTemplate({
type: "connected",
headerL10nId: "ipprotection-connection-status-connected",
buttonL10nId: "ipprotection-button-turn-vpn-off",
iconSrc:
"chrome://browser/content/ipprotection/assets/states/ipprotection-on.svg",
})}
`;
}
return html`
${this.statusTemplate({
type: "disconnected",
headerL10nId: "ipprotection-connection-status-disconnected",
buttonL10nId: "ipprotection-button-turn-vpn-on",
buttonType: "primary",
})}
`;
}
}
customElements.define("ipprotection-status-card", IPProtectionStatusCard);