From 4f6450d5f3723c65cd52a96f9a06f58d32745150 Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Sun, 18 Jan 2026 12:33:59 -0500 Subject: [PATCH] UX improvements --- sitecompanion/background.js | 1 + sitecompanion/manifest.json | 2 +- sitecompanion/popup.html | 4 ++ sitecompanion/popup.js | 81 +++++++++++++++++++++++++++++++++---- sitecompanion/settings.html | 6 +++ sitecompanion/settings.js | 6 +++ 6 files changed, 92 insertions(+), 8 deletions(-) diff --git a/sitecompanion/background.js b/sitecompanion/background.js index d52524c..5be2496 100644 --- a/sitecompanion/background.js +++ b/sitecompanion/background.js @@ -18,6 +18,7 @@ const DEFAULT_SETTINGS = { shortcuts: [], theme: "system", toolbarAutoHide: true, + alwaysShowOutput: false, workspaces: [] }; diff --git a/sitecompanion/manifest.json b/sitecompanion/manifest.json index e39b611..fefeec3 100644 --- a/sitecompanion/manifest.json +++ b/sitecompanion/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "SiteCompanion", - "version": "0.4.3", + "version": "0.4.4", "description": "AI companion for site-bound text extraction and tasks.", "permissions": ["storage", "activeTab"], "host_permissions": [""], diff --git a/sitecompanion/popup.html b/sitecompanion/popup.html index 374471a..8b93dca 100644 --- a/sitecompanion/popup.html +++ b/sitecompanion/popup.html @@ -38,6 +38,10 @@ +
+ + +
diff --git a/sitecompanion/popup.js b/sitecompanion/popup.js index 09b6f7d..d88a601 100644 --- a/sitecompanion/popup.js +++ b/sitecompanion/popup.js @@ -11,6 +11,7 @@ const settingsBtn = document.getElementById("settingsBtn"); const copyRenderedBtn = document.getElementById("copyRenderedBtn"); const copyRawBtn = document.getElementById("copyRawBtn"); const clearOutputBtn = document.getElementById("clearOutputBtn"); +const outputSection = document.querySelector(".output"); const OUTPUT_STORAGE_KEY = "lastOutput"; const AUTO_RUN_KEY = "autoRunDefaultTask"; @@ -30,6 +31,7 @@ const extractFullBtn = document.getElementById("extractFullBtn"); const extractedPreview = document.getElementById("extractedPreview"); const siteNameInput = document.getElementById("siteNameInput"); const urlPatternInput = document.getElementById("urlPatternInput"); +const workspaceSelect = document.getElementById("workspaceSelect"); const retryExtractBtn = document.getElementById("retryExtractBtn"); const confirmSiteBtn = document.getElementById("confirmSiteBtn"); const currentWorkspaceName = document.getElementById("currentWorkspaceName"); @@ -54,7 +56,8 @@ const state = { siteTextTarget: null, selectedTaskId: "", selectedEnvId: "", - selectedProfileId: "" + selectedProfileId: "", + alwaysShowOutput: false }; async function switchState(stateName) { @@ -66,11 +69,13 @@ async function switchState(stateName) { if (stateName === "unknown") { unknownSiteState.classList.remove("hidden"); } else if (stateName === "review") { + updateWorkspaceOptions(); extractionReviewState.classList.remove("hidden"); } else if (stateName === "normal") { normalExecutionState.classList.remove("hidden"); } setMinimalStatus(""); + updateOutputVisibility(); await chrome.storage.local.set({ lastPopupState: stateName }); } @@ -80,7 +85,8 @@ function buildPopupDraft() { siteText: state.siteText || "", urlPattern: urlPatternInput?.value?.trim() || "", siteName: siteNameInput?.value?.trim() || "", - siteTextTarget: state.siteTextTarget + siteTextTarget: state.siteTextTarget, + workspaceId: workspaceSelect?.value || "global" }; } @@ -104,6 +110,9 @@ function applyPopupDraft(draft) { if (typeof draft.siteName === "string") { siteNameInput.value = draft.siteName; } + if (typeof draft.workspaceId === "string" && workspaceSelect) { + workspaceSelect.value = draft.workspaceId; + } if (draft.siteTextTarget) { state.siteTextTarget = draft.siteTextTarget; } else if (typeof draft.siteTextSelector === "string") { @@ -245,6 +254,31 @@ function normalizeStoredExtractTarget(site) { return null; } +function updateWorkspaceOptions() { + if (!workspaceSelect) return; + const selected = workspaceSelect.value || "global"; + workspaceSelect.innerHTML = ""; + + const globalOpt = document.createElement("option"); + globalOpt.value = "global"; + globalOpt.textContent = "Global"; + workspaceSelect.appendChild(globalOpt); + + for (const workspace of state.workspaces || []) { + const opt = document.createElement("option"); + opt.value = workspace.id; + opt.textContent = workspace.name || "Untitled Workspace"; + workspaceSelect.appendChild(opt); + } + + if (selected) { + workspaceSelect.value = selected; + } + if (!workspaceSelect.value) { + workspaceSelect.value = "global"; + } +} + function filterApiConfigsForScope(apiConfigs, workspace, site) { const workspaceDisabled = workspace?.disabledInherited?.apiConfigs || []; const siteDisabled = site?.disabledInherited?.apiConfigs || []; @@ -527,6 +561,13 @@ function setAnalyzing(isAnalyzing) { updateProfileSelectState(); } +function updateOutputVisibility() { + if (!outputSection) return; + const shouldHide = + state.currentPopupState !== "normal" && !state.alwaysShowOutput; + outputSection.classList.toggle("hidden", shouldHide); +} + function updateSiteTextCount() { postingCountEl.textContent = `Site Text: ${state.siteText.length} chars`; } @@ -766,6 +807,7 @@ async function loadConfig() { "workspaces", "sites", "theme", + "alwaysShowOutput", LAST_TASK_KEY, LAST_ENV_KEY, LAST_PROFILE_KEY @@ -789,6 +831,7 @@ async function loadConfig() { : state.workspaces; state.sites = sites; state.workspaces = workspaces; + updateWorkspaceOptions(); if (needsSiteUpdate) { await chrome.storage.local.set({ sites }); } @@ -810,7 +853,9 @@ async function loadConfig() { if (stored.theme) { state.globalTheme = stored.theme; } + state.alwaysShowOutput = Boolean(stored.alwaysShowOutput); applyTheme(resolveThemeForPopup(state.globalTheme)); + updateOutputVisibility(); const effectiveEnvs = resolveEffectiveList( envs, @@ -1206,12 +1251,18 @@ urlPatternInput.addEventListener("input", () => { void persistPopupDraft(); }); +workspaceSelect?.addEventListener("change", () => { + if (state.currentPopupState !== "review") return; + void persistPopupDraft(); +}); + retryExtractBtn.addEventListener("click", () => { switchState("unknown"); partialTextPaste.value = ""; extractedPreview.textContent = ""; urlPatternInput.value = ""; siteNameInput.value = ""; + if (workspaceSelect) workspaceSelect.value = "global"; state.siteText = ""; state.siteTextTarget = null; setMinimalStatus(""); @@ -1246,17 +1297,29 @@ confirmSiteBtn.addEventListener("click", async () => { id: `site-${Date.now()}`, name, urlPattern: pattern, - workspaceId: "global", // Default to global for now + workspaceId: workspaceSelect?.value || "global", extractTarget: state.siteTextTarget }; state.sites.push(newSite); - await chrome.storage.local.set({ sites: state.sites }); + state.outputRaw = ""; + renderOutput(); + await persistOutputNow(); + await chrome.storage.local.set({ + sites: state.sites, + [LAST_TASK_KEY]: "", + [LAST_ENV_KEY]: "", + [LAST_PROFILE_KEY]: "", + lastPopupState: "normal" + }); await clearPopupDraft(); state.currentSite = newSite; - state.currentWorkspace = { name: "Global", id: "global" }; - currentWorkspaceName.textContent = "Global"; - switchState("normal"); + const selectedWorkspace = + state.workspaces.find((entry) => entry.id === newSite.workspaceId) || null; + state.currentWorkspace = selectedWorkspace || { name: "Global", id: "global" }; + currentWorkspaceName.textContent = state.currentWorkspace.name || "Global"; + await loadConfig(); + await switchState("normal"); updateSiteTextCount(); setStatus("Site saved."); }); @@ -1423,4 +1486,8 @@ chrome.storage.onChanged.addListener((changes) => { state.globalTheme = changes.theme.newValue || "system"; applyTheme(resolveThemeForPopup(state.globalTheme)); } + if (changes.alwaysShowOutput) { + state.alwaysShowOutput = Boolean(changes.alwaysShowOutput.newValue); + updateOutputVisibility(); + } }); diff --git a/sitecompanion/settings.html b/sitecompanion/settings.html index 6b7eb2e..b16240a 100644 --- a/sitecompanion/settings.html +++ b/sitecompanion/settings.html @@ -87,6 +87,12 @@ Auto-hide toolbar on unknown sites
+
+ +
diff --git a/sitecompanion/settings.js b/sitecompanion/settings.js index 1c31eef..2883e14 100644 --- a/sitecompanion/settings.js +++ b/sitecompanion/settings.js @@ -20,6 +20,7 @@ const sidebarErrorsEl = document.getElementById("sidebarErrors"); const themeSelect = document.getElementById("themeSelect"); const toolbarPositionSelect = document.getElementById("toolbarPositionSelect"); const toolbarAutoHide = document.getElementById("toolbarAutoHide"); +const alwaysShowOutput = document.getElementById("alwaysShowOutput"); const globalSitesContainer = document.getElementById("globalSites"); const toc = document.querySelector(".toc"); const tocResizer = document.getElementById("tocResizer"); @@ -3527,6 +3528,7 @@ async function loadSettings() { sites = [], toolbarPosition = "bottom-right", toolbarAutoHide: storedToolbarAutoHide = true, + alwaysShowOutput: storedAlwaysShowOutput = false, sidebarWidth } = await getStorage([ "apiKey", @@ -3563,6 +3565,9 @@ async function loadSettings() { if (toolbarAutoHide) { toolbarAutoHide.checked = Boolean(storedToolbarAutoHide); } + if (alwaysShowOutput) { + alwaysShowOutput.checked = Boolean(storedAlwaysShowOutput); + } if (Number.isFinite(sidebarWidth)) { applySidebarWidth(sidebarWidth); } @@ -3962,6 +3967,7 @@ async function saveSettings() { ? toolbarPositionSelect.value : "bottom-right", toolbarAutoHide: toolbarAutoHide ? toolbarAutoHide.checked : true, + alwaysShowOutput: alwaysShowOutput ? alwaysShowOutput.checked : false, workspaces, sites });