mirror of
https://github.com/zen-browser/desktop
synced 2026-04-25 17:15:00 +02:00
gh-13258: Implement new loading indicator (gh-13259)
This commit is contained in:
@@ -57,3 +57,6 @@
|
|||||||
|
|
||||||
- name: zen.view.overflow-webext-toolbar
|
- name: zen.view.overflow-webext-toolbar
|
||||||
value: "@IS_TWILIGHT@"
|
value: "@IS_TWILIGHT@"
|
||||||
|
|
||||||
|
- name: zen.view.enable-loading-indicator
|
||||||
|
value: true
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
|
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
|
||||||
index 0ea3d82b88819c41ffd866ae9533ebb5a7bff957..37db181d7e71fb6250df5bae363e9cf984b44f79 100644
|
index 0ea3d82b88819c41ffd866ae9533ebb5a7bff957..3ed2fc4d08b20883e0587e4435daacd86ad603de 100644
|
||||||
--- a/browser/base/content/browser.js
|
--- a/browser/base/content/browser.js
|
||||||
+++ b/browser/base/content/browser.js
|
+++ b/browser/base/content/browser.js
|
||||||
@@ -33,6 +33,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
@@ -33,6 +33,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
||||||
@@ -24,16 +24,7 @@ index 0ea3d82b88819c41ffd866ae9533ebb5a7bff957..37db181d7e71fb6250df5bae363e9cf9
|
|||||||
if (backDisabled) {
|
if (backDisabled) {
|
||||||
backCommand.removeAttribute("disabled");
|
backCommand.removeAttribute("disabled");
|
||||||
} else {
|
} else {
|
||||||
@@ -2305,6 +2311,8 @@ var XULBrowserWindow = {
|
@@ -3820,7 +3826,7 @@ function warnAboutClosingWindow() {
|
||||||
AboutReaderParent.updateReaderButton(gBrowser.selectedBrowser);
|
|
||||||
TranslationsParent.onLocationChange(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
+ gZenPinnedTabManager.onLocationChange(gBrowser.selectedBrowser, location);
|
|
||||||
+
|
|
||||||
PictureInPicture.updateUrlbarToggle(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
if (!gMultiProcessBrowser) {
|
|
||||||
@@ -3820,7 +3828,7 @@ function warnAboutClosingWindow() {
|
|
||||||
|
|
||||||
if (!isPBWindow && !toolbar.visible) {
|
if (!isPBWindow && !toolbar.visible) {
|
||||||
return gBrowser.warnAboutClosingTabs(
|
return gBrowser.warnAboutClosingTabs(
|
||||||
@@ -42,7 +33,7 @@ index 0ea3d82b88819c41ffd866ae9533ebb5a7bff957..37db181d7e71fb6250df5bae363e9cf9
|
|||||||
gBrowser.closingTabsEnum.ALL
|
gBrowser.closingTabsEnum.ALL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -3860,7 +3868,7 @@ function warnAboutClosingWindow() {
|
@@ -3860,7 +3866,7 @@ function warnAboutClosingWindow() {
|
||||||
return (
|
return (
|
||||||
isPBWindow ||
|
isPBWindow ||
|
||||||
gBrowser.warnAboutClosingTabs(
|
gBrowser.warnAboutClosingTabs(
|
||||||
@@ -51,7 +42,7 @@ index 0ea3d82b88819c41ffd866ae9533ebb5a7bff957..37db181d7e71fb6250df5bae363e9cf9
|
|||||||
gBrowser.closingTabsEnum.ALL
|
gBrowser.closingTabsEnum.ALL
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -3885,7 +3893,7 @@ function warnAboutClosingWindow() {
|
@@ -3885,7 +3891,7 @@ function warnAboutClosingWindow() {
|
||||||
AppConstants.platform != "macosx" ||
|
AppConstants.platform != "macosx" ||
|
||||||
isPBWindow ||
|
isPBWindow ||
|
||||||
gBrowser.warnAboutClosingTabs(
|
gBrowser.warnAboutClosingTabs(
|
||||||
@@ -60,7 +51,7 @@ index 0ea3d82b88819c41ffd866ae9533ebb5a7bff957..37db181d7e71fb6250df5bae363e9cf9
|
|||||||
gBrowser.closingTabsEnum.ALL
|
gBrowser.closingTabsEnum.ALL
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -4825,6 +4833,9 @@ var ConfirmationHint = {
|
@@ -4825,6 +4831,9 @@ var ConfirmationHint = {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.l10n.setAttributes(this._message, messageId, options.l10nArgs);
|
document.l10n.setAttributes(this._message, messageId, options.l10nArgs);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class ZenStartup {
|
|||||||
gZenWorkspaces.init();
|
gZenWorkspaces.init();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
gZenUIManager.init();
|
gZenUIManager.init();
|
||||||
|
this.#initUIComponents();
|
||||||
this.#checkForWelcomePage();
|
this.#checkForWelcomePage();
|
||||||
}, 0);
|
}, 0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -161,6 +162,16 @@ class ZenStartup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#initUIComponents() {
|
||||||
|
const kUIComponents = ["ZenProgressBar"];
|
||||||
|
for (let component of kUIComponents) {
|
||||||
|
const module = ChromeUtils.importESModule(
|
||||||
|
"resource:///modules/zen/ui/" + component + ".sys.mjs"
|
||||||
|
);
|
||||||
|
new module[component](window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#checkForWelcomePage() {
|
#checkForWelcomePage() {
|
||||||
const kWelcomeScreenSeenPref = "zen.welcome-screen.seen";
|
const kWelcomeScreenSeenPref = "zen.welcome-screen.seen";
|
||||||
if (Services.env.get("MOZ_HEADLESS")) {
|
if (Services.env.get("MOZ_HEADLESS")) {
|
||||||
|
|||||||
@@ -7,3 +7,8 @@ EXTRA_JS_MODULES += [
|
|||||||
"sys/ZenCustomizableUI.sys.mjs",
|
"sys/ZenCustomizableUI.sys.mjs",
|
||||||
"sys/ZenUIMigration.sys.mjs",
|
"sys/ZenUIMigration.sys.mjs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
EXTRA_JS_MODULES.zen.ui += [
|
||||||
|
"sys/ui/ZenProgressBar.sys.mjs",
|
||||||
|
"sys/ui/ZenUIComponent.sys.mjs",
|
||||||
|
]
|
||||||
|
|||||||
@@ -56,3 +56,38 @@
|
|||||||
background-position: -400% 50%;
|
background-position: -400% 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes zen-progress-bar-pulse {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.8) translate(-50%, -50%);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(0.95) translate(-50%, -50%);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0.8) translate(-50%, -50%);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes zen-progress-bar-long-load {
|
||||||
|
0% {
|
||||||
|
left: -100%;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
left: 100%;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes zen-progress-bar-settle {
|
||||||
|
to {
|
||||||
|
transform: translate(-50%, -50%) scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
width: 10rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -486,11 +486,12 @@
|
|||||||
margin-block: -1px !important;
|
margin-block: -1px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& #identity-icon-box {
|
#urlbar[open][zen-floating-urlbar="true"] #identity-icon-box,
|
||||||
--urlbar-box-hover-bgcolor: transparent;
|
:root[zen-single-toolbar="true"] #urlbar[breakout-extend="true"] #identity-icon-box {
|
||||||
margin-inline: 2px 8px;
|
--urlbar-box-hover-bgcolor: transparent;
|
||||||
}
|
margin-inline: 2px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stylelint-disable-next-line media-query-no-invalid */
|
/* stylelint-disable-next-line media-query-no-invalid */
|
||||||
|
|||||||
@@ -683,3 +683,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Loading progress bar */
|
||||||
|
#zen-loading-progress-bar {
|
||||||
|
position: fixed;
|
||||||
|
top: max(calc(var(--zen-element-separation) / -2), -4px);
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%) scale(0);
|
||||||
|
background: light-dark(rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.7));
|
||||||
|
height: .4rem;
|
||||||
|
width: 5rem;
|
||||||
|
z-index: 9;
|
||||||
|
border-radius: 100px;
|
||||||
|
transition: opacity .3s ease-in-out,
|
||||||
|
background-color .3s ease-in-out,
|
||||||
|
transform .3s ease-in-out;
|
||||||
|
overflow: clip;
|
||||||
|
pointer-events: none;
|
||||||
|
animation: zen-progress-bar-pulse 1.5s linear infinite forwards;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
|
||||||
|
&[long-load="true"] {
|
||||||
|
opacity: 1;
|
||||||
|
animation: zen-progress-bar-settle .3s ease-out forwards;
|
||||||
|
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1));
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 75%;
|
||||||
|
opacity: 0;
|
||||||
|
animation: zen-progress-bar-long-load 1s ease-in-out infinite;
|
||||||
|
animation-delay: 0.3s;
|
||||||
|
background: light-dark(rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.7));
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stylelint-disable-next-line media-query-no-invalid */
|
||||||
|
@media not -moz-pref("zen.view.enable-loading-indicator") {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
127
src/zen/common/sys/ui/ZenProgressBar.sys.mjs
Normal file
127
src/zen/common/sys/ui/ZenProgressBar.sys.mjs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// 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 http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
import { ZenUIComponent } from "resource:///modules/zen/ui/ZenUIComponent.sys.mjs";
|
||||||
|
|
||||||
|
const WAIT_BEFORE_SHOWING_LONG_LOAD = 3000;
|
||||||
|
|
||||||
|
export class ZenProgressBar extends ZenUIComponent {
|
||||||
|
#element = null;
|
||||||
|
#loadingTab = null;
|
||||||
|
#longLoadTimer = null;
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.listenBrowserTabsProgress();
|
||||||
|
this.addEventListener("TabSelect");
|
||||||
|
}
|
||||||
|
|
||||||
|
onStateChange(aWebProgress) {
|
||||||
|
this.#checkBrowserProgress(aWebProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
onLocationChange(webProgress) {
|
||||||
|
this.#checkBrowserProgress(webProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
on_TabSelect() {
|
||||||
|
const gBrowser = this.window.gBrowser;
|
||||||
|
const selectedTab = gBrowser.selectedTab;
|
||||||
|
this.onLocationChange(gBrowser.getBrowserForTab(selectedTab));
|
||||||
|
}
|
||||||
|
|
||||||
|
get #progressBar() {
|
||||||
|
if (!this.#loadingTab) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!this.#element) {
|
||||||
|
this.#element = this.window.document.createXULElement("hbox");
|
||||||
|
this.#element.id = "zen-loading-progress-bar";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.#element._loadingTab?.deref() !== this.#loadingTab &&
|
||||||
|
this.#loadingTab
|
||||||
|
) {
|
||||||
|
this.#element._loadingTab = new WeakRef(this.#loadingTab);
|
||||||
|
const container = this.window.document.getElementById(
|
||||||
|
this.#loadingTab.linkedPanel
|
||||||
|
);
|
||||||
|
container.firstChild.before(this.#element);
|
||||||
|
this.window.gZenUIManager.elementAnimate(
|
||||||
|
this.#element,
|
||||||
|
{
|
||||||
|
opacity: [0, 0.6],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: 400,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.#element;
|
||||||
|
}
|
||||||
|
|
||||||
|
#checkBrowserProgress(webProgress) {
|
||||||
|
const window = this.window;
|
||||||
|
const gBrowser = window.gBrowser;
|
||||||
|
const tab = gBrowser.getTabForBrowser(webProgress);
|
||||||
|
const isLoading =
|
||||||
|
tab?.selected &&
|
||||||
|
(tab.hasAttribute("busy") || tab.hasAttribute("progress"));
|
||||||
|
if (isLoading) {
|
||||||
|
this.#showProgressBar(tab);
|
||||||
|
} else {
|
||||||
|
this.#hideProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#hideProgressBar() {
|
||||||
|
const progressBar = this.#element;
|
||||||
|
const window = this.window;
|
||||||
|
if (this.#longLoadTimer) {
|
||||||
|
window.clearTimeout(this.#longLoadTimer);
|
||||||
|
this.#longLoadTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#loadingTab = null;
|
||||||
|
if (!progressBar) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const callback = () => {
|
||||||
|
delete progressBar._loadingTab;
|
||||||
|
progressBar.remove();
|
||||||
|
this.#element = null;
|
||||||
|
};
|
||||||
|
if (this.window.gReduceMotion) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.window.gZenUIManager
|
||||||
|
.elementAnimate(
|
||||||
|
progressBar,
|
||||||
|
{
|
||||||
|
transform: ["scaleX(0.8) translate(-50%, -50%)"],
|
||||||
|
opacity: [0],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: 300,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
#showProgressBar(aTab) {
|
||||||
|
if (this.#loadingTab === aTab) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#loadingTab = aTab;
|
||||||
|
const progressBar = this.#progressBar;
|
||||||
|
progressBar.removeAttribute("fade-out");
|
||||||
|
progressBar.removeAttribute("long-load");
|
||||||
|
this.#longLoadTimer = this.window.setTimeout(() => {
|
||||||
|
if (this.#loadingTab === aTab) {
|
||||||
|
progressBar.setAttribute("long-load", "true");
|
||||||
|
}
|
||||||
|
this.#longLoadTimer = null;
|
||||||
|
}, WAIT_BEFORE_SHOWING_LONG_LOAD);
|
||||||
|
}
|
||||||
|
}
|
||||||
61
src/zen/common/sys/ui/ZenUIComponent.sys.mjs
Normal file
61
src/zen/common/sys/ui/ZenUIComponent.sys.mjs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// 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 http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for UI components in Zen.
|
||||||
|
* UI components are responsible for managing their own event listeners
|
||||||
|
* and providing a consistent interface for handling events.
|
||||||
|
*/
|
||||||
|
export class ZenUIComponent {
|
||||||
|
#window = null;
|
||||||
|
#eventListeners = new Set();
|
||||||
|
|
||||||
|
constructor(aWindow) {
|
||||||
|
this.#window = aWindow;
|
||||||
|
this.init();
|
||||||
|
this.#window.addEventListener("unload", () => {
|
||||||
|
if (typeof this.uninit === "function") {
|
||||||
|
this.uninit();
|
||||||
|
}
|
||||||
|
for (const { type, options } of this.#eventListeners) {
|
||||||
|
this.#window.removeEventListener(type, this, options);
|
||||||
|
}
|
||||||
|
this.#eventListeners.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get window() {
|
||||||
|
return this.#window;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an event listener to the component that will automatically be removed when the window unloads.
|
||||||
|
*
|
||||||
|
* @param {string} type - The event type to listen for.
|
||||||
|
* @param {object} options - The event listener function or an object containing options.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
addEventListener(type, options = {}) {
|
||||||
|
this.#window.addEventListener(type, this, options);
|
||||||
|
if (options?.once) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#eventListeners.add({ type, options });
|
||||||
|
}
|
||||||
|
|
||||||
|
listenBrowserTabsProgress() {
|
||||||
|
this.#window.gBrowser.addTabsProgressListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
listenBrowserProgress() {
|
||||||
|
this.#window.gBrowser.addProgressListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEvent(event) {
|
||||||
|
const handlerName = "on_" + event.type;
|
||||||
|
if (typeof this[handlerName] === "function") {
|
||||||
|
this[handlerName](event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,12 +96,6 @@
|
|||||||
|
|
||||||
.browserSidebarContainer.zen-glance-background {
|
.browserSidebarContainer.zen-glance-background {
|
||||||
box-shadow: var(--zen-big-shadow);
|
box-shadow: var(--zen-big-shadow);
|
||||||
|
|
||||||
& .browserContainer {
|
|
||||||
/* For rounding the corners of the content to work while
|
|
||||||
* applying a transformation to the container. */
|
|
||||||
will-change: transform;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.browserSidebarContainer.zen-glance-background,
|
.browserSidebarContainer.zen-glance-background,
|
||||||
|
|||||||
@@ -79,8 +79,9 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
|||||||
this._zenClickEventListener = this._onTabClick.bind(this);
|
this._zenClickEventListener = this._onTabClick.bind(this);
|
||||||
|
|
||||||
gZenWorkspaces._resolvePinnedInitialized();
|
gZenWorkspaces._resolvePinnedInitialized();
|
||||||
if (lazy.zenPinnedTabRestorePinnedTabsToPinnedUrl) {
|
gZenWorkspaces.promiseInitialized.then(() => {
|
||||||
gZenWorkspaces.promiseInitialized.then(() => {
|
gBrowser.addTabsProgressListener(this);
|
||||||
|
if (lazy.zenPinnedTabRestorePinnedTabsToPinnedUrl) {
|
||||||
for (const tab of gZenWorkspaces.allStoredTabs) {
|
for (const tab of gZenWorkspaces.allStoredTabs) {
|
||||||
try {
|
try {
|
||||||
this.resetPinnedTab(tab);
|
this.resetPinnedTab(tab);
|
||||||
@@ -88,8 +89,8 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
|||||||
console.error("Error restoring pinned tab:", ex);
|
console.error("Error restoring pinned tab:", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
log(message) {
|
log(message) {
|
||||||
@@ -833,11 +834,13 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onLocationChange(aBrowser, aLocation) {
|
onLocationChange(aBrowser, aWebProgress, aRequest, aLocationURI) {
|
||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
let location = aLocationURI ? aLocationURI.spec : "";
|
||||||
if (
|
if (
|
||||||
(aLocation == "about:blank" &&
|
(location == "about:blank" &&
|
||||||
BrowserUIUtils.checkEmptyPageOrigin(aBrowser)) ||
|
BrowserUIUtils.checkEmptyPageOrigin(aBrowser)) ||
|
||||||
aLocation == ""
|
location == ""
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -852,7 +855,7 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
|||||||
}
|
}
|
||||||
// Remove # and ? from the URL
|
// Remove # and ? from the URL
|
||||||
const pinUrl = tab._zenPinnedInitialState.entry.url.split("#")[0];
|
const pinUrl = tab._zenPinnedInitialState.entry.url.split("#")[0];
|
||||||
const currentUrl = aLocation.split("#")[0];
|
const currentUrl = location.split("#")[0];
|
||||||
// Add an indicator that the pin has been changed
|
// Add an indicator that the pin has been changed
|
||||||
if (pinUrl === currentUrl) {
|
if (pinUrl === currentUrl) {
|
||||||
this.resetPinChangedUrl(tab);
|
this.resetPinChangedUrl(tab);
|
||||||
|
|||||||
Reference in New Issue
Block a user