summaryrefslogtreecommitdiffstats
path: root/browser/components/firefoxview/firefoxview.mjs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /browser/components/firefoxview/firefoxview.mjs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/firefoxview/firefoxview.mjs')
-rw-r--r--browser/components/firefoxview/firefoxview.mjs189
1 files changed, 189 insertions, 0 deletions
diff --git a/browser/components/firefoxview/firefoxview.mjs b/browser/components/firefoxview/firefoxview.mjs
new file mode 100644
index 0000000000..77f4c06cc7
--- /dev/null
+++ b/browser/components/firefoxview/firefoxview.mjs
@@ -0,0 +1,189 @@
+/* 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/. */
+
+let pageList = [];
+let categoryPagesDeck = null;
+let categoryNavigation = null;
+let activeComponent = null;
+let searchKeyboardShortcut = null;
+
+const { topChromeWindow } = window.browsingContext;
+
+function onHashChange() {
+ let page = document.location?.hash.substring(1);
+ if (!page || !pageList.includes(page)) {
+ page = "recentbrowsing";
+ }
+ changePage(page);
+}
+
+function changePage(page) {
+ categoryPagesDeck.selectedViewName = page;
+ categoryNavigation.currentCategory = page;
+ if (categoryNavigation.categoryButtons.includes(document.activeElement)) {
+ let currentCategoryButton = categoryNavigation.categoryButtons.find(
+ categoryButton => categoryButton.name === page
+ );
+ (currentCategoryButton || categoryNavigation.categoryButtons[0]).focus();
+ }
+}
+
+function onPagesDeckViewChange() {
+ for (const child of categoryPagesDeck.children) {
+ if (child.getAttribute("name") == categoryPagesDeck.selectedViewName) {
+ child.enter();
+ activeComponent = child;
+ } else {
+ child.exit();
+ }
+ }
+}
+
+function recordNavigationTelemetry(source, eventTarget) {
+ let page = "recentbrowsing";
+ if (source === "category-navigation") {
+ page = eventTarget.parentNode.currentCategory;
+ } else if (source === "view-all") {
+ page = eventTarget.shortPageName;
+ }
+ // Record telemetry
+ Services.telemetry.recordEvent(
+ "firefoxview_next",
+ "change_page",
+ "navigation",
+ null,
+ {
+ page,
+ source,
+ }
+ );
+}
+
+async function updateSearchTextboxSize() {
+ const msgs = [
+ { id: "firefoxview-search-text-box-recentbrowsing" },
+ { id: "firefoxview-search-text-box-opentabs" },
+ { id: "firefoxview-search-text-box-recentlyclosed" },
+ { id: "firefoxview-search-text-box-syncedtabs" },
+ { id: "firefoxview-search-text-box-history" },
+ ];
+ let maxLength = 30;
+ for (const msg of await document.l10n.formatMessages(msgs)) {
+ const placeholder = msg.attributes[0].value;
+ maxLength = Math.max(maxLength, placeholder.length);
+ }
+ for (const child of categoryPagesDeck.children) {
+ child.searchTextboxSize = maxLength;
+ }
+}
+
+async function updateSearchKeyboardShortcut() {
+ const [message] = await topChromeWindow.document.l10n.formatMessages([
+ { id: "find-shortcut" },
+ ]);
+ const key = message.attributes[0].value;
+ searchKeyboardShortcut = key.toLocaleLowerCase();
+}
+
+window.addEventListener("DOMContentLoaded", async () => {
+ recordEnteredTelemetry();
+
+ categoryNavigation = document.querySelector("fxview-category-navigation");
+ categoryPagesDeck = document.querySelector("named-deck");
+
+ for (const item of categoryNavigation.categoryButtons) {
+ pageList.push(item.getAttribute("name"));
+ }
+ window.addEventListener("hashchange", onHashChange);
+ window.addEventListener("change-category", function (event) {
+ location.hash = event.target.getAttribute("name");
+ window.scrollTo(0, 0);
+ recordNavigationTelemetry("category-navigation", event.target);
+ });
+ window.addEventListener("card-container-view-all", function (event) {
+ recordNavigationTelemetry("view-all", event.originalTarget);
+ });
+
+ categoryPagesDeck.addEventListener("view-changed", onPagesDeckViewChange);
+
+ // set the initial state
+ onHashChange();
+ onPagesDeckViewChange();
+ await updateSearchTextboxSize();
+ await updateSearchKeyboardShortcut();
+
+ if (Cu.isInAutomation) {
+ Services.obs.notifyObservers(null, "firefoxview-entered");
+ }
+});
+
+document.addEventListener("visibilitychange", () => {
+ if (document.visibilityState === "visible") {
+ recordEnteredTelemetry();
+ if (Cu.isInAutomation) {
+ // allow all the component visibilitychange handlers to execute before notifying
+ requestAnimationFrame(() => {
+ Services.obs.notifyObservers(null, "firefoxview-entered");
+ });
+ }
+ }
+});
+
+function recordEnteredTelemetry() {
+ Services.telemetry.recordEvent(
+ "firefoxview_next",
+ "entered",
+ "firefoxview",
+ null,
+ {
+ page: document.location?.hash?.substring(1) || "recentbrowsing",
+ }
+ );
+}
+
+document.addEventListener("keydown", e => {
+ if (e.getModifierState("Accel") && e.key === searchKeyboardShortcut) {
+ activeComponent.searchTextbox?.focus();
+ }
+});
+
+window.addEventListener(
+ "unload",
+ () => {
+ // Clear out the document so the disconnectedCallback will trigger
+ // properly and all of the custom elements can cleanup.
+ document.body.textContent = "";
+ topChromeWindow.removeEventListener("command", onCommand);
+ Services.obs.removeObserver(onLocalesChanged, "intl:app-locales-changed");
+ },
+ { once: true }
+);
+
+topChromeWindow.addEventListener("command", onCommand);
+Services.obs.addObserver(onLocalesChanged, "intl:app-locales-changed");
+
+function onCommand(e) {
+ if (document.hidden || !e.target.closest("#contentAreaContextMenu")) {
+ return;
+ }
+ const item =
+ e.target.closest("#context-openlinkinusercontext-menu") || e.target;
+ Services.telemetry.recordEvent(
+ "firefoxview_next",
+ "browser_context_menu",
+ "tabs",
+ null,
+ {
+ menu_action: item.id,
+ page: location.hash?.substring(1) || "recentbrowsing",
+ }
+ );
+}
+
+function onLocalesChanged() {
+ requestIdleCallback(() => {
+ updateSearchTextboxSize();
+ updateSearchKeyboardShortcut();
+ });
+}