From 1522b0e2dca4378a98a534b07b09b7e0859f7e2a Mon Sep 17 00:00:00 2001 From: glacambre Date: Fri, 26 Jan 2024 18:56:17 +0100 Subject: [PATCH] lib/tabs.ts: enable accessing all tabs through `tri.tabs` --- src/excmds.ts | 16 +++++++++++++--- src/lib/tabs.ts | 15 ++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/excmds.ts b/src/excmds.ts index 114974c5..a76ae610 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -5890,9 +5890,19 @@ export async function js(...str: string[]) { * - Get the URL of the tab whose id 3: * `:jsb tri.tabs[3].location.href.then(console.log)` * - Set the title of the tab whose id is 6: - * `:jsb tri.tabs[3].document.title = "New title!"` - * - Run `alert()` in all tabs: - * `:jsb browser.tabs.query({}).then(tabs => tabs.forEach(tab => tri.tabs[tab.id].tri.excmds.js('alert()')))` + * `:jsb tri.tabs[6].document.title = "New title!"` + * - Run `alert()` in a tab whose id is 9: + * `:jsb tri.tabs[9].alert()` + * + * You can also directly access the corresonding property in all tabs by using + * the "tabs" object itself, e.g. + * + * - Build a string containing the id of the active element of each tab: + * `:jsb tri.tabs.document.activeElement.id.then(ids => ids.reduce(s, id => s + " " + id))` + * - Scroll all tabs to the tenth pixel: + * `:jsb tri.tabs.document.documentElement.scrollTop = 10` + * - Use tridactyl's JS ex command to perform a complex computation: + * `:jsb tri.tabs.tri.excmds.js("let x = 1; let y = 2; x + y").then(console.log)` * * When fetching a value or running a function in a tab through the `tabs` property, the returned value is a Promise and must be awaited. * Setting values through the `tab` property is asynchronous too and there is no way to await this operation. diff --git a/src/lib/tabs.ts b/src/lib/tabs.ts index 63ea917a..7339ef4b 100644 --- a/src/lib/tabs.ts +++ b/src/lib/tabs.ts @@ -2,9 +2,6 @@ import * as Messaging from "@src/lib/messaging" const allTabs = -1 -// Small wrapper meant to enable sending a message either to a single tab or -// multiple ones. Note that for now, sending messages to all tabs does not -// work, for reasons unknown. const msg = (tabId, ...args) => { if (tabId === allTabs) { return Messaging.messageAllTabs("omniscient_content", ...args) @@ -80,11 +77,11 @@ export const tabsProxy = new Proxy(Object.create(null), { // for a single tab return tabProxy(id, []) } - throw Error("Foreground tabs proxy needs to be indexed by tab ID.") - // Ideally, if p is a string, we should construct a proxy for all - // existing tabs. This unfortunately does not seem to work: - // Messaging.messageAllTab seems to return an array of undefined when - // running e.g. `tabs.document.title`. - // return tabProxy(allTabs, []); + if (typeof p === "string") { + // If `p` is a string, then we return a proxy with a sentinel value + // indicating that the request should be sent to all tabs instead. + return tabProxy(allTabs, [])[p] + } + throw new Error(`'tabs' object can only be accessed by a number (e.g. tabs[3]) or a string (e.g. tabs.document or tabs['document']). Type of accessor: "${typeof p}"`) }, })