Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Release: build macOS x64 Bun artifacts and add regression coverage for Homebrew formula rewrites during dual-arch releases (#122, thanks @androidshu).
- YouTube: tighten hostname validation across core, slides, and extension helpers so attacker-controlled lookalike hosts are no longer treated as YouTube URLs (#91, thanks @RinZ27).
- Config: honor `zai.baseUrl` config fallback for blank env values and keep Z.AI base URL overrides working outside the summary flow (#102, thanks @liuy).
- Chrome extension: tighten options and sidepanel UI spacing, copy actions, and advanced-controls layout for a cleaner panel experience (#86, thanks @morozRed).
- Slides: warn in summary mode when `--slides` dependencies are missing, and document required local installs for `ffmpeg`, `yt-dlp`, and optional `tesseract`.
- Docs: fix broken docs index links by setting an empty Jekyll `baseurl` (#113, thanks @Youpen-y).
- Models: preserve model id casing after the provider prefix so OpenAI-compatible proxies can route exact names correctly (#128, thanks @WinnCook).
Expand Down
30 changes: 22 additions & 8 deletions apps/chrome-extension/src/entrypoints/options/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ <h1>Summarize Settings</h1>
<span class="daemonStatus__text">Checking daemon…</span>
</div>
<div id="buildInfo" class="buildInfo"></div>
<span id="status" class="status" aria-live="polite"></span>
</div>
</div>
<form id="form">
Expand Down Expand Up @@ -123,7 +124,9 @@ <h1>Summarize Settings</h1>
<button id="automationPermissions" type="button" class="miniButton">
Enable automation permissions
</button>
<span class="subtitle">Grant optional permissions (userScripts).</span>
<span class="subtitle permissionHint">
Opens Chrome permission prompt for optional <code>userScripts</code>.
</span>
</div>
<div id="userScriptsNotice" class="notice" hidden></div>
</section>
Expand All @@ -134,7 +137,22 @@ <h2>Token setup</h2>
<span>Token</span>
<div class="inputRow">
<input id="token" type="text" placeholder="(generated in side panel)" />
<button id="tokenCopy" type="button" class="miniButton copyButton">Copy</button>
<button
id="tokenCopy"
type="button"
class="iconButton inputCopyButton"
aria-label="Copy token"
title="Copy token"
>
<svg class="copyIcon" viewBox="0 0 16 16" aria-hidden="true">
<path
d="M5.5 3.5A2.5 2.5 0 0 1 8 1h4a2.5 2.5 0 0 1 2.5 2.5v6A2.5 2.5 0 0 1 12 12h-4A2.5 2.5 0 0 1 5.5 9.5v-6Z"
/>
<path
d="M1.5 6A2.5 2.5 0 0 1 4 3.5h1a.75.75 0 0 1 0 1.5H4A1 1 0 0 0 3 6v6a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1a.75.75 0 0 1 1.5 0v1A2.5 2.5 0 0 1 8 14H4a2.5 2.5 0 0 1-2.5-2.5V6Z"
/>
</svg>
</button>
</div>
</label>
</section>
Expand Down Expand Up @@ -514,11 +532,11 @@ <h2>Process Manager</h2>
<button
id="processesLogsCopy"
type="button"
class="miniButton processLogsCopy"
class="iconButton processLogsCopy"
aria-label="Copy logs"
title="Copy logs"
>
<svg viewBox="0 0 16 16" aria-hidden="true">
<svg class="copyIcon" viewBox="0 0 16 16" aria-hidden="true">
<path
d="M5.5 3.5A2.5 2.5 0 0 1 8 1h4a2.5 2.5 0 0 1 2.5 2.5v6A2.5 2.5 0 0 1 12 12h-4A2.5 2.5 0 0 1 5.5 9.5v-6Z"
/>
Expand Down Expand Up @@ -609,10 +627,6 @@ <h2>Logs</h2>
</div>
</section>
</div>

<div class="buttons">
<span id="status" class="status"></span>
</div>
</form>
<div class="pageFooter hint">
<a href="https://summarize.sh" target="_blank" rel="noopener noreferrer">Summarize</a> made
Expand Down
31 changes: 23 additions & 8 deletions apps/chrome-extension/src/entrypoints/options/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -752,15 +752,20 @@ form {
}

.processLogsCopy {
padding: 0;
width: 26px;
height: 26px;
border-radius: 8px;
}

.iconButton {
padding: 0;
width: 24px;
height: 24px;
border-radius: 9px;
display: grid;
place-items: center;
}

.processLogsCopy svg {
.copyIcon {
width: 14px;
height: 14px;
fill: currentColor;
Expand Down Expand Up @@ -841,8 +846,7 @@ form {
}

#automationPermissions.miniButton {
padding-top: 1px;
padding-bottom: 3px;
padding: 6px 14px;
line-height: 1.1;
}

Expand Down Expand Up @@ -1024,14 +1028,20 @@ label {
align-items: center;
gap: 8px;
min-width: 0;
position: relative;
}

.inputRow input {
flex: 1;
flex: 1 1 0%;
min-width: 0;
padding-right: 46px;
}

.copyButton {
white-space: nowrap;
.inputCopyButton {
position: absolute;
right: 6px;
top: 50%;
transform: translateY(-50%);
}

label > span {
Expand All @@ -1045,6 +1055,11 @@ label > span {
line-height: 1.3;
}

.permissionHint code {
font-family: var(--mono);
font-size: 10px;
}

.hint {
color: var(--muted);
font-size: 12px;
Expand Down
18 changes: 10 additions & 8 deletions apps/chrome-extension/src/entrypoints/sidepanel/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,17 @@
</select>
</label>
<div class="drawerAdvancedRow">
<div id="autoToggle" class="toggleRow"></div>
<div class="drawerActions drawerAdvancedActions">
<button id="refresh" type="button" class="ghost" title="Refresh (Shift+Enter)">
Refresh
</button>
<button id="clear" type="button" class="ghost" title="Clear summary + chat">
Clear
</button>
<button id="advanced" type="button" class="ghost">Advanced…</button>
<div id="autoToggle" class="toggleRow"></div>
<div class="drawerAdvancedButtons">
<button id="refresh" type="button" class="ghost" title="Refresh (Shift+Enter)">
Refresh
</button>
<button id="clear" type="button" class="ghost" title="Clear summary + chat">
Clear
</button>
<button id="advanced" type="button" class="ghost">Advanced</button>
</div>
</div>
</div>
</div>
Expand Down
87 changes: 87 additions & 0 deletions apps/chrome-extension/src/entrypoints/sidepanel/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ const sizeLgBtn = byId<HTMLButtonElement>("sizeLg");
const lineTightBtn = byId<HTMLButtonElement>("lineTight");
const lineLooseBtn = byId<HTMLButtonElement>("lineLoose");
const advancedSettingsEl = byId<HTMLDetailsElement>("advancedSettings");
const advancedSettingsSummaryEl = advancedSettingsEl.querySelector("summary");
if (!advancedSettingsSummaryEl) throw new Error("Missing advanced settings summary");
const advancedSettingsBodyEl = advancedSettingsEl.querySelector<HTMLElement>(".drawerAdvancedBody");
if (!advancedSettingsBodyEl) throw new Error("Missing advanced settings body");
const modelPresetEl = byId<HTMLSelectElement>("modelPreset");
const modelCustomEl = byId<HTMLInputElement>("modelCustom");
const modelRefreshBtn = byId<HTMLButtonElement>("modelRefresh");
Expand Down Expand Up @@ -247,6 +251,7 @@ const panelState: PanelState = {
chatStreaming: false,
};
let drawerAnimation: Animation | null = null;
let advancedSettingsAnimation: Animation | null = null;
let autoValue = false;
let chatEnabledValue = defaultSettings.chatEnabled;
let automationEnabledValue = defaultSettings.automationEnabled;
Expand Down Expand Up @@ -3986,6 +3991,83 @@ function toggleDrawer(force?: boolean, opts?: { animate?: boolean }) {
};
}

function toggleAdvancedSettings(force?: boolean, opts?: { animate?: boolean }) {
const reducedMotion = window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches ?? false;
const animate = opts?.animate !== false && !reducedMotion;
const isOpen = advancedSettingsEl.open;
const next = typeof force === "boolean" ? force : !isOpen;

if (next === isOpen) {
if (next) refreshModelsIfStale();
return;
}

const cleanup = () => {
advancedSettingsBodyEl.style.removeProperty("height");
advancedSettingsBodyEl.style.removeProperty("opacity");
advancedSettingsBodyEl.style.removeProperty("transform");
advancedSettingsBodyEl.style.removeProperty("overflow");
};

advancedSettingsAnimation?.cancel();
advancedSettingsAnimation = null;
cleanup();

if (!animate) {
advancedSettingsEl.open = next;
if (next) refreshModelsIfStale();
return;
}

if (next) {
advancedSettingsBodyEl.style.height = "0px";
advancedSettingsBodyEl.style.opacity = "0";
advancedSettingsBodyEl.style.transform = "translateY(-6px)";
advancedSettingsBodyEl.style.overflow = "hidden";
advancedSettingsEl.open = true;

const targetHeight = advancedSettingsBodyEl.scrollHeight;
advancedSettingsAnimation = advancedSettingsBodyEl.animate(
[
{ height: "0px", opacity: 0, transform: "translateY(-6px)" },
{ height: `${targetHeight}px`, opacity: 1, transform: "translateY(0px)" },
],
{ duration: 200, easing: "cubic-bezier(0.2, 0, 0, 1)", fill: "both" },
);
advancedSettingsAnimation.onfinish = () => {
advancedSettingsAnimation = null;
cleanup();
refreshModelsIfStale();
};
advancedSettingsAnimation.oncancel = () => {
advancedSettingsAnimation = null;
};
return;
}

const currentHeight = advancedSettingsBodyEl.getBoundingClientRect().height;
advancedSettingsBodyEl.style.height = `${currentHeight}px`;
advancedSettingsBodyEl.style.opacity = "1";
advancedSettingsBodyEl.style.transform = "translateY(0px)";
advancedSettingsBodyEl.style.overflow = "hidden";

advancedSettingsAnimation = advancedSettingsBodyEl.animate(
[
{ height: `${currentHeight}px`, opacity: 1, transform: "translateY(0px)" },
{ height: "0px", opacity: 0, transform: "translateY(-6px)" },
],
{ duration: 180, easing: "cubic-bezier(0.4, 0, 0.2, 1)", fill: "both" },
);
advancedSettingsAnimation.onfinish = () => {
advancedSettingsAnimation = null;
advancedSettingsEl.open = false;
cleanup();
};
advancedSettingsAnimation.oncancel = () => {
advancedSettingsAnimation = null;
};
}

function resetChatState() {
panelState.chatStreaming = false;
chatController.reset();
Expand Down Expand Up @@ -4167,6 +4249,10 @@ drawerToggleBtn.addEventListener("click", () => toggleDrawer());
advancedBtn.addEventListener("click", () => {
void send({ type: "panel:openOptions" });
});
advancedSettingsSummaryEl.addEventListener("click", (event) => {
event.preventDefault();
toggleAdvancedSettings();
});

chatSendBtn.addEventListener("click", sendChatMessage);
chatInputEl.addEventListener("keydown", (e) => {
Expand Down Expand Up @@ -4241,6 +4327,7 @@ modelPresetEl.addEventListener("pointerdown", refreshModelsIfStale);
modelCustomEl.addEventListener("focus", refreshModelsIfStale);
modelCustomEl.addEventListener("pointerdown", refreshModelsIfStale);
advancedSettingsEl.addEventListener("toggle", () => {
if (advancedSettingsAnimation) return;
if (advancedSettingsEl.open) refreshModelsIfStale();
});
modelRefreshBtn.addEventListener("click", () => {
Expand Down
48 changes: 31 additions & 17 deletions apps/chrome-extension/src/entrypoints/sidepanel/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ header {

.headerRow {
display: flex;
align-items: flex-start;
align-items: center;
justify-content: space-between;
gap: 10px;
}
Expand Down Expand Up @@ -525,6 +525,10 @@ header {
text-overflow: ellipsis;
}

.subtitle:empty {
display: none;
}

.controls {
display: flex;
gap: 8px;
Expand Down Expand Up @@ -976,49 +980,59 @@ button.ghost.small {
transform: rotate(225deg);
}

details.drawerAdvanced:not([open]) > .drawerAdvancedBody {
display: grid;
}

.drawerAdvancedBody {
display: grid;
gap: 8px;
margin-top: 0;
max-height: 0;
margin-top: 10px;
opacity: 0;
overflow: hidden;
pointer-events: none;
transform: translateY(-4px);
transition:
max-height 220ms ease,
opacity 180ms ease,
transform 220ms ease,
margin-top 220ms ease;
will-change: max-height, opacity, transform;
transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
will-change: opacity, transform;
}

.drawerAdvanced[open] .drawerAdvancedBody {
margin-top: 10px;
max-height: 600px;
opacity: 1;
pointer-events: auto;
transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
.drawerAdvanced summary::after,
.drawerAdvancedBody {
transition: none;
}
}

.drawerAdvancedRow {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 10px;
min-width: 0;
}

.drawerAdvancedRow .toggleRow {
flex: 1;
min-width: 160px;
flex: 1 1 160px;
min-width: 0;
}

.drawerAdvancedActions {
justify-content: flex-end;
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
column-gap: 10px;
width: 100%;
min-width: 0;
}

.drawerAdvancedButtons {
display: flex;
flex-wrap: nowrap;
justify-content: flex-end;
gap: 8px;
}

.drawerAdvanced .modelRow {
Expand Down