added logic to always show site text count
This commit is contained in:
@@ -596,6 +596,7 @@ async function refreshToolbar() {
|
||||
|
||||
|
||||
let refreshTimer = null;
|
||||
let contentChangeTimer = null;
|
||||
function scheduleToolbarRefresh() {
|
||||
if (refreshTimer) return;
|
||||
refreshTimer = window.setTimeout(() => {
|
||||
@@ -610,9 +611,22 @@ function scheduleToolbarRefresh() {
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function scheduleContentChangeNotice() {
|
||||
if (contentChangeTimer) return;
|
||||
contentChangeTimer = window.setTimeout(() => {
|
||||
contentChangeTimer = null;
|
||||
chrome.runtime.sendMessage({ type: "SITE_CONTENT_CHANGED" }, () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}, 250);
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
if (suppressObserver) return;
|
||||
scheduleToolbarRefresh();
|
||||
scheduleContentChangeNotice();
|
||||
});
|
||||
|
||||
observer.observe(document.documentElement, { childList: true, subtree: true });
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
</div>
|
||||
<div class="meta">
|
||||
<span id="postingCount">Site Text: 0 chars</span>
|
||||
<span id="promptCount">Task: 0 chars</span>
|
||||
<span id="promptCount">Total: 0 chars</span>
|
||||
<span id="status" class="status">Idle</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -57,7 +57,9 @@ const state = {
|
||||
selectedTaskId: "",
|
||||
selectedEnvId: "",
|
||||
selectedProfileId: "",
|
||||
alwaysShowOutput: false
|
||||
alwaysShowOutput: false,
|
||||
activeTabId: null,
|
||||
pendingConfigRefresh: false
|
||||
};
|
||||
|
||||
async function switchState(stateName) {
|
||||
@@ -118,6 +120,7 @@ function applyPopupDraft(draft) {
|
||||
} else if (typeof draft.siteTextSelector === "string") {
|
||||
state.siteTextTarget = { kind: "css", selector: draft.siteTextSelector };
|
||||
}
|
||||
updateCounts();
|
||||
}
|
||||
|
||||
function matchUrl(url, pattern) {
|
||||
@@ -677,6 +680,10 @@ function setAnalyzing(isAnalyzing) {
|
||||
updateTaskSelectState();
|
||||
updateEnvSelectState();
|
||||
updateProfileSelectState();
|
||||
if (!isAnalyzing && state.pendingConfigRefresh) {
|
||||
state.pendingConfigRefresh = false;
|
||||
scheduleConfigRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
function updateOutputVisibility() {
|
||||
@@ -686,12 +693,93 @@ function updateOutputVisibility() {
|
||||
outputSection.classList.toggle("hidden", shouldHide);
|
||||
}
|
||||
|
||||
function getSelectedTask() {
|
||||
if (state.forcedTask) return state.forcedTask;
|
||||
const selectedId = taskSelect?.value || state.selectedTaskId;
|
||||
return state.tasks.find((item) => item.id === selectedId) || state.tasks[0] || null;
|
||||
}
|
||||
|
||||
function getSelectedProfile() {
|
||||
const selectedId = profileSelect?.value || state.selectedProfileId;
|
||||
return (
|
||||
state.profiles.find((item) => item.id === selectedId) ||
|
||||
state.profiles[0] ||
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
function getSelectedEnv() {
|
||||
const selectedId = envSelect?.value || state.selectedEnvId;
|
||||
return state.envs.find((item) => item.id === selectedId) || state.envs[0] || null;
|
||||
}
|
||||
|
||||
function buildTotalPromptText() {
|
||||
const task = getSelectedTask();
|
||||
const profile = getSelectedProfile();
|
||||
const env = getSelectedEnv();
|
||||
const systemPrompt = env?.systemPrompt || "";
|
||||
const userPrompt = buildUserMessage(
|
||||
profile?.text || "",
|
||||
task?.text || "",
|
||||
state.siteText || ""
|
||||
);
|
||||
return systemPrompt ? `${systemPrompt}\n\n${userPrompt}` : userPrompt;
|
||||
}
|
||||
|
||||
function updateSiteTextCount() {
|
||||
postingCountEl.textContent = `Site Text: ${state.siteText.length} chars`;
|
||||
const length = (state.siteText || "").length;
|
||||
postingCountEl.textContent = `Site Text: ${length} chars`;
|
||||
}
|
||||
|
||||
function updatePromptCount(count) {
|
||||
promptCountEl.textContent = `Task: ${count} chars`;
|
||||
const total =
|
||||
typeof count === "number" ? count : buildTotalPromptText().length;
|
||||
promptCountEl.textContent = `Total: ${total} chars`;
|
||||
}
|
||||
|
||||
function updateCounts() {
|
||||
updateSiteTextCount();
|
||||
updatePromptCount();
|
||||
}
|
||||
|
||||
let siteContentRefreshTimer = null;
|
||||
function scheduleSiteContentRefresh() {
|
||||
if (siteContentRefreshTimer) return;
|
||||
siteContentRefreshTimer = window.setTimeout(() => {
|
||||
siteContentRefreshTimer = null;
|
||||
void refreshSiteContentCounts();
|
||||
}, 250);
|
||||
}
|
||||
|
||||
let configRefreshTimer = null;
|
||||
function scheduleConfigRefresh() {
|
||||
if (state.isAnalyzing) {
|
||||
state.pendingConfigRefresh = true;
|
||||
return;
|
||||
}
|
||||
if (configRefreshTimer) return;
|
||||
configRefreshTimer = window.setTimeout(() => {
|
||||
configRefreshTimer = null;
|
||||
void loadConfig();
|
||||
}, 250);
|
||||
}
|
||||
|
||||
async function refreshSiteContentCounts() {
|
||||
if (state.isAnalyzing) return;
|
||||
if (state.currentPopupState !== "normal") return;
|
||||
if (!state.siteTextTarget) return;
|
||||
try {
|
||||
const response = await sendToActiveTab({
|
||||
type: "EXTRACT_BY_SELECTOR",
|
||||
target: state.siteTextTarget
|
||||
});
|
||||
if (!response?.ok) return;
|
||||
state.siteText = response.extracted || "";
|
||||
state.siteTextTarget = response.target || state.siteTextTarget;
|
||||
updateCounts();
|
||||
} catch {
|
||||
// Ignore refresh failures; counts will update on next explicit extract.
|
||||
}
|
||||
}
|
||||
|
||||
function renderTasks(tasks) {
|
||||
@@ -792,6 +880,7 @@ function setEnvironmentSelection(envId) {
|
||||
envSelect.value = target;
|
||||
}
|
||||
state.selectedEnvId = target;
|
||||
updatePromptCount();
|
||||
}
|
||||
|
||||
function setProfileSelection(profileId) {
|
||||
@@ -803,6 +892,7 @@ function setProfileSelection(profileId) {
|
||||
profileSelect.value = target;
|
||||
}
|
||||
state.selectedProfileId = target;
|
||||
updatePromptCount();
|
||||
}
|
||||
|
||||
function selectTask(taskId, { resetEnv } = { resetEnv: false }) {
|
||||
@@ -814,6 +904,7 @@ function selectTask(taskId, { resetEnv } = { resetEnv: false }) {
|
||||
setEnvironmentSelection(getTaskDefaultEnvId(task));
|
||||
setProfileSelection(getTaskDefaultProfileId(task));
|
||||
}
|
||||
updatePromptCount();
|
||||
}
|
||||
|
||||
async function persistSelections() {
|
||||
@@ -900,6 +991,7 @@ function ensurePort() {
|
||||
async function loadConfig() {
|
||||
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
const currentUrl = tabs[0]?.url || "";
|
||||
state.activeTabId = tabs[0]?.id || null;
|
||||
|
||||
const { lastPopupState, [POPUP_DRAFT_KEY]: popupDraft } = await getStorage([
|
||||
"lastPopupState",
|
||||
@@ -968,6 +1060,9 @@ async function loadConfig() {
|
||||
state.currentWorkspace = activeWorkspace;
|
||||
currentWorkspaceName.textContent = activeWorkspace.name || "Global";
|
||||
}
|
||||
if (state.currentSite && !state.siteTextTarget) {
|
||||
state.siteTextTarget = normalizeStoredExtractTarget(state.currentSite);
|
||||
}
|
||||
if (stored.theme) {
|
||||
state.globalTheme = stored.theme;
|
||||
}
|
||||
@@ -1005,6 +1100,7 @@ async function loadConfig() {
|
||||
state.selectedTaskId = "";
|
||||
setEnvironmentSelection(effectiveEnvs[0]?.id || "");
|
||||
setProfileSelection(effectiveProfiles[0]?.id || "");
|
||||
updateCounts();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1040,6 +1136,10 @@ async function loadConfig() {
|
||||
await persistSelections();
|
||||
}
|
||||
|
||||
updateCounts();
|
||||
if (state.currentSite) {
|
||||
await refreshSiteContentCounts();
|
||||
}
|
||||
maybeRunDefaultTask();
|
||||
}
|
||||
|
||||
@@ -1068,8 +1168,7 @@ async function handleExtract() {
|
||||
|
||||
state.siteText = response.extracted || "";
|
||||
state.siteTextTarget = response.target || target;
|
||||
updateSiteTextCount();
|
||||
updatePromptCount(0);
|
||||
updateCounts();
|
||||
setStatus("Text extracted.");
|
||||
return true;
|
||||
} catch (error) {
|
||||
@@ -1199,7 +1298,7 @@ async function handleAnalyze() {
|
||||
task.text || "",
|
||||
state.siteText
|
||||
);
|
||||
updatePromptCount(promptText.length);
|
||||
updatePromptCount();
|
||||
|
||||
state.outputRaw = "";
|
||||
renderOutput();
|
||||
@@ -1298,6 +1397,7 @@ async function runMinimalExtraction(text, minLength = 5) {
|
||||
state.siteText = response.extracted;
|
||||
state.siteTextTarget = response.target || { kind: "textScope", text: trimmed };
|
||||
extractedPreview.textContent = state.siteText;
|
||||
updateCounts();
|
||||
await fillSiteDefaultsFromTab();
|
||||
switchState("review");
|
||||
await persistPopupDraft();
|
||||
@@ -1336,6 +1436,7 @@ extractFullBtn.addEventListener("click", async () => {
|
||||
state.siteText = response.extracted;
|
||||
state.siteTextTarget = target;
|
||||
extractedPreview.textContent = state.siteText;
|
||||
updateCounts();
|
||||
await fillSiteDefaultsFromTab();
|
||||
switchState("review");
|
||||
await persistPopupDraft();
|
||||
@@ -1372,6 +1473,7 @@ retryExtractBtn.addEventListener("click", () => {
|
||||
if (workspaceSelect) workspaceSelect.value = "global";
|
||||
state.siteText = "";
|
||||
state.siteTextTarget = null;
|
||||
updateCounts();
|
||||
setMinimalStatus("");
|
||||
void clearPopupDraft();
|
||||
setStatus("Ready.");
|
||||
@@ -1427,7 +1529,7 @@ confirmSiteBtn.addEventListener("click", async () => {
|
||||
currentWorkspaceName.textContent = state.currentWorkspace.name || "Global";
|
||||
await loadConfig();
|
||||
await switchState("normal");
|
||||
updateSiteTextCount();
|
||||
updateCounts();
|
||||
setStatus("Site saved.");
|
||||
});
|
||||
|
||||
@@ -1450,8 +1552,7 @@ profileSelect.addEventListener("change", () => {
|
||||
void persistSelections();
|
||||
});
|
||||
|
||||
updateSiteTextCount();
|
||||
updatePromptCount(0);
|
||||
updateCounts();
|
||||
renderOutput();
|
||||
setAnalyzing(false);
|
||||
void loadTheme();
|
||||
@@ -1597,4 +1698,27 @@ chrome.storage.onChanged.addListener((changes) => {
|
||||
state.alwaysShowOutput = Boolean(changes.alwaysShowOutput.newValue);
|
||||
updateOutputVisibility();
|
||||
}
|
||||
|
||||
const configKeys = [
|
||||
"tasks",
|
||||
"envConfigs",
|
||||
"profiles",
|
||||
"shortcuts",
|
||||
"workspaces",
|
||||
"sites",
|
||||
"theme",
|
||||
"alwaysShowOutput"
|
||||
];
|
||||
if (configKeys.some((key) => changes[key])) {
|
||||
scheduleConfigRefresh();
|
||||
}
|
||||
});
|
||||
|
||||
chrome.runtime.onMessage.addListener((message, sender) => {
|
||||
if (message?.type !== "SITE_CONTENT_CHANGED") return;
|
||||
const senderTabId = sender?.tab?.id || null;
|
||||
if (state.activeTabId && senderTabId && senderTabId !== state.activeTabId) {
|
||||
return;
|
||||
}
|
||||
scheduleSiteContentRefresh();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user