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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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
15 changes: 6 additions & 9 deletions apps/desktop/src/renderer/settings/bot-chat-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -404,11 +404,11 @@ function WeChatScanLoginModal(props: {
</div>
<div className="settingsBotScanLoginActions" role="group" aria-label="微信扫码登录操作">
{(status === 'expired' || status === 'error') && (
<Button className="settingsBotAction" type="button" variant="secondary" onClick={() => void fetchQr()}>
<Button type="button" variant="secondary" onClick={() => void fetchQr()}>
刷新二维码
</Button>
)}
<Button className="settingsBotAction" type="button" variant="secondary" onClick={props.onClose}>
<Button type="button" variant="secondary" onClick={props.onClose}>
{status === 'confirmed' ? '关闭' : '取消'}
</Button>
</div>
Expand DownExpand Up@@ -1128,7 +1128,7 @@ export function BotChatSettingsPage(props: {
{selected === 'wechat' ? (
<>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1138,7 +1138,7 @@ export function BotChatSettingsPage(props: {
</Button>
{(channel.token || selectedStatus?.identity) && (
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1148,7 +1148,7 @@ export function BotChatSettingsPage(props: {
</Button>
)}
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1157,7 +1157,7 @@ export function BotChatSettingsPage(props: {
本机桥接二维码
</Button>
<Button
className="settingsBotAction"

type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1168,7 +1168,6 @@ export function BotChatSettingsPage(props: {
</>
) : support === 'runtime' && !selectedStatus?.running ? (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand All@@ -1178,7 +1177,6 @@ export function BotChatSettingsPage(props: {
</Button>
) : (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy || support === 'planned'}
Expand All@@ -1196,7 +1194,6 @@ export function BotChatSettingsPage(props: {
resolution feedback. */}
{support === 'runtime' && (selectedStatus?.running || restarting) && selected !== 'wechat' && (
<Button
className="settingsBotAction"
type="button"
variant="secondary"
disabled={botActionBusy}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,15 +142,15 @@ export function DailyReviewSettingsPage(props: { connections: readonly LlmConnec

return (
<section className="settingsFeatureStatusPage" aria-label="每日回顾">
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<strong>每日回顾</strong>
<span>
{hasConfigIpc
? '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。'
: '当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。'}
</span>
</header>
{/* Detail audit: the always-on feature banner repeated the page
subtitle — report by exception instead: only the not-wired
fallback state warrants a banner. */}
{!hasConfigIpc && (
<header className="settingsFeatureStatusBanner" role="status">
<span className="settingsFeatureStatusBannerDot" aria-hidden="true" />
<span>当前版本仅本地数字聚合,定时生成 / LLM 摘要尚未连接到后端。</span>
</header>
)}

{loadError ? (
<Alert variant="error" className="settingsSurfaceAlert">
Expand Down
11 changes: 8 additions & 3 deletions apps/desktop/src/renderer/settings/data-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,9 +202,15 @@ export function DataSettingsPage() {
value="本机 localStorage"
/>
</SettingsRows>
{/* Detail audit: was two wrapped rows with 打开文件夹 wearing primary
(a utility action) and destructive 清空输入历史 dressed neutral.
One row; utilities are secondary; the destructive action reads
destructive (red outline family, same recipe as the permission
dialog confirm). */}
<div className="settingsActionRow" role="group" aria-label="工作区数据操作">
<Button
type="button"
variant="secondary"
onClick={() => void openWorkspace()}
disabled={!info || dataActionDisabled}
>
Expand All@@ -218,11 +224,10 @@ export function DataSettingsPage() {
>
{isDataActionPending('workspace:path:copy') ? '复制中…' : '复制路径'}
</Button>
</div>
<div className="settingsActionRow" role="group" aria-label="输入历史操作">
<Button
type="button"
variant="secondary"
variant="outline"
className="border-[oklch(from_var(--destructive)_l_c_h_/_0.45)] text-[color:var(--destructive)] hover:bg-[oklch(from_var(--destructive)_l_c_h_/_0.08)]"
onClick={() => void clearInputHistory()}
disabled={dataActionDisabled}
>
Expand Down
40 changes: 19 additions & 21 deletions apps/desktop/src/renderer/settings/memory-settings-page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -646,9 +646,9 @@ export function MemorySettingsPage(props: {
{(file.status === 'available' || file.status === 'empty') && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:open`)}
onClick={() => void openWorkspaceInstructionFile(file.file)}
Expand All@@ -659,9 +659,9 @@ export function MemorySettingsPage(props: {
{file.status === 'missing' && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`创建项目指令文件 ${file.file}`}
disabled={memoryControlsDisabled || isMemoryActionPending(`instruction:${file.file}:create`)}
onClick={() => void createWorkspaceInstructionFile(file.file)}
Expand DownExpand Up@@ -720,9 +720,9 @@ export function MemorySettingsPage(props: {
<span>{backupCandidateLabel} · <RelativeTime ts={backup.updatedAt} /></span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`打开备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:open`)}
onClick={() => void openBackupCandidate(backup)}
Expand All@@ -731,9 +731,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`恢复备份候选 ${backupCandidateLabel}`}
disabled={memoryControlsDisabled || !effective.enabled || isMemoryActionPending(`backup:${backup.kind}:restore`)}
onClick={() => void restoreBackupCandidate(backup)}
Expand All@@ -742,9 +742,9 @@ export function MemorySettingsPage(props: {
</Button>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
aria-label={`复制备份候选引用 ${backupCandidateLabel}`}
disabled={isMemoryActionPending(`backup:${backup.kind}:copy`)}
onClick={() => void copyBackupReference(backup)}
Expand DownExpand Up@@ -783,9 +783,9 @@ export function MemorySettingsPage(props: {
<span>{promptPreviewWillInject ? '发送时会注入' : '当前不会注入'}</span>
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
disabled={!localMemoryPromptPreview || isMemoryActionPending('memory:prompt-preview:copy')}
onClick={() => void copyLocalMemoryPromptPreview()}
>
Expand DownExpand Up@@ -818,9 +818,8 @@ export function MemorySettingsPage(props: {
{normalizedMemoryEntryQuery ? (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => setMemoryEntryQuery('')}
>
清除
Expand DownExpand Up@@ -909,7 +908,7 @@ export function MemorySettingsPage(props: {
</div>
<Button
type="button"
variant="ghost"
variant="secondary"
disabled={memoryControlsDisabled || effective.status === 'incognito_blocked' || !effective.enabled}
onClick={addManualMemoryDraftEntry}
>
Expand DownExpand Up@@ -1052,9 +1051,9 @@ function MemoryEntryList(props: {
{props.onCopyReference && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[4rem]"
className="min-w-[4rem]"
disabled={copyPending}
onClick={() => void props.onCopyReference?.(entry)}
>
Expand All@@ -1064,9 +1063,8 @@ function MemoryEntryList(props: {
{props.onFocusDraft && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton"
onClick={() => void props.onFocusDraft?.(entry)}
>
定位草稿
Expand All@@ -1075,9 +1073,9 @@ function MemoryEntryList(props: {
{props.onStatusChange && (
<Button
type="button"
variant="quiet"
variant="outline"
size="sm"
className="settingsInlineTextButton min-w-[5rem]"
className="min-w-[5rem]"
aria-label={statusActionAriaLabel}
disabled={props.busy}
onClick={() => void props.onStatusChange?.(entry, props.archived ? 'active' : 'archived')}
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/settings/settings-nav.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -93,7 +93,7 @@ export const SETTINGS_NAV: SettingsNavItem[] = [
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
description: '每天自动分析本机对话,生成摘要、遗漏提醒和建议。模型按需消耗。' },
{ id: 'voice', label: '语音', Icon: Mic, enabled: true, group: 'AI 与集成',
description: '语音转写、麦克风权限与本地音频管线设置。' },
{ id: 'open-gateway', label: '开放网关', Icon: Network, enabled: true, group: 'AI 与集成',
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/renderer/styles/settings/bot.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,7 +216,9 @@
}
.settingsBotStatusGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
/* Detail audit: fixed 4 columns orphaned the 5th status card onto its
own row. Auto-fit keeps one balanced row and degrades gracefully. */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-2);
margin: 0;
}
Expand DownExpand Up@@ -412,6 +414,13 @@
transition: background var(--duration-base) var(--ease-out-strong);
}

/* Detail audit: bare Switch controls sat at the value column's START
(x≈mid-page) while inputs/selects hug the right rail — two alignments
in one list. Controls end-align like every other row control. */
.settingsRow > button[role="switch"] {
justify-self: end;
}

/* #520 PR9: .settingsBadge retired onto the Chip primitive variant="neutral"
(packages/ui/src/primitives/chip.tsx, size="sm"). Generic settings labels
stay squared (radius-control), not pill Badge. */
Expand Down
10 changes: 0 additions & 10 deletions apps/desktop/src/renderer/styles/settings/connection.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -210,16 +210,6 @@
align-items: center;
gap: var(--space-1-5);
}
.settingsInlineTextButton {
border: 0;
padding: 0;
background: transparent;
color: var(--link);
font: inherit;
}
.settingsInlineTextButton:hover {
text-decoration: underline;
}
.settingsConnectionActions {
display: flex;
flex-wrap: wrap;
Expand Down
11 changes: 6 additions & 5 deletions apps/desktop/src/renderer/styles/settings/memory.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -492,11 +492,12 @@
.settingsMemoryMeta {
flex-wrap: wrap;
row-gap: var(--space-1);
/* Anchor the strip: it floated unboxed between two cards and read
as orphaned fragments. A hairline + breathing room marks it as
the editor's status footnote (divider over a nested card). */
padding: var(--space-1-5) var(--space-0-5) 0;
border-top: var(--border-width-hairline) solid var(--foreground-10);
/* Detail audit round 2: the hairline alone still read as orphaned
fragments floating between two cards (user screenshot). A quiet
filled strip gives the path + status words a real container. */
padding: var(--space-1-5) var(--space-2-5);
border-radius: var(--radius-control);
background: var(--foreground-3);
}
.settingsMemoryPath {
/* The component already shortens the path for display
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/renderer/styles/settings/nav-sidebar.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -257,7 +257,7 @@
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border: var(--border-width-hairline) dashed oklch(from var(--info) l c h / 0.32);
border: var(--border-width-hairline) solid oklch(from var(--info) l c h / 0.32);
border-radius: var(--radius-surface);
background: oklch(from var(--info) l c h / 0.06);
color: var(--foreground-secondary);
Expand Down
38 changes: 10 additions & 28 deletions apps/desktop/src/renderer/styles/settings/theme-preview.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,14 +140,17 @@
display: grid;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: var(--border-width-hairline) solid oklch(from var(--success) l c h / 0.24);
/* Detail audit: this card family (关于 privacy card + 数据 import/export)
wore --success green as SECTION EMPHASIS — a non-status use that read
as residual brand-green after the blue rebrand. Brand family instead. */
border: var(--border-width-hairline) solid oklch(from var(--brand-deep) l c h / 0.22);
border-radius: var(--radius-surface);
background: oklch(from var(--success) l c h / 0.04);
background: oklch(from var(--brand-deep) l c h / 0.04);
}

.settingsAboutPrivacy h3 {
margin: 0;
color: var(--success);
color: oklch(from var(--brand-deep) calc(l - 0.12) c h);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-wider);
Expand DownExpand Up@@ -448,31 +451,10 @@
gap: var(--space-3);
margin-top: var(--space-2);
}
.settingsBotAction {
appearance: none;
min-width: 110px;
min-height: 36px;
padding: 0 var(--space-6);
border: var(--border-width-hairline) solid oklch(from var(--accent) l c h / 0.45);
border-radius: var(--radius-pill);
background: transparent;
color: var(--accent);
font-size: var(--font-size-ui);
font-weight: var(--font-weight-medium);
transition: background var(--duration-quick) var(--ease-out-strong), border-color var(--duration-quick) var(--ease-out-strong), color var(--duration-quick) var(--ease-out-strong);
}
.settingsBotAction:hover {
background: oklch(from var(--accent) l c h / 0.08);
}
.settingsBotAction:focus-visible {
outline: none;
box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.22);
}
.settingsBotAction[disabled] {
opacity: var(--opacity-disabled);
cursor: not-allowed;
}

/* Detail audit: the .settingsBotAction pill re-skin (radius-pill + raw
accent chrome smuggled through this file's governance allowlist) was
removed — the buttons render as standard UiButton secondary chips like
every other settings action. */
/* Inline hint after a field label — mirrors "(国内网络必填)" /
"(仅用于 Bot 鉴权)" in the reference. */
.settingsFieldHint {
Expand Down
Loading