show mute status correctly when tab mute and add to get single tab status
This commit is contained in:
@@ -173,6 +173,13 @@ class BrowserCLI:
|
|||||||
"""Switch browser focus to a tab by ID."""
|
"""Switch browser focus to a tab by ID."""
|
||||||
self._cmd("tabs.active", {"tabId": tab_id})
|
self._cmd("tabs.active", {"tabId": tab_id})
|
||||||
|
|
||||||
|
def tabs_status(self, tab_id: int | None = None) -> Tab:
|
||||||
|
"""Return status for the active tab or a specific tab."""
|
||||||
|
data = self._cmd("tabs.status", {"tabId": tab_id})
|
||||||
|
if not isinstance(data, dict) or "id" not in data:
|
||||||
|
raise RuntimeError("No tab status returned")
|
||||||
|
return self._make_tab(data)
|
||||||
|
|
||||||
def tabs_mute(self, tab_id: int | None = None) -> int:
|
def tabs_mute(self, tab_id: int | None = None) -> int:
|
||||||
"""Mute the active tab or a specific tab. Returns the target tab ID."""
|
"""Mute the active tab or a specific tab. Returns the target tab ID."""
|
||||||
result = self._cmd("tabs.mute", {"tabId": tab_id})
|
result = self._cmd("tabs.mute", {"tabId": tab_id})
|
||||||
|
|||||||
@@ -125,6 +125,23 @@ def tabs_active(tab_id):
|
|||||||
console.print(f"[green]Switched to tab {tab_id}[/green]")
|
console.print(f"[green]Switched to tab {tab_id}[/green]")
|
||||||
|
|
||||||
|
|
||||||
|
@tabs_group.command("status")
|
||||||
|
@click.argument("tab_id", type=int, required=False)
|
||||||
|
def tabs_status(tab_id):
|
||||||
|
"""Show status for the active tab or a specific tab."""
|
||||||
|
tab = _handle("tabs.status", {"tabId": tab_id}) or {}
|
||||||
|
table = Table(show_header=False)
|
||||||
|
table.add_column("Field", style="bold cyan")
|
||||||
|
table.add_column("Value")
|
||||||
|
table.add_row("ID", str(tab.get("id", "")))
|
||||||
|
table.add_row("Window", str(tab.get("windowId", "")))
|
||||||
|
table.add_row("Active", "yes" if tab.get("active") else "no")
|
||||||
|
table.add_row("Muted", "yes" if tab.get("muted") else "no")
|
||||||
|
table.add_row("Title", tab.get("title") or "")
|
||||||
|
table.add_row("URL", tab.get("url") or "")
|
||||||
|
console.print(table)
|
||||||
|
|
||||||
|
|
||||||
@tabs_group.command("filter")
|
@tabs_group.command("filter")
|
||||||
@click.argument("pattern")
|
@click.argument("pattern")
|
||||||
def tabs_filter(pattern):
|
def tabs_filter(pattern):
|
||||||
|
|||||||
+22
-8
@@ -134,6 +134,7 @@ async function dispatch(command, args) {
|
|||||||
case "tabs.move": return tabsMove(args);
|
case "tabs.move": return tabsMove(args);
|
||||||
case "tabs.active": return tabsActive(args);
|
case "tabs.active": return tabsActive(args);
|
||||||
case "tabs.active_in_window": return tabsActiveInWindow(args);
|
case "tabs.active_in_window": return tabsActiveInWindow(args);
|
||||||
|
case "tabs.status": return tabsStatus(args);
|
||||||
case "tabs.filter": return tabsFilter(args);
|
case "tabs.filter": return tabsFilter(args);
|
||||||
case "tabs.count": return tabsCount(args);
|
case "tabs.count": return tabsCount(args);
|
||||||
case "tabs.query": return tabsQuery(args);
|
case "tabs.query": return tabsQuery(args);
|
||||||
@@ -275,15 +276,10 @@ async function tabsList() {
|
|||||||
for (const w of windows) {
|
for (const w of windows) {
|
||||||
for (const t of w.tabs) {
|
for (const t of w.tabs) {
|
||||||
tabs.push({
|
tabs.push({
|
||||||
id: t.id,
|
...tabInfo(t),
|
||||||
windowId: t.windowId,
|
|
||||||
windowAlias: aliases[t.windowId] || null,
|
windowAlias: aliases[t.windowId] || null,
|
||||||
active: t.active,
|
|
||||||
pinned: t.pinned,
|
pinned: t.pinned,
|
||||||
title: t.title,
|
|
||||||
url: t.url,
|
|
||||||
favIconUrl: t.favIconUrl,
|
favIconUrl: t.favIconUrl,
|
||||||
groupId: t.groupId >= 0 ? t.groupId : null,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,6 +342,11 @@ async function tabsActiveInWindow({ windowId }) {
|
|||||||
return tabInfo(tab);
|
return tabInfo(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function tabsStatus({ tabId }) {
|
||||||
|
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
|
||||||
|
return tabInfo(tab);
|
||||||
|
}
|
||||||
|
|
||||||
async function tabsFilter({ pattern }) {
|
async function tabsFilter({ pattern }) {
|
||||||
const all = await chrome.tabs.query({});
|
const all = await chrome.tabs.query({});
|
||||||
return all.filter(t => t.url && t.url.includes(pattern)).map(tabInfo);
|
return all.filter(t => t.url && t.url.includes(pattern)).map(tabInfo);
|
||||||
@@ -442,13 +443,13 @@ async function tabsMergeWindows() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function tabsMute({ tabId }) {
|
async function tabsMute({ tabId }) {
|
||||||
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
|
const tab = await resolveTabForDirectAction(tabId, "mute");
|
||||||
await chrome.tabs.update(tab.id, { muted: true });
|
await chrome.tabs.update(tab.id, { muted: true });
|
||||||
return { tabId: tab.id, muted: true };
|
return { tabId: tab.id, muted: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tabsUnmute({ tabId }) {
|
async function tabsUnmute({ tabId }) {
|
||||||
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
|
const tab = await resolveTabForDirectAction(tabId, "unmute");
|
||||||
await chrome.tabs.update(tab.id, { muted: false });
|
await chrome.tabs.update(tab.id, { muted: false });
|
||||||
return { tabId: tab.id, muted: false };
|
return { tabId: tab.id, muted: false };
|
||||||
}
|
}
|
||||||
@@ -1243,6 +1244,19 @@ async function getActiveTab() {
|
|||||||
|| activeTabs[0];
|
|| activeTabs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resolveTabForDirectAction(tabId, actionName) {
|
||||||
|
if (tabId != null) {
|
||||||
|
return chrome.tabs.get(tabId);
|
||||||
|
}
|
||||||
|
const allTabs = await chrome.tabs.query({});
|
||||||
|
if (allTabs.length !== 1) {
|
||||||
|
throw new Error(
|
||||||
|
`Refusing to ${actionName} without explicit tab ID when ${allTabs.length} tabs are open`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return allTabs[0];
|
||||||
|
}
|
||||||
|
|
||||||
async function resolveGroupId(nameOrId) {
|
async function resolveGroupId(nameOrId) {
|
||||||
const asInt = parseInt(nameOrId);
|
const asInt = parseInt(nameOrId);
|
||||||
if (!isNaN(asInt)) return asInt;
|
if (!isNaN(asInt)) return asInt;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "browser-cli",
|
"name": "browser-cli",
|
||||||
"version": "0.5.10",
|
"version": "0.5.12",
|
||||||
"description": "Control your browser from the terminal via browser-cli",
|
"description": "Control your browser from the terminal via browser-cli",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"tabs",
|
"tabs",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "browser-cli"
|
name = "browser-cli"
|
||||||
version = "0.5.10"
|
version = "0.5.12"
|
||||||
description = "Control your real running browser from the terminal via a Chrome extension"
|
description = "Control your real running browser from the terminal via a Chrome extension"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -52,6 +52,13 @@ def test_tabs_active_in_window(browser):
|
|||||||
assert result["windowId"] == active["windowId"]
|
assert result["windowId"] == active["windowId"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_tabs_status(browser):
|
||||||
|
result = browser("tabs.status", {})
|
||||||
|
assert isinstance(result, dict)
|
||||||
|
assert "id" in result
|
||||||
|
assert "muted" in result
|
||||||
|
|
||||||
|
|
||||||
def test_tabs_html(browser, http_tab):
|
def test_tabs_html(browser, http_tab):
|
||||||
html = browser("tabs.html", {"tabId": http_tab["id"]})
|
html = browser("tabs.html", {"tabId": http_tab["id"]})
|
||||||
assert isinstance(html, str)
|
assert isinstance(html, str)
|
||||||
@@ -133,3 +140,14 @@ def test_tabs_mute_and_unmute(browser, http_tab):
|
|||||||
listed = browser("tabs.list")
|
listed = browser("tabs.list")
|
||||||
listed_tab = next(t for t in listed if t["id"] == http_tab["id"])
|
listed_tab = next(t for t in listed if t["id"] == http_tab["id"])
|
||||||
assert listed_tab["muted"] is False
|
assert listed_tab["muted"] is False
|
||||||
|
status = browser("tabs.status", {"tabId": http_tab["id"]})
|
||||||
|
assert status["muted"] is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_tabs_mute_requires_explicit_tab_when_multiple_tabs_open(browser):
|
||||||
|
opened = browser("navigate.open", {"url": "https://example.com", "background": True})
|
||||||
|
try:
|
||||||
|
with pytest.raises(RuntimeError, match="Refusing to mute without explicit tab ID"):
|
||||||
|
browser("tabs.mute", {})
|
||||||
|
finally:
|
||||||
|
browser("tabs.close", {"tabId": opened["id"]})
|
||||||
|
|||||||
Reference in New Issue
Block a user