allow to mute and unmute tabs and get mute status into tab info
Testing / test (push) Failing after 34s

This commit is contained in:
2026-04-13 21:19:27 +02:00
parent 5150933319
commit c494e76fe2
7 changed files with 84 additions and 3 deletions
+11
View File
@@ -77,6 +77,7 @@ class BrowserCLI:
id=data["id"], id=data["id"],
window_id=data.get("windowId", 0), window_id=data.get("windowId", 0),
active=data.get("active", False), active=data.get("active", False),
muted=data.get("muted", False),
title=data.get("title") or "", title=data.get("title") or "",
url=data.get("url") or "", url=data.get("url") or "",
group_id=data.get("groupId") or None, group_id=data.get("groupId") or None,
@@ -172,6 +173,16 @@ 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_mute(self, tab_id: int | None = None) -> int:
"""Mute the active tab or a specific tab. Returns the target tab ID."""
result = self._cmd("tabs.mute", {"tabId": tab_id})
return result.get("tabId", tab_id) if isinstance(result, dict) else int(tab_id or 0)
def tabs_unmute(self, tab_id: int | None = None) -> int:
"""Unmute the active tab or a specific tab. Returns the target tab ID."""
result = self._cmd("tabs.unmute", {"tabId": tab_id})
return result.get("tabId", tab_id) if isinstance(result, dict) else int(tab_id or 0)
def window_active_tab(self, window_id: int) -> Tab: def window_active_tab(self, window_id: int) -> Tab:
"""Return active tab for a specific browser window.""" """Return active tab for a specific browser window."""
data = self._cmd("tabs.active_in_window", {"windowId": window_id}) data = self._cmd("tabs.active_in_window", {"windowId": window_id})
+21
View File
@@ -44,15 +44,18 @@ def _print_tabs(tabs: list[dict], *, show_browser: bool = False) -> None:
table.add_column("ID", style="dim", no_wrap=True) table.add_column("ID", style="dim", no_wrap=True)
table.add_column("Window", no_wrap=True) table.add_column("Window", no_wrap=True)
table.add_column("Active", width=7) table.add_column("Active", width=7)
table.add_column("Muted", width=7)
table.add_column("Title") table.add_column("Title")
table.add_column("URL") table.add_column("URL")
for t in tabs: for t in tabs:
active = "[green]✓[/green]" if t.get("active") else "" active = "[green]✓[/green]" if t.get("active") else ""
muted = "[yellow]✓[/yellow]" if t.get("muted") else ""
row = [ row = [
t.get("browser", "") if show_browser else None, t.get("browser", "") if show_browser else None,
str(t.get("id", "")), str(t.get("id", "")),
str(t.get("windowId", "")), str(t.get("windowId", "")),
active, active,
muted,
(t.get("title") or "")[:60], (t.get("title") or "")[:60],
(t.get("url") or "")[:80], (t.get("url") or "")[:80],
] ]
@@ -198,3 +201,21 @@ def tabs_merge_windows():
result = _handle("tabs.merge_windows") result = _handle("tabs.merge_windows")
count = result.get("moved", 0) if isinstance(result, dict) else 0 count = result.get("moved", 0) if isinstance(result, dict) else 0
console.print(f"[green]Merged — moved {count} tab(s) into current window[/green]") console.print(f"[green]Merged — moved {count} tab(s) into current window[/green]")
@tabs_group.command("mute")
@click.argument("tab_id", type=int, required=False)
def tabs_mute(tab_id):
"""Mute the active tab or a specific tab."""
result = _handle("tabs.mute", {"tabId": tab_id})
target = result.get("tabId", tab_id) if isinstance(result, dict) else tab_id
console.print(f"[green]Muted tab {target}[/green]")
@tabs_group.command("unmute")
@click.argument("tab_id", type=int, required=False)
def tabs_unmute(tab_id):
"""Unmute the active tab or a specific tab."""
result = _handle("tabs.unmute", {"tabId": tab_id})
target = result.get("tabId", tab_id) if isinstance(result, dict) else tab_id
console.print(f"[green]Unmuted tab {target}[/green]")
+9
View File
@@ -29,6 +29,7 @@ class Tab:
id: int id: int
window_id: int window_id: int
active: bool active: bool
muted: bool
title: str title: str
url: str url: str
group_id: int | None = None group_id: int | None = None
@@ -48,6 +49,14 @@ class Tab:
"""Switch browser focus to this tab.""" """Switch browser focus to this tab."""
self._b()._cmd("tabs.active", {"tabId": self.id}) self._b()._cmd("tabs.active", {"tabId": self.id})
def mute(self) -> None:
"""Mute this tab."""
self._b()._cmd("tabs.mute", {"tabId": self.id})
def unmute(self) -> None:
"""Unmute this tab."""
self._b()._cmd("tabs.unmute", {"tabId": self.id})
def reload(self) -> None: def reload(self) -> None:
"""Reload this tab.""" """Reload this tab."""
self._b()._cmd("navigate.reload", {"tabId": self.id}) self._b()._cmd("navigate.reload", {"tabId": self.id})
+22 -1
View File
@@ -141,6 +141,8 @@ async function dispatch(command, args) {
case "tabs.dedupe": return tabsDedupe(); case "tabs.dedupe": return tabsDedupe();
case "tabs.sort": return tabsSort(args); case "tabs.sort": return tabsSort(args);
case "tabs.merge_windows": return tabsMergeWindows(); case "tabs.merge_windows": return tabsMergeWindows();
case "tabs.mute": return tabsMute(args);
case "tabs.unmute": return tabsUnmute(args);
// ── Groups ──────────────────────────────────────────────────────────── // ── Groups ────────────────────────────────────────────────────────────
case "group.list": return groupList(); case "group.list": return groupList();
@@ -439,8 +441,27 @@ async function tabsMergeWindows() {
return { moved }; return { moved };
} }
async function tabsMute({ tabId }) {
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
await chrome.tabs.update(tab.id, { muted: true });
return { tabId: tab.id, muted: true };
}
async function tabsUnmute({ tabId }) {
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
await chrome.tabs.update(tab.id, { muted: false });
return { tabId: tab.id, muted: false };
}
function tabInfo(t) { function tabInfo(t) {
return { id: t.id, windowId: t.windowId, active: t.active, title: t.title, url: t.url }; return {
id: t.id,
windowId: t.windowId,
active: t.active,
muted: Boolean(t.mutedInfo && t.mutedInfo.muted),
title: t.title,
url: t.url,
};
} }
// ── Groups ──────────────────────────────────────────────────────────────────── // ── Groups ────────────────────────────────────────────────────────────────────
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "browser-cli", "name": "browser-cli",
"version": "0.5.8", "version": "0.5.10",
"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
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "browser-cli" name = "browser-cli"
version = "0.5.8" version = "0.5.10"
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 = [
+19
View File
@@ -12,6 +12,7 @@ def test_tabs_list(browser):
assert "windowId" in first assert "windowId" in first
assert "url" in first assert "url" in first
assert "title" in first assert "title" in first
assert "muted" in first
def test_tabs_count(browser): def test_tabs_count(browser):
@@ -114,3 +115,21 @@ def test_tabs_merge_windows_no_crash(browser):
result = browser("tabs.merge_windows") result = browser("tabs.merge_windows")
assert isinstance(result, dict) assert isinstance(result, dict)
assert "moved" in result assert "moved" in result
def test_tabs_mute_and_unmute(browser, http_tab):
muted = browser("tabs.mute", {"tabId": http_tab["id"]})
assert isinstance(muted, dict)
assert muted["tabId"] == http_tab["id"]
assert muted["muted"] is True
listed = browser("tabs.list")
listed_tab = next(t for t in listed if t["id"] == http_tab["id"])
assert listed_tab["muted"] is True
unmuted = browser("tabs.unmute", {"tabId": http_tab["id"]})
assert isinstance(unmuted, dict)
assert unmuted["tabId"] == http_tab["id"]
assert unmuted["muted"] is False
listed = browser("tabs.list")
listed_tab = next(t for t in listed if t["id"] == http_tab["id"])
assert listed_tab["muted"] is False