chrome.tabs.create({ url: bookmark.url })
chrome.tabs.create({ url: bookmark.url, active: false })
chrome.windows.create({ url: bookmark.url })
chrome.windows.create({ url: bookmark.url, incognito: true })
const tabIds = [];
for (const bookmark of bookmarks) {
if (!bookmark.url) continue;
const tab = await chrome.tabs.create({ url: bookmark.url, active: false });
tabIds.push(tab.id);
}
if (tabIds.length === 0) return;
const groupId = await chrome.tabs.group({ tabIds });
const color = (inputs.color || '').toLowerCase();
const updateProps = {};
if (inputs.name) updateProps.title = inputs.name;
if (color && color !== 'unspecified') updateProps.color = color;
if (Object.keys(updateProps).length > 0) {
await chrome.tabGroups.update(groupId, updateProps);
}
await chrome.bookmarks.create({
parentId: bookmark.parentId,
title: bookmark.title,
url: bookmark.url,
index: bookmark.index + 1
});
await chrome.bookmarks.update(bookmark.id, { title: inputs.title });
await chrome.bookmarks.update(bookmark.id, { url: inputs.url });
const parentId = await resolveBookmarkParentFolder(inputs);
await chrome.bookmarks.create({ title: inputs.folder, parentId });
const parentId = await resolveBookmarkFolder(inputs);
await chrome.bookmarks.move(bookmark.id, { parentId });
const sorted = [...bookmarks].sort((a, b) => (a.url || "").localeCompare(b.url || ""));
for (const [i, bookmark] of sorted.entries()) {
await chrome.bookmarks.move(bookmark.id, { index: i });
}
const sorted = [...bookmarks].sort((a, b) => (a.title || "").localeCompare(b.title || ""));
for (const [i, bookmark] of sorted.entries()) {
await chrome.bookmarks.move(bookmark.id, { index: i });
}
const shuffled = shuffleArray(bookmarks);
for (const [i, bookmark] of shuffled.entries()) {
await chrome.bookmarks.move(bookmark.id, { index: i });
}
const seen = new Set();
for (const bookmark of bookmarks) {
if (!bookmark.url) continue;
if (seen.has(bookmark.url)) {
await chrome.bookmarks.remove(bookmark.id);
} else {
seen.add(bookmark.url);
}
}
const lastByUrl = new Map();
for (const bookmark of bookmarks) {
if (!bookmark.url) continue;
lastByUrl.set(bookmark.url, bookmark.id);
}
const keepIds = new Set(lastByUrl.values());
for (const bookmark of bookmarks) {
if (bookmark.url && !keepIds.has(bookmark.id)) {
await chrome.bookmarks.remove(bookmark.id);
}
}
const replace = inputs.replace || "";
const regex = new RegExp(inputs.find, "g");
if (!bookmark.url) return;
const newUrl = bookmark.url.replace(regex, replace);
if (newUrl !== bookmark.url) {
await chrome.bookmarks.update(bookmark.id, { url: newUrl });
}
const replace = inputs.replace || "";
const regex = new RegExp(inputs.find, "g");
const currentTitle = bookmark.title || "";
const newTitle = currentTitle.replace(regex, replace);
if (newTitle !== currentTitle) {
await chrome.bookmarks.update(bookmark.id, { title: newTitle });
}
const text = (bookmarks || []).map(b => b.url).filter(Boolean).join("\n");
await copyToClipboard(text);
const json = JSON.stringify(bookmarks || [], null, 2);
const blob = new Blob([json], { type: "application/json" });
const url = URL.createObjectURL(blob);
await chrome.downloads.download({ url, filename: "bookmarks-export.json" });
chrome.bookmarks.remove(bookmark.id)
const dispositionMap = { 'Current Tab': 'CURRENT_TAB', 'New Window': 'NEW_WINDOW' };
const disposition = dispositionMap[inputs.disposition] || 'NEW_TAB';
return chrome.search.query({ text: inputs.query, disposition });
const sessions = await chrome.sessions.getRecentlyClosed({ maxResults: 1 });
if (sessions.length === 0) return;
const session = sessions[0];
const sessionId = session.tab?.sessionId || session.window?.sessionId;
if (!sessionId) return;
await chrome.sessions.restore(sessionId);
chrome.windows.create({})
chrome.windows.create({ incognito: true })
chrome.downloads.showDefaultFolder()
chrome.runtime.openOptionsPage()
await copyToClipboard(inputs.text, inputs.mode);
const url = (inputs.url || "").trim();
let parentId;
if (inputs.destination && inputs.destination !== "(Default)") {
parentId = await resolveBookmarkFolder(inputs);
}
await chrome.bookmarks.create({
parentId,
title: (inputs.title || "").trim() || url,
url
});
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab) throw new Error("No active tab");
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (value) => {
document.execCommand('insertText', false, value);
},
args: [inputs.text]
});
const types = Array.isArray(inputs?.types) && inputs.types.length > 0 ? inputs.types : null;
const info = await getSystemInfo(types);
await copyToClipboard(JSON.stringify(info, null, 2));
const types = Array.isArray(inputs?.types) && inputs.types.length > 0 ? inputs.types : null;
const info = await getSystemInfo(types);
const filename = `system-info-${new Date().getTime()}.json`;
const json = JSON.stringify(info, null, 2);
const blob = new Blob([json], { type: "application/json" });
const url = URL.createObjectURL(blob);
await chrome.downloads.download({ url, filename });
const parsedLimit = parseInt(inputs.limit, 10);
const limit = !isNaN(parsedLimit) ? Math.min(20, Math.max(1, parsedLimit)) : 10;
const sites = await chrome.topSites.get();
for (const site of sites.slice(0, limit)) {
await chrome.tabs.create({ url: site.url, active: false });
}
const size = parseInt(inputs.size, 10);
await chrome.fontSettings.setDefaultFontSize({ pixelSize: size });
const size = parseInt(inputs.size, 10);
await chrome.fontSettings.setMinimumFontSize({ pixelSize: size });
chrome.power.requestKeepAwake('display');
chrome.power.requestKeepAwake("system");
chrome.power.releaseKeepAwake();
chrome.runtime.reload()
const dataTypes = normalizeDataTypes(inputs.types);
const dataToRemove = buildDataToRemove(dataTypes);
const since = getSinceFromRange(inputs.range);
await chrome.browsingData.remove({ since }, dataToRemove);
const name = inputs.name;
const extensions = await chrome.management.getAll();
const target = extensions.find(e => e.name.toLowerCase().includes(name.toLowerCase()));
if (target) {
await chrome.management.setEnabled(target.id, true);
} else {
throw new Error(`Extension "${name}" not found`);
}
const extensions = await chrome.management.getAll();
for (const ext of extensions) {
if (!ext.enabled && ext.type === "extension") {
try {
await chrome.management.setEnabled(ext.id, true);
} catch (e) {
logger.error(`Failed to enable extension: ${ext.name}`, e);
}
}
}
const name = inputs.name;
const extensions = await chrome.management.getAll();
const target = extensions.find(e => e.name.toLowerCase().includes(name.toLowerCase()));
if (target) {
await chrome.management.setEnabled(target.id, !target.enabled);
} else {
throw new Error(`Extension "${name}" not found`);
}
const name = inputs.name;
const extensions = await chrome.management.getAll();
const target = extensions.find(e => e.name.toLowerCase().includes(name.toLowerCase()));
if (target) {
await chrome.management.setEnabled(target.id, false);
} else {
throw new Error(`Extension "${name}" not found`);
}
const extensions = await chrome.management.getAll();
const selfId = chrome.runtime.id;
for (const ext of extensions) {
if (ext.id !== selfId && ext.enabled && ext.type === "extension") {
try {
await chrome.management.setEnabled(ext.id, false);
} catch (e) {
logger.error(`Failed to disable extension: ${ext.name}`, e, { notify: true });
}
}
}
const extensions = await chrome.management.getAll();
const selfId = chrome.runtime.id;
for (const ext of extensions) {
if (ext.id !== selfId && ext.enabled && ext.type === "extension") {
try {
await chrome.management.setEnabled(ext.id, false);
} catch (e) {
logger.error(`Failed to disable extension: ${ext.name}`, e, { notify: true });
}
}
}
await chrome.management.setEnabled(selfId, false);
applyGlobalContentSettings(inputs?.types, "allow")
applyGlobalContentSettings(inputs?.types, "block")
applyGlobalContentSettings(inputs?.types, "toggle")
setGlobalContentSetting("cookies", "session_only")
for (const type of GLOBAL_CONTENT_SETTING_DEFAULTS) {
await clearGlobalContentSetting(type);
}
const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
const url = inputs.url || undefined;
const position = inputs.position || "Right of Tab";
let index;
if (position === "Right of Tab") {
index = activeTab ? activeTab.index + 1 : undefined;
} else if (position === "Left of Tab") {
index = activeTab ? activeTab.index : undefined;
} else if (position === "First") {
index = 0;
} else if (position === "Last") {
index = undefined; // Chrome places at end by default
} else if (position === "Random") {
const tabs = await chrome.tabs.query({ currentWindow: true });
index = Math.floor(Math.random() * (tabs.length + 1));
}
return chrome.tabs.create({ url, index });
chrome.tabs.remove(tab.id)
chrome.tabs.duplicate(tab.id)
chrome.tabs.discard(tab.id)
chrome.tabs.reload(tab.id)
chrome.tabs.reload(tab.id, { bypassCache: true })
chrome.tabs.goBack(tab.id)
chrome.tabs.goForward(tab.id)
chrome.tabs.update(tab.id, { active: true })
if (!Array.isArray(tabs) || tabs.length === 0) return;
const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!activeTab) return;
const sortedTabs = [...tabs].sort((a, b) => a.index - b.index);
const currentIndex = sortedTabs.findIndex(t => t.id === activeTab.id);
const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % sortedTabs.length;
const nextTab = sortedTabs[nextIndex];
if (!nextTab) return;
await chrome.tabs.update(nextTab.id, { active: true });
await chrome.windows.update(nextTab.windowId, { focused: true });
if (!Array.isArray(tabs) || tabs.length === 0) return;
const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!activeTab) return;
const sortedTabs = [...tabs].sort((a, b) => a.index - b.index);
const currentIndex = sortedTabs.findIndex(t => t.id === activeTab.id);
const prevIndex = currentIndex === -1 ? sortedTabs.length - 1 : (currentIndex - 1 + sortedTabs.length) % sortedTabs.length;
const prevTab = sortedTabs[prevIndex];
if (!prevTab) return;
await chrome.tabs.update(prevTab.id, { active: true });
await chrome.windows.update(prevTab.windowId, { focused: true });
const tabsByWindow = new Map();
for (const tab of tabs || []) {
if (!tab) continue;
if (typeof tab.windowId !== "number" || typeof tab.index !== "number") continue;
if (!tabsByWindow.has(tab.windowId)) {
tabsByWindow.set(tab.windowId, []);
}
tabsByWindow.get(tab.windowId).push(tab.index);
}
for (const [windowId, indices] of tabsByWindow) {
if (indices.length > 0) {
await chrome.tabs.highlight({ windowId, tabs: indices });
}
}
chrome.tabs.update(tab.id, { pinned: true })
chrome.tabs.update(tab.id, { pinned: false })
chrome.tabs.update(tab.id, { pinned: !tab.pinned })
chrome.tabs.update(tab.id, { muted: true })
chrome.tabs.update(tab.id, { muted: false })
chrome.tabs.update(tab.id, { muted: !tab.mutedInfo?.muted })
if (tab.index > 0) {
await chrome.tabs.move(tab.id, { index: tab.index - 1 });
}
chrome.tabs.move(tab.id, { index: tab.index + 1 })
chrome.tabs.move(tab.id, { index: 0 })
chrome.tabs.move(tab.id, { index: -1 })
let index = parseInt(inputs.index, 10);
if (index < 0) {
const tabs = await chrome.tabs.query({ windowId: tab.windowId });
index = Math.max(0, tabs.length + index);
}
return chrome.tabs.move(tab.id, { index });
const tabIds = (tabs || []).map((t) => t?.id).filter((id) => typeof id === "number");
const win = await chrome.windows.create({ tabId: tabIds[0] });
if (tabIds.length > 1) {
await chrome.tabs.move(tabIds.slice(1), { windowId: win.id, index: -1 });
}
const win = await chrome.windows.create({});
const defaultTab = win.tabs && win.tabs[0];
for (const tab of tabs || []) {
if (!tab || !tab.url) continue;
await chrome.tabs.create({ windowId: win.id, url: tab.url });
}
if (defaultTab) {
await chrome.tabs.remove(defaultTab.id);
}
const tabIds = (tabs || []).map((t) => t?.id).filter((id) => typeof id === "number");
const groupId = await chrome.tabs.group({ tabIds });
const color = inputs.color.toLowerCase();
const updateProps = {};
if (inputs.name) updateProps.title = inputs.name;
if (color && color !== "unspecified") updateProps.color = color;
if (Object.keys(updateProps).length > 0) {
await chrome.tabGroups.update(groupId, updateProps);
}
const name = (inputs.groupName || '').trim();
const groups = await chrome.tabGroups.query({});
const targetGroup = groups.find((group) => String(group?.title || '').trim().toLowerCase() === name.toLowerCase());
const groupId = targetGroup ? targetGroup.id : null;
if (groupId === null) throw new Error(`Group "${name}" not found`);
const tabIds = (tabs || []).map((t) => t?.id).filter((id) => typeof id === "number");
await chrome.tabs.group({ tabIds, groupId });
const domainMap = new Map();
for (const tab of tabs || []) {
try {
if (!tab || !tab.url) continue;
const domain = new URL(tab.url).hostname;
if (!domainMap.has(domain)) {
domainMap.set(domain, []);
}
domainMap.get(domain).push(tab.id);
} catch {
// ignore invalid URLs
}
}
const color = inputs.color.toLowerCase();
for (const [domain, ids] of domainMap) {
if (ids.length > 1) {
const groupId = await chrome.tabs.group({ tabIds: ids });
const updateProps = { title: domain };
if (color && color !== "unspecified") updateProps.color = color;
await chrome.tabGroups.update(groupId, updateProps);
}
}
chrome.tabs.ungroup(tab.id)
const seen = new Set();
const toClose = [];
for (const tab of tabs) {
if (!tab.url) continue;
if (seen.has(tab.url)) {
toClose.push(tab.id);
} else {
seen.add(tab.url);
}
}
if (toClose.length > 0) {
await chrome.tabs.remove(toClose);
}
const lastByUrl = new Map();
for (const tab of tabs) {
if (!tab.url) continue;
lastByUrl.set(tab.url, tab.id);
}
const keepIds = new Set(lastByUrl.values());
const toClose = [];
for (const tab of tabs) {
if (tab.url && !keepIds.has(tab.id)) {
toClose.push(tab.id);
}
}
if (toClose.length > 0) {
await chrome.tabs.remove(toClose);
}
const sorted = [...tabs].sort((a, b) => (a.url || "").localeCompare(b.url || ""));
for (const [i, tab] of sorted.entries()) {
await chrome.tabs.move(tab.id, { index: i });
}
const sorted = [...tabs].sort((a, b) => (a.title || "").localeCompare(b.title || ""));
for (const [i, tab] of sorted.entries()) {
await chrome.tabs.move(tab.id, { index: i });
}
const shuffled = shuffleArray(tabs);
for (const [i, tab] of shuffled.entries()) {
await chrome.tabs.move(tab.id, { index: i });
}
const zoom = await chrome.tabs.getZoom(tab.id);
const value = String(inputs.step ?? '').trim();
let delta;
if (!value) {
delta = 0.1;
} else if (value.endsWith('%')) {
const percent = parseFloat(value.slice(0, -1));
delta = percent / 100;
} else {
const numeric = parseFloat(value);
delta = numeric <= 1 ? numeric : numeric / 100;
}
await chrome.tabs.setZoom(tab.id, Math.min(zoom + delta, ZOOM_LIMITS.max));
const zoom = await chrome.tabs.getZoom(tab.id);
const value = String(inputs.step ?? '').trim();
let delta;
if (!value) {
delta = 0.1;
} else if (value.endsWith('%')) {
const percent = parseFloat(value.slice(0, -1));
delta = percent / 100;
} else {
const numeric = parseFloat(value);
delta = numeric <= 1 ? numeric : numeric / 100;
}
await chrome.tabs.setZoom(tab.id, Math.max(zoom - delta, ZOOM_LIMITS.min));
const level = parseFloat(inputs.level);
if (!isNaN(level) && level >= ZOOM_LIMITS.min && level <= ZOOM_LIMITS.max) {
return chrome.tabs.setZoom(tab.id, level);
}
const text = (tabs || []).map(t => t.url).filter(Boolean).join("\n");
await copyToClipboard(text);
const json = JSON.stringify(tabs || [], null, 2);
const blob = new Blob([json], { type: "application/json" });
const url = URL.createObjectURL(blob);
await chrome.downloads.download({ url, filename: "tab-inventory.json" });
try {
await chrome.tabs.update(tab.id, { active: true });
await new Promise(r => setTimeout(r, 100));
const formatMap = { 'PNG': 'png', 'JPG': 'jpeg' };
const extMap = { 'PNG': '.png', 'JPG': '.jpg' };
const chosen = inputs.format || 'PNG';
const format = formatMap[chosen] || 'png';
const ext = extMap[chosen] || '.png';
const dataUrl = await chrome.tabs.captureVisibleTab(tab.windowId, { format });
const dateStr = new Date().toISOString().split('T')[0];
let filename = (inputs.filename || '{{url}}-{{date}}')
.replace(/\{\{date\}\}/g, dateStr)
.replace(/\{\{title\}\}/g, tab.title || String(tab.id))
.replace(/\{\{url\}\}/g, safeHostname(tab.url));
filename = filename.replace(/[<>:"/\\|?*]+/g, '_').replace(/_{2,}/g, '_').replace(/^_|_$/g, '') + ext;
await chrome.downloads.download({ url: dataUrl, filename });
} catch (e) {
logger.error("Screenshot failed:", e, { notify: true });
}
try {
await chrome.tabs.update(tab.id, { active: true });
await new Promise(r => setTimeout(r, 100));
const dataUrl = await chrome.tabs.captureVisibleTab(tab.windowId, { format: "png" });
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: async (url) => {
const res = await fetch(url);
const blob = await res.blob();
const item = new ClipboardItem({ [blob.type]: blob });
await navigator.clipboard.write([item]);
},
args: [dataUrl]
});
} catch (e) {
logger.error("Screenshot to clipboard failed:", e, { notify: true });
}
const replace = inputs.replace || "";
const regex = new RegExp(inputs.find, "g");
const newUrl = tab.url.replace(regex, replace);
if (newUrl !== tab.url) {
await chrome.tabs.update(tab.id, { url: newUrl });
}
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => window.print()
});
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (scrollBehavior) => {
window.scrollTo({ top: 0, behavior: scrollBehavior });
},
args: [behavior]
});
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (scrollBehavior) => {
const maxScrollTop = Math.max(
document.body?.scrollHeight || 0,
document.documentElement?.scrollHeight || 0
);
window.scrollTo({ top: maxScrollTop, behavior: scrollBehavior });
},
args: [behavior]
});
const parsedAmount = parseInt(inputs?.amount, 10);
const amount = !isNaN(parsedAmount) && parsedAmount > 0 ? parsedAmount : 300;
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (pixels, scrollBehavior) => {
window.scrollBy({ top: -pixels, left: 0, behavior: scrollBehavior });
},
args: [amount, behavior]
});
const parsedAmount = parseInt(inputs?.amount, 10);
const amount = !isNaN(parsedAmount) && parsedAmount > 0 ? parsedAmount : 300;
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (pixels, scrollBehavior) => {
window.scrollBy({ top: pixels, left: 0, behavior: scrollBehavior });
},
args: [amount, behavior]
});
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (scrollBehavior) => {
window.scrollBy({ top: -window.innerHeight, left: 0, behavior: scrollBehavior });
},
args: [behavior]
});
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (scrollBehavior) => {
window.scrollBy({ top: window.innerHeight, left: 0, behavior: scrollBehavior });
},
args: [behavior]
});
const parsedAmount = parseInt(inputs?.amount, 10);
const amount = !isNaN(parsedAmount) && parsedAmount > 0 ? parsedAmount : 300;
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (pixels, scrollBehavior) => {
window.scrollBy({ top: 0, left: -pixels, behavior: scrollBehavior });
},
args: [amount, behavior]
});
const parsedAmount = parseInt(inputs?.amount, 10);
const amount = !isNaN(parsedAmount) && parsedAmount > 0 ? parsedAmount : 300;
const behavior = inputs?.smooth === true ? "smooth" : "auto";
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (pixels, scrollBehavior) => {
window.scrollBy({ top: 0, left: pixels, behavior: scrollBehavior });
},
args: [amount, behavior]
});
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: async () => {
if (typeof navigator.share !== "function") {
throw new Error("Web Share API is not available on this page");
}
await navigator.share({ title: document.title, url: location.href });
}
});
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => {
document.designMode = "on";
}
});
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => {
document.designMode = "off";
}
});
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => {
document.designMode = document.designMode === "on" ? "off" : "on";
}
});
const code = String(inputs.code || "");
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (userCode) => {
(0, eval)(userCode);
},
args: [code]
});
const css = String(inputs.css || "");
await chrome.scripting.insertCSS({
target: { tabId: tab.id },
css
});
const css = String(inputs.css || "");
await chrome.scripting.removeCSS({
target: { tabId: tab.id },
css
});
let parentId;
if (inputs.destination && inputs.destination !== '(Default)') {
parentId = await resolveBookmarkFolder(inputs);
}
await chrome.bookmarks.create({
parentId,
title: tab.title || tab.url,
url: tab.url
});
await chrome.readingList.addEntry({
url: tab.url,
title: tab.title,
hasBeenRead: false
});
if (!tab.sessionId) return;
await chrome.sessions.restore(tab.sessionId);
applySiteContentSettings(tab, inputs?.types, "allow")
applySiteContentSettings(tab, inputs?.types, "block")
applySiteContentSettings(tab, inputs?.types, "toggle")
const dataTypes = normalizeDataTypes(inputs.types);
const dataToRemove = buildDataToRemove(dataTypes);
const since = getSinceFromRange(inputs.range);
if (!tab?.url) return;
const url = new URL(tab.url);
if (url.protocol !== "http:" && url.protocol !== "https:") return;
await chrome.browsingData.remove({ since, origins: [url.origin] }, dataToRemove);
const windowId = (typeof win === "number" ? win : win?.id);
const url = inputs.url || undefined;
const position = inputs.position || "First";
let index;
if (position === "First") {
index = 0;
} else if (position === "Last") {
index = undefined; // Chrome places at end by default
} else if (position === "Random") {
const currentWindow = await chrome.windows.get(windowId, { populate: true });
const tabCount = currentWindow.tabs ? currentWindow.tabs.length : 0;
index = Math.floor(Math.random() * (tabCount + 1));
}
await chrome.tabs.create({ windowId, url, index });
chrome.windows.update((typeof win === "number" ? win : win?.id), { focused: true })
if (!Array.isArray(windows) || windows.length === 0) return;
const focusedWindow = await chrome.windows.getLastFocused();
if (!focusedWindow) return;
const sortedWindows = [...windows].sort((a, b) => a.id - b.id);
const currentIndex = sortedWindows.findIndex(w => w.id === focusedWindow.id);
const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % sortedWindows.length;
const nextWindow = sortedWindows[nextIndex];
if (!nextWindow) return;
await chrome.windows.update(nextWindow.id, { focused: true });
if (!Array.isArray(windows) || windows.length === 0) return;
const focusedWindow = await chrome.windows.getLastFocused();
if (!focusedWindow) return;
const sortedWindows = [...windows].sort((a, b) => a.id - b.id);
const currentIndex = sortedWindows.findIndex(w => w.id === focusedWindow.id);
const prevIndex = currentIndex === -1 ? sortedWindows.length - 1 : (currentIndex - 1 + sortedWindows.length) % sortedWindows.length;
const prevWindow = sortedWindows[prevIndex];
if (!prevWindow) return;
await chrome.windows.update(prevWindow.id, { focused: true });
chrome.windows.update((typeof win === "number" ? win : win?.id), { state: "minimized" })
chrome.windows.update((typeof win === "number" ? win : win?.id), { state: "maximized" })
chrome.windows.update((typeof win === "number" ? win : win?.id), { state: "fullscreen" })
chrome.windows.update((typeof win === "number" ? win : win?.id), { state: "normal" })
const windowId = (typeof win === "number" ? win : win?.id);
const current = await chrome.windows.get(windowId);
const nextState = current.state === "maximized" ? "normal" : "maximized";
await chrome.windows.update(windowId, { state: nextState });
const windowId = (typeof win === "number" ? win : win?.id);
const current = await chrome.windows.get(windowId);
const nextState = current.state === "fullscreen" ? "normal" : "fullscreen";
await chrome.windows.update(windowId, { state: nextState });
chrome.windows.update((typeof win === "number" ? win : win?.id), { drawAttention: true })
const windowId = (typeof win === "number" ? win : win?.id);
const width = parseInt(inputs.width);
const height = parseInt(inputs.height);
const update = {};
if (!isNaN(width)) update.width = width;
if (!isNaN(height)) update.height = height;
if (Object.keys(update).length > 0) {
return chrome.windows.update(windowId, update);
}
const windowId = (typeof win === "number" ? win : win?.id);
const left = parseInt(inputs.left);
const top = parseInt(inputs.top);
const update = {};
if (!isNaN(left)) update.left = left;
if (!isNaN(top)) update.top = top;
if (Object.keys(update).length > 0) {
return chrome.windows.update(windowId, update);
}
const windowId = (typeof win === "number" ? win : win?.id);
const currentWindow = await chrome.windows.get(windowId, { populate: true });
const newWin = await chrome.windows.create({});
const defaultTab = newWin.tabs && newWin.tabs[0];
for (const tab of currentWindow.tabs || []) {
if (!tab || !tab.url) continue;
await chrome.tabs.create({ windowId: newWin.id, url: tab.url });
}
if (defaultTab) {
await chrome.tabs.remove(defaultTab.id);
}
const windowId = (typeof win === "number" ? win : win?.id);
const focusedWindow = await chrome.windows.getLastFocused();
if (windowId !== focusedWindow.id) {
const currentWindow = await chrome.windows.get(windowId, { populate: true });
if (currentWindow.tabs && currentWindow.tabs.length > 0) {
const tabIds = currentWindow.tabs.map(t => t.id);
await chrome.tabs.move(tabIds, { windowId: focusedWindow.id, index: -1 });
}
}
if (win.sessionId) {
await chrome.sessions.restore(win.sessionId);
}
chrome.windows.remove((typeof win === "number" ? win : win?.id))