deerflow-code/browser-extension/deer-web-clipper/popup.js
2026-09-07 18:24:55 +08:00

152 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

function setStatus(message) {
document.getElementById("status").textContent = message;
}
async function getActiveTab() {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab?.id) {
throw new Error("No readable active tab found.");
}
return tab;
}
async function captureFromActiveTab(tabId) {
const [result] = await chrome.scripting.executeScript({
target: { tabId },
func: deerExtractCurrentPage,
});
if (!result?.result?.content) {
throw new Error("The current page has no readable text to send.");
}
return result.result;
}
async function submitToZncm(page, settings, prompt) {
const apiBaseUrl = deerNormalizeBaseUrl(settings.apiBaseUrl || DEER_CLIPPER_DEFAULTS.apiBaseUrl);
const response = await fetch(`${apiBaseUrl}/api/browser-context/capture`, {
method: "POST",
headers: {
"Content-Type": "application/json",
...deerAuthHeaders(settings),
},
body: JSON.stringify({
title: page.title,
url: page.url,
content: page.content,
content_type: page.contentType,
prompt,
}),
});
const data = await response.json().catch(() => ({}));
if (!response.ok) {
const detail = typeof data.detail === "string" ? data.detail : JSON.stringify(data.detail || data);
throw new Error(detail || `HTTP ${response.status}`);
}
return data;
}
async function sendCurrentPage() {
const sendButton = document.getElementById("send");
sendButton.disabled = true;
setStatus("正在读取当前页面...");
try {
await syncToken({ silent: true });
const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS);
const prompt = document.getElementById("prompt").value.trim() || settings.defaultPrompt || DEER_CLIPPER_DEFAULT_PROMPT;
const tab = await getActiveTab();
const page = await captureFromActiveTab(tab.id);
setStatus("正在发送到 zncm...");
const result = await submitToZncm(page, settings, prompt);
const webBaseUrl = deerNormalizeBaseUrl(settings.webBaseUrl || DEER_CLIPPER_DEFAULTS.webBaseUrl);
await chrome.tabs.create({ url: `${webBaseUrl}/${result.chat_url}`.replace(/\/#/g, "/#") });
setStatus("已发送,zncm 聊天页面已打开。");
} catch (error) {
setStatus(error instanceof Error ? error.message : "发送失败。");
} finally {
sendButton.disabled = false;
}
}
function sendSyncTokenMessage() {
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ type: "zncm-sync-token" }, (response) => {
const error = chrome.runtime.lastError;
if (error) {
reject(new Error(error.message));
return;
}
resolve(response || { ok: false, message: "Token 同步没有返回结果。" });
});
});
}
function sendPollNowMessage() {
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ type: "zncm-poll-now" }, (response) => {
const error = chrome.runtime.lastError;
if (error) {
reject(new Error(error.message));
return;
}
resolve(response || { ok: true, message: "Poll requested." });
});
});
}
async function syncToken(options = {}) {
const button = document.getElementById("syncToken");
button.disabled = true;
if (!options.silent) {
setStatus("正在同步 zncm token...");
}
try {
const response = await sendSyncTokenMessage();
if (!options.silent) {
setStatus(response.message || "Token sync finished.");
}
return response;
} catch (error) {
if (!options.silent) {
setStatus(error instanceof Error ? error.message : "Token 同步失败。");
}
return { ok: false, message: error instanceof Error ? error.message : "Token 同步失败。" };
} finally {
button.disabled = false;
}
}
async function pollNow() {
const button = document.getElementById("pollNow");
button.disabled = true;
setStatus("正在检查 zncm 浏览器任务...");
try {
await syncToken({ silent: true });
const response = await sendPollNowMessage();
setStatus(response.message || "任务检查完成。");
} catch (error) {
setStatus(error instanceof Error ? error.message : "任务检查失败。");
} finally {
button.disabled = false;
}
}
async function togglePageAssistant() {
const enabled = document.getElementById("pageAssistantEnabled").checked;
await chrome.storage.sync.set({ pageAssistantEnabled: enabled });
setStatus(enabled ? "页面问答框已开启。" : "页面问答框已关闭。");
}
async function init() {
const settings = await chrome.storage.sync.get(DEER_CLIPPER_DEFAULTS);
document.getElementById("prompt").value = settings.defaultPrompt || DEER_CLIPPER_DEFAULT_PROMPT;
document.getElementById("pageAssistantEnabled").checked = Boolean(settings.pageAssistantEnabled);
document.getElementById("send").addEventListener("click", sendCurrentPage);
document.getElementById("syncToken").addEventListener("click", () => syncToken());
document.getElementById("pollNow").addEventListener("click", pollNow);
document.getElementById("pageAssistantEnabled").addEventListener("change", togglePageAssistant);
document.getElementById("options").addEventListener("click", () => chrome.runtime.openOptionsPage());
}
void init();