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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down
, '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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down
, '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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down
, '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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down
, '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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down
, '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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down
, '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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down
, '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
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,11 @@ describe('Settings coming-soon cleanup contract', () => {
const styles = await readRepo('apps/desktop/src/renderer/styles.css');
const providerCatalog = await readRepo('packages/core/src/llm-connections.ts');
assert.doesNotMatch(settings, /comingSoon\??:/, 'Settings nav items must not carry stale comingSoon flags');
assert.doesNotMatch(settings, /settingsNavBadge/, 'Settings nav must not render stale Roadmap badges');
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): `settingsNavBadge`
// is now legitimately reused as a Beta chip on shipping features.
// The earlier blanket ban on the class name is dropped; the other
// copy-level assertions in this block (e.g. command palette `即将推出`
// ban below) still guard the original intent.
assert.doesNotMatch(palette, /即将推出/, 'Command palette settings entries must not advertise dead coming-soon hints');
assert.doesNotMatch(palette, /comingSoon/, 'Command palette must not read removed nav comingSoon flags');
assert.doesNotMatch(providers, /即将支持的 OAuth 订阅登录/, 'Providers header must not advertise future OAuth login as a model-provider affordance');
Expand All@@ -37,6 +41,9 @@ describe('Settings coming-soon cleanup contract', () => {
assert.doesNotMatch(providers, /还没有供应商/, 'ProvidersPanel empty state should not read like unfinished product setup');
assert.doesNotMatch(providerCatalog, /catalogBadge:\s*'Soon'|future phase/, 'provider catalog metadata must not keep soon/future-phase copy');
assert.doesNotMatch(styles, /ComingSoonPage|roadmap banner|providerComingSoon|providerCatalogSoon/, 'Settings CSS must not keep stale coming-soon/provider-roadmap naming');
// PR-SETTINGS-NAV-REGROUP-0: `.settingsNavBadge` is reused as the Beta
// chip primitive. Lock it down so we don't lose it accidentally.
assert.match(styles, /\.settingsNavBadge\s*\{/);
});

it('keeps feature status pages product-scoped instead of demo-version or future-roadmap copy', async () => {
Expand Down
52 changes: 33 additions & 19 deletions apps/desktop/src/renderer/settings/SettingsModal.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -137,6 +137,12 @@ type SettingsNavItem = {
* label. Helps the user understand "where am I?" at the page top.
*/
description?: string;
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): render a small
* "Beta" chip next to the nav label. Reference uses this for the
* 应用快照 / 工作台 items.
*/
badge?: 'Beta';
};

type AccountSecretProbeStatus = boolean | 'loading' | 'error';
Expand DownExpand Up@@ -211,37 +217,40 @@ export type { SettingsNavGroup };
// PR-SETTINGS-IA-CONSOLIDATE-0 + PR-SETTINGS-REVIEW-0: WAWQAQ msg
// `886f6406` rolled back the 记忆+回顾 merge — the combined page was
// too dense. 记忆 and 每日回顾 are separate nav items again.
// PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
// → 3 wider groups. 基础→通用, AI+集成→「AI 与集成」, 数据+其他→系统.
// Mirrors reference's tighter grouping (1 big group + a couple small
// ones) instead of 5 categories with only 1-3 items each.
export const SETTINGS_NAV: SettingsNavItem[] = [
// Group 1: 基础 — 通用 (kitchen sink) + 外观 (personalization + theme merged)
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '基础',
// Group 1: 通用
{ id: 'general', label: '通用', Icon: SettingsIcon, enabled: true, group: '通用',
description: '隐身、启动、对话默认与网络代理等系统偏好。' },
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '基础',
{ id: 'appearance', label: '外观', Icon: Palette, enabled: true, group: '通用',
description: '主题、配色、字体面板与个性化身份。' },
// Group 2: AI — models, usage, memory, daily-review, voice+gateway
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI',
// Group 2: AI 与集成 — models, usage, memory, daily-review, voice+gateway, bots, search
{ id: 'models', label: '模型', Icon: Cpu, enabled: true, group: 'AI 与集成',
description: '模型连接、API key 与 OAuth 订阅管理。' },
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI',
{ id: 'usage', label: '使用统计', Icon: BarChart3, enabled: true, group: 'AI 与集成',
description: 'token、模型、工具使用走势与配额追踪。' },
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI',
{ id: 'memory', label: '记忆', Icon: Brain, enabled: true, group: 'AI 与集成',
description: '本地 MEMORY.md、项目指令文件与上下文注入开关。' },
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI',
{ id: 'daily-review', label: '每日回顾', Icon: CalendarDays, enabled: true, group: 'AI 与集成',
description: '当天对话、模型与工具用量汇总。' },
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI',
{ id: 'voice-gateway', label: '语音与网关', Icon: Volume2, enabled: true, group: 'AI 与集成',
description: '语音转写与 Maka 开放网关 SSE 接入。' },
// Group 3: 集成 — bot、搜索 (network/proxy now lives inside 通用)
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: '集成',
{ id: 'bot-chat', label: '机器人对话', Icon: Bot, enabled: true, group: 'AI 与集成',
description: 'Telegram / 飞书 / 企业微信等机器人凭据与运行状态。' },
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: '集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。' },
// Group 4: 数据
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '数据',
{ id: 'search', label: '联网搜索', Icon: Search, enabled: true, group: 'AI 与集成',
description: '联网搜索供应商(如 Tavily)凭据与隐私边界。',
badge: 'Beta' },
// Group 3: 系统 — data, permissions, health, about
{ id: 'data', label: '数据', Icon: Database, enabled: true, group: '系统',
description: '本地工作区路径、备份与恢复。' },
// Group 5: 其他
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '其他',
{ id: 'permissions', label: '权限与能力', Icon: ShieldCheck, enabled: true, group: '系统',
description: '系统权限授予状态与 Maka 能力运行时检查。' },
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '其他',
{ id: 'health', label: '健康', Icon: Activity, enabled: true, group: '系统',
description: '运行时连接、模型探针与本地健康状态。' },
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '其他',
{ id: 'about', label: '关于', Icon: Info, enabled: true, group: '系统',
description: '版本、运行环境与隐私承诺。' },
];

Expand DownExpand Up@@ -1002,6 +1011,11 @@ function SettingsSurface(props: {
<item.Icon size={16} strokeWidth={1.5} />
</span>
<strong>{item.label}</strong>
{item.badge && (
<span className="settingsNavBadge" data-badge={item.badge}>
{item.badge}
</span>
)}
</Button>
))}
</div>
Expand Down
26 changes: 17 additions & 9 deletions apps/desktop/src/renderer/settings/nav-group-summary.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,13 +16,20 @@

import type { AppSettings, LlmConnection } from '@maka/core';

export type SettingsNavGroup = '基础' | 'AI' | '集成' | '数据' | '其他';
/**
* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): 5 narrow groups
* collapsed to 3. `基础` → `通用`, `AI` + `集成` → `AI 与集成`,
* `数据` + `其他` → `系统`. Mirrors reference's tighter nav grouping
* (通用 / 扩展与集成 / 高级设置) where one big group carries most
* items instead of 5 tiny ones.
*/
export type SettingsNavGroup = '通用' | 'AI 与集成' | '系统';

/**
* The render order used by the Settings modal sidebar. Lives here so the
* nav-group enum and its presentation order stay in one place.
*/
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['基础', 'AI', '集成', '数据', '其他'];
export const NAV_GROUP_ORDER: SettingsNavGroup[] = ['通用', 'AI 与集成', '系统'];

export interface NavGroupSummary {
/** Short text rendered next to the group label, e.g. "3 verified · 1 needs reauth". */
Expand All@@ -49,13 +56,14 @@ export interface NavGroupSummaryInput {
*/
export function deriveNavGroupSummary(input: NavGroupSummaryInput): NavGroupSummary | undefined {
switch (input.group) {
case 'AI':
return summarizeAi(input.connections, input.defaultSlug);
case '集成':
return summarizeIntegrations(input.connections, input.settings);
case '数据':
case '基础':
case '其他':
case 'AI 与集成':
// PR-SETTINGS-NAV-REGROUP-0: AI and 集成 groups merged. Prefer
// showing the highest-urgency message — AI connection errors
// outrank proxy/bot status.
return summarizeAi(input.connections, input.defaultSlug)
?? summarizeIntegrations(input.connections, input.settings);
case '通用':
case '系统':
return undefined;
}
}
Expand Down
23 changes: 20 additions & 3 deletions apps/desktop/src/renderer/styles.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -6997,13 +6997,12 @@ button:active {

.settingsNavItem {
/* PR-SETTINGS-SIDEBAR-SPACIOUS-0: roomier nav row matching reference.
Height 32→38, icon column 20→24, label gap 8→12, side padding
8→12, label font 13→14. */
PR-SETTINGS-NAV-REGROUP-0: 3rd grid column for optional Beta badge. */
width: calc(100% - 8px);
height: 38px;
min-height: 38px;
display: grid;
grid-template-columns: 24px minmax(0, 1fr);
grid-template-columns: 24px minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
border: 0;
Expand All@@ -7019,6 +7018,24 @@ button:active {
transition: background-color 150ms var(--ease-out-strong), color 150ms var(--ease-out-strong);
}

/* PR-SETTINGS-NAV-REGROUP-0 (WAWQAQ msg `a9ef0d5d`): small chip on nav
items that are still in beta — matches reference's pattern of
surfacing maturity inline rather than relegating to a separate
release notes view. */
.settingsNavBadge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 4px;
background: oklch(from var(--accent) l c h / 0.12);
color: var(--accent);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: none;
}

.settingsSidebar .settingsNavItem,
.settingsSidebar .settingsNavItem[data-active="true"],
.settingsSidebar .settingsNavItem:hover {
Expand Down