gh-15437: Fixed command actions on the urlbar not working (gh-15449)

This commit is contained in:
mr. m
2026-09-18 00:37:43 +02:00
committed by GitHub
parent 5ff06e4274
commit 4b4a659c7b
8 changed files with 265 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/urlbar/content/UrlbarInputBase.mjs b/browser/components/urlbar/content/UrlbarInputBase.mjs
index 8be35b58c5369e123ca69426e852e3849bf75513..9357aaadee0f8d2dab170e2d5e0b57282d909bf5 100644
index 8be35b58c5369e123ca69426e852e3849bf75513..778d8aecce4da6748ecbf8b86a38c2da6e01bec5 100644
--- a/browser/components/urlbar/content/UrlbarInputBase.mjs
+++ b/browser/components/urlbar/content/UrlbarInputBase.mjs
@@ -83,6 +83,12 @@ if (lazy) {
@@ -397,7 +397,7 @@ index 8be35b58c5369e123ca69426e852e3849bf75513..9357aaadee0f8d2dab170e2d5e0b5728
// Also ignore mousedown on the urlbarView context menu: opening/closing the
// view is already handled by the result opening flow.
- if (event.target.closest?.("tab, #urlbarView-context-menu")) {
+ if (event.target.closest?.("tab, #urlbarView-context-menu") || event.target.closest?.("#tabs-newtab-button")) {
+ if (event.target.closest?.("tab, #urlbarView-context-menu") || event.target.closest?.("menupopup") || event.target.closest?.("#tabs-newtab-button")) {
break;
}

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/urlbar/content/UrlbarShared.mjs b/browser/components/urlbar/content/UrlbarShared.mjs
index 0ac5330223c84fbb98880a5c2d83ae58a8f3079e..f9d3d27333f5552404bd8a1138fb1e5d6150a3d8 100644
index 0ac5330223c84fbb98880a5c2d83ae58a8f3079e..ff488cf5a2c8b7857a8e145e40aaf861cfa655ec 100644
--- a/browser/components/urlbar/content/UrlbarShared.mjs
+++ b/browser/components/urlbar/content/UrlbarShared.mjs
@@ -158,6 +158,7 @@ export const UrlbarShared = {
@@ -71,3 +71,11 @@ index 0ac5330223c84fbb98880a5c2d83ae58a8f3079e..f9d3d27333f5552404bd8a1138fb1e5d
case "UrlbarProviderOmnibox":
return UrlbarShared.RESULT_GROUP.HEURISTIC_OMNIBOX;
case "UrlbarProviderRestrictKeywordsAutofill":
@@ -1060,6 +1080,7 @@ export const UrlbarShared = {
case "UrlbarProviderAboutPages":
return UrlbarShared.RESULT_GROUP.ABOUT_PAGES;
case "UrlbarProviderInputHistory":
+ case "ZenUrlbarProviderSidebar":
return UrlbarShared.RESULT_GROUP.INPUT_HISTORY;
case "UrlbarProviderQuickSuggest":
return UrlbarShared.RESULT_GROUP.GENERAL_PARENT;

View File

@@ -146,6 +146,20 @@ window.gZenUIManager = {
});
},
/**
* Shakes an element from side to side to catch the user's eye.
*
* @param {Element} element
* @param {number} delay Milliseconds to wait before shaking.
*/
shakeElement(element, delay = 0) {
return this.elementAnimate(
element,
{ x: [0, -12, 8, -4, 2, 0] },
{ duration: 600, delay, easing: "ease-out" }
);
},
_addNewCustomizableButtonsIfNeeded() {
const kPref = "zen.ui.migration.compact-mode-button-added";
let navbarPlacements = CustomizableUI.getWidgetIdsInArea(
@@ -1595,10 +1609,6 @@ window.gZenVerticalTabsManager = {
},
rebuildURLBarMenus() {
if (document.getElementById("paste-and-go")) {
return;
}
gURLBar._initCopyCutController();
gURLBar.updatePlaceholder();
},

View File

@@ -2229,6 +2229,31 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
);
}
/**
* Switches to the folder's space, expands its parents (root first) and the
* folder itself, then jiggles it so it's easy to spot.
*
* @param {MozTabbrowserTabGroup} folder The folder to reveal.
*/
async revealFolder(folder) {
const workspaceId = folder.getAttribute("zen-workspace-id");
if (workspaceId && workspaceId != gZenWorkspaces.activeWorkspace) {
await gZenWorkspaces.changeWorkspaceWithID(workspaceId);
}
let collapsedRoot = folder.rootMostCollapsedFolder;
const wasCollapsed = !!collapsedRoot;
while (collapsedRoot) {
collapsedRoot.collapsed = false;
collapsedRoot = folder.rootMostCollapsedFolder;
}
const label = folder.labelElement.parentElement;
label.scrollIntoView({ block: "nearest", behavior: "smooth" });
await gZenUIManager.shakeElement(
label,
wasCollapsed ? this.#folderRevealDuration * 1000 : 0
);
}
styleCleanup(items) {
items.forEach(item => {
item.style.removeProperty("opacity");

View File

@@ -437,17 +437,7 @@ class nsZenShareManager extends nsZenDOMOperatedFeature {
// Shake the new split group in the sidebar.
const group = tabs[0]?.group;
if (group?.hasAttribute("split-view-group")) {
requestAnimationFrame(() => {
gZenUIManager.motion
.animate(
group,
{ x: [-32, 0] },
{ type: "spring", bounce: 0.5, duration: 1.5 }
)
.then(() => {
group.style.removeProperty("transform");
});
});
gZenUIManager.shakeElement(group);
}
}

View File

@@ -9,6 +9,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
/* eslint-disable mozilla/valid-lazy */
ZenUrlbarProviderGlobalActions:
"resource:///modules/ZenUBActionsProvider.sys.mjs",
ZenUrlbarProviderSidebar: "resource:///modules/ZenUBSidebarProvider.sys.mjs",
});
export function registerZenUrlbarProviders() {

View File

@@ -0,0 +1,212 @@
/* 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 {
UrlbarProvider,
UrlbarUtils,
} from "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs";
import { UrlbarShared } from "chrome://browser/content/urlbar/UrlbarShared.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
UrlbarResult: "chrome://browser/content/urlbar/UrlbarResult.mjs",
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
UrlbarPrefs: "moz-src:///browser/components/urlbar/UrlbarPrefs.sys.mjs",
UrlbarProviderOpenTabs:
"moz-src:///browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs",
ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
});
const DYNAMIC_TYPE_NAME = "zen-folders";
export class ZenUrlbarProviderSidebar extends UrlbarProvider {
get name() {
return "ZenUrlbarProviderSidebar";
}
/**
* @returns {Values<typeof UrlbarShared.PROVIDER_TYPE>}
*/
get type() {
return UrlbarShared.PROVIDER_TYPE.PROFILE;
}
async isActive(queryContext) {
// The sidebar data never holds tabs from private windows.
return (
!queryContext.isPrivate &&
!!queryContext.tokens.length &&
queryContext.sources.includes(UrlbarShared.RESULT_SOURCE.TABS) &&
lazy.UrlbarPrefs.get("suggest.openpage")
);
}
async startQuery(queryContext, addCallback) {
const sidebar = lazy.ZenSessionStore.getSidebarData();
if (!sidebar) {
return;
}
const tokens = queryContext.tokens.map(t => t.lowerCaseValue);
const matches = text => {
text = text.toLowerCase();
return tokens.every(token => text.includes(token));
};
this.#addFolders(sidebar, matches, addCallback);
this.#addTabs(sidebar, matches, queryContext, addCallback);
}
#addTabs(sidebar, matches, queryContext, addCallback) {
const openTabUrls = lazy.UrlbarProviderOpenTabs.getOpenTabUrls();
const activeSpace =
lazy.BrowserWindowTracker.getTopWindow().gZenWorkspaces.activeWorkspace;
let resultsAdded = 0;
for (const tabData of sidebar.tabs || []) {
// Essentials have no space, they are part of every one of them.
if (!tabData.zenEssential && tabData.zenWorkspace != activeSpace) {
continue;
}
const entries = tabData.entries || [];
const entry = entries[(tabData.index || entries.length) - 1];
const label = tabData.zenStaticLabel || entry?.title;
if (typeof label !== "string" || !label || !matches(label)) {
continue;
}
const url = entry?.url;
if (!url || url == queryContext.currentPage) {
// Don't suggest switching to the current tab.
continue;
}
const userContextId = tabData.userContextId || 0;
// The sidebar data can lag behind a navigation, only offer tabs that
// are still registered as open with this url.
const openTab = [...(openTabUrls.get(url) || [])].find(
([contextId]) => contextId == userContextId
);
if (!openTab) {
continue;
}
addCallback(
this,
new lazy.UrlbarResult({
type: UrlbarShared.RESULT_TYPE.TAB_SWITCH,
source: UrlbarShared.RESULT_SOURCE.TABS,
payload: {
url,
title: label,
icon: UrlbarShared.getIconForUrl(url),
userContext: UrlbarUtils.getUserContextData(userContextId),
tabGroup: openTab[1],
action: lazy.UrlbarPrefs.get("secondaryActions.switchToTab")
? UrlbarUtils.createTabSwitchSecondaryAction(userContextId)
: undefined,
},
highlights: {
url: UrlbarShared.HIGHLIGHT.TYPED,
title: UrlbarShared.HIGHLIGHT.TYPED,
},
})
);
if (++resultsAdded == queryContext.maxResults) {
return;
}
}
}
#addFolders(sidebar, matches, addCallback) {
const folders = new Map(
(sidebar.folders || []).map(folder => [folder.id, folder])
);
for (const folder of folders.values()) {
if (folder.splitViewGroup || !folder.name || !matches(folder.name)) {
continue;
}
const space = sidebar.spaces?.find(s => s.uuid == folder.workspaceId);
const path = [];
for (
let parent = folders.get(folder.parentId);
parent;
parent = folders.get(parent.parentId)
) {
path.unshift(parent.name);
}
if (space?.name) {
path.unshift(space.name);
}
addCallback(
this,
new lazy.UrlbarResult({
type: UrlbarShared.RESULT_TYPE.DYNAMIC,
source: UrlbarShared.RESULT_SOURCE.TABS,
payload: {
dynamicType: DYNAMIC_TYPE_NAME,
zenFolderId: folder.id,
title: folder.name,
icon:
folder.userIcon || "chrome://browser/skin/zen-icons/folder.svg",
path: path.join(" / "),
},
})
);
}
}
getViewUpdate(result) {
return {
icon: { attributes: { src: result.payload.icon } },
titleStrong: {
textContent: result.payload.title,
attributes: { dir: "ltr" },
},
path: {
textContent: result.payload.path,
attributes: { dir: "ltr", hidden: !result.payload.path },
},
};
}
getViewTemplate() {
return {
attributes: {
selectable: true,
},
children: [
{
name: "icon",
tag: "img",
classList: ["urlbarView-favicon"],
},
{
name: "title",
tag: "span",
classList: ["urlbarView-title"],
children: [
{
name: "titleStrong",
tag: "strong",
},
],
},
{
name: "path",
tag: "span",
classList: ["urlbarView-prettyName"],
},
],
};
}
onEngagement(queryContext, controller, details) {
const { zenFolderId } = details.result.payload;
if (!zenFolderId) {
return;
}
const ownerGlobal = details.element.documentGlobal;
ownerGlobal.gBrowser.selectedBrowser.focus();
const folder = ownerGlobal.document.getElementById(zenFolderId);
if (folder?.isZenFolder) {
ownerGlobal.gZenFolders.revealFolder(folder);
}
}
}

View File

@@ -8,4 +8,5 @@ EXTRA_JS_MODULES += [
"ZenUBGlobalActions.sys.mjs",
"ZenUBProvider.sys.mjs",
"ZenUBResultsLearner.sys.mjs",
"ZenUBSidebarProvider.sys.mjs",
]