更新登录

This commit is contained in:
2026-05-05 20:44:24 +08:00
parent bf134dec86
commit eba6478913
20 changed files with 389 additions and 412 deletions
+1
View File
@@ -0,0 +1 @@
{"sessionId":"15770f56-9fb8-4d72-9afd-c60f20801589","pid":36832,"acquiredAt":1777979563514}
+9
View File
@@ -0,0 +1,9 @@
{
"permissions": {
"allow": [
"PowerShell($tmp = Join-Path $env:TEMP 'rustup-init.exe'; Invoke-WebRequest -Uri 'https://win.rustup.rs/x86_64' -OutFile $tmp -UseBasicParsing; & $tmp -y --default-toolchain stable --default-host x86_64-pc-windows-msvc --profile minimal; Write-Output \"rustup exit: $LASTEXITCODE\")",
"PowerShell($env:Path = \"$env:USERPROFILE\\\\.cargo\\\\bin;$env:USERPROFILE\\\\.bun\\\\bin;$env:Path\"; $env:SKIP_INSTALL = '1'; $env:TEMP = 'C:\\\\BunTemp'; $env:TMP = 'C:\\\\BunTemp'; Set-Location 'C:\\\\Users\\\\陈晨\\\\Desktop\\\\工单相关\\\\heicode\\\\cc-haha\\\\desktop'; bun run build:windows-x64)",
"PowerShell(Get-PSDrive -PSProvider FileSystem | Format-Table -AutoSize; Write-Output '---'; @\\('C:\\\\bun-ascii','D:\\\\','C:\\\\ProgramData','C:\\\\Tools'\\) | ForEach-Object { try { $tp = Join-Path $_ 'tmp_probe.txt'; $null = New-Item -ItemType File -Force -Path $tp -ErrorAction Stop; Remove-Item $tp -Force; Write-Output \"WRITE OK: $_\" } catch { Write-Output \"WRITE FAIL: $_ -> $\\($_.Exception.Message.Split\\([Environment]::NewLine\\)[0]\\)\" } })"
]
}
}
+2 -2
View File
@@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Claude Code Companion</title>
<title>Heicode</title>
<!-- Fonts are self-hosted in /fonts/ and declared via @font-face in globals.css -->
<style>
/* Prevent white flash on load */
html { background: #FAF9F5; }
html { background: #0A0A0C; }
</style>
</head>
<body>
@@ -113,10 +113,10 @@ function Get-StagedArtifactName {
switch -Regex ($ArtifactName) {
'^latest\.json$' { return 'latest.json' }
'\.msi\.zip\.sig$' { return "Claude-Code-Haha_${appVersion}_windows_x64_msi.msi.zip.sig" }
'\.msi\.zip$' { return "Claude-Code-Haha_${appVersion}_windows_x64_msi.msi.zip" }
'\.msi\.sig$' { return "Claude-Code-Haha_${appVersion}_windows_x64_msi.msi.sig" }
'\.msi$' { return "Claude-Code-Haha_${appVersion}_windows_x64_msi.msi" }
'\.msi\.zip\.sig$' { return "Heicode_${appVersion}_windows_x64_msi.msi.zip.sig" }
'\.msi\.zip$' { return "Heicode_${appVersion}_windows_x64_msi.msi.zip" }
'\.msi\.sig$' { return "Heicode_${appVersion}_windows_x64_msi.msi.sig" }
'\.msi$' { return "Heicode_${appVersion}_windows_x64_msi.msi" }
default { return $ArtifactName }
}
}
@@ -61,15 +61,15 @@ function buildProviderChoices(
providerModelsMap: Record<string, ModelInfo[]>,
labels: Record<'main' | 'haiku' | 'sonnet' | 'opus', string>,
): ProviderChoice[] {
return providers.map((provider) => ({
providerId: provider.id,
providerName: provider.name,
isDefault: activeId === provider.id,
models:
providerModelsMap[provider.id]?.length > 0
? providerModelsMap[provider.id]
: buildProviderModels(provider, labels),
}))
return providers.map((provider) => {
const cached = providerModelsMap[provider.id]
return {
providerId: provider.id,
providerName: provider.name,
isDefault: activeId === provider.id,
models: cached && cached.length > 0 ? cached : buildProviderModels(provider, labels),
}
})
}
function resolveDefaultRuntimeSelection(
@@ -15,7 +15,7 @@ export function TitleBar() {
{/* Logo */}
<div className="flex items-center gap-2 mr-4" data-tauri-drag-region>
<span className="text-xs font-bold tracking-wider text-[var(--color-brand)] uppercase">Claude Code Companion</span>
<span className="text-xs font-bold tracking-[0.18em] text-[var(--color-brand)] uppercase">Heicode</span>
</div>
{/* Navigation arrows */}
@@ -1,7 +1,7 @@
// desktop/src/components/login/HeicodeLoginPage.tsx
//
// 全屏登录页 — 当 HeiCode 检测到尚未登录时由 AppShell 渲染。
// 仅 2 个登录入口:TaijiAICloud / ClawdRouter,没有第三选项。
// 全屏登录页 — 当 Heicode 检测到尚未登录时由 AppShell 渲染。
// 仅 1 个登录入口:TaijiAICloud。
import { useEffect } from 'react'
import { useHeicodeAuthStore } from '../../stores/heicodeAuthStore'
@@ -33,11 +33,11 @@ export function HeicodeLoginPage() {
className="flex h-screen w-screen flex-col items-center justify-center overflow-auto bg-[var(--color-surface)] px-6 py-10"
data-testid="heicode-login-page"
>
<div className="mb-8 text-center">
<h1 className="text-3xl font-semibold text-[var(--color-text-primary)]">
HeiCode
<div className="mb-10 text-center">
<h1 className="text-4xl font-bold tracking-[0.18em] uppercase text-[var(--color-brand)]">
Heicode
</h1>
<p className="mt-2 text-sm text-[var(--color-text-secondary)]">
<p className="mt-3 text-sm text-[var(--color-text-secondary)]">
{t('login.subtitle')}
</p>
</div>
@@ -55,7 +55,7 @@ export function HeicodeLoginPage() {
) : null}
{hasFetched && providers.length > 0 ? (
<div className="grid w-full max-w-4xl grid-cols-1 gap-6 md:grid-cols-2">
<div className="grid w-full max-w-md grid-cols-1 gap-6">
{providers.map((provider) => (
<ProviderLoginCard
key={provider.id}
+2 -2
View File
@@ -956,8 +956,8 @@ export const en = {
'serverVerb.Task in progress': 'Task in progress',
// ─── HeiCode Login ──────────────────────────────────────
'login.subtitle': 'Choose how to sign in to start using HeiCode',
'login.footnote': 'HeiCode talks directly to TaijiAICloud or ClawdRouter; your API key never leaves this machine.',
'login.subtitle': 'Sign in to start using Heicode',
'login.footnote': 'Heicode talks directly to TaijiAICloud; your API key never leaves this machine.',
'login.tags.recommended': 'Recommended',
'login.tags.comingSoon': 'Coming soon',
'login.oauth.button': 'Sign in with browser',
+2 -2
View File
@@ -958,8 +958,8 @@ export const zh: Record<TranslationKey, string> = {
'serverVerb.Task in progress': '任务进行中',
// ─── HeiCode 登录 ──────────────────────────────────────
'login.subtitle': '选择登录方式以开始使用 HeiCode',
'login.footnote': 'HeiCode 直接连 TaijiAICloud 或 ClawdRouter,API Key 仅保存在你这台机器上。',
'login.subtitle': '登录以开始使用 Heicode',
'login.footnote': 'Heicode 直接连 TaijiAICloud,API Key 仅保存在你这台机器上。',
'login.tags.recommended': '推荐',
'login.tags.comingSoon': '即将开放',
'login.oauth.button': '浏览器登录',
+1 -1
View File
@@ -141,7 +141,7 @@ export function ActiveSession() {
</>
) : (
<>
<img src="/app-icon.png" alt="Claude Code Haha" className="mb-6 h-24 w-24" />
<img src="/app-icon.png" alt="Heicode" className="mb-6 h-24 w-24" />
<h1 className="mb-2 text-3xl font-extrabold tracking-tight text-[var(--color-text-primary)]" style={{ fontFamily: 'var(--font-headline)' }}>
{t('empty.title')}
</h1>
+1 -1
View File
@@ -460,7 +460,7 @@ export function EmptySession() {
<div className="relative flex flex-1 flex-col overflow-hidden bg-[var(--color-surface)]">
<div className="flex flex-1 flex-col items-center justify-center p-8 pb-32">
<div className="flex max-w-md flex-col items-center text-center">
<img src="/app-icon.png" alt="Claude Code Haha" className="mb-6 h-24 w-24" />
<img src="/app-icon.png" alt="Heicode" className="mb-6 h-24 w-24" />
<h1 className="mb-2 text-3xl font-extrabold tracking-tight text-[var(--color-text-primary)]" style={{ fontFamily: 'var(--font-headline)' }}>
{t('empty.title')}
</h1>
+20 -20
View File
@@ -22,23 +22,23 @@ export default function NewTaskModal() {
return (
<div className="bg-[var(--color-background)] text-[var(--color-on-surface)] font-[var(--font-body)] min-h-screen flex flex-col">
{/* ─── TopAppBar / Header ──────────────────────────────────── */}
<header className="bg-[#FAF9F5] flex justify-between items-center px-6 h-12 w-full z-40">
<header className="bg-[var(--color-surface)] flex justify-between items-center px-6 h-12 w-full z-40">
<div className="flex items-center gap-6">
<span className="text-sm font-bold text-[#1B1C1A] uppercase tracking-tighter font-[var(--font-headline)]">
Claude Code Companion
<span className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter font-[var(--font-headline)]">
Heicode
</span>
<nav className="hidden md:flex gap-4 font-[var(--font-headline)] font-semibold tracking-wide text-sm">
<a className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer">Code</a>
<a className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer">Terminal</a>
<a className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer">History</a>
<a className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer">Code</a>
<a className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer">Terminal</a>
<a className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer">History</a>
</nav>
</div>
<div className="flex items-center gap-4">
<div className="flex items-center gap-2 text-[#8F482F]">
<div className="flex items-center gap-2 text-[var(--color-brand)]">
<span className="material-symbols-outlined cursor-pointer active:opacity-70 text-sm">arrow_back_ios</span>
<span className="material-symbols-outlined cursor-pointer active:opacity-70 text-sm">arrow_forward_ios</span>
</div>
<span className="font-[var(--font-headline)] font-semibold tracking-wide text-sm text-[#87736D] cursor-pointer hover:text-[#8F482F] transition-colors">
<span className="font-[var(--font-headline)] font-semibold tracking-wide text-sm text-[var(--color-text-secondary)] cursor-pointer hover:text-[var(--color-brand)] transition-colors">
Settings
</span>
</div>
@@ -64,22 +64,22 @@ export default function NewTaskModal() {
{/* nav items -- session counts derived from mockSessions */}
<div className="font-[var(--font-body)] text-sm font-medium space-y-1">
<div className="flex items-center gap-3 px-3 py-2 text-[#87736D]">
<div className="flex items-center gap-3 px-3 py-2 text-[var(--color-text-secondary)]">
<span className="material-symbols-outlined">add</span>New session
</div>
<div className="flex items-center gap-3 px-3 py-2 bg-[#FAF9F5] text-[#1B1C1A] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[#8F482F] before:rounded-full">
<div className="flex items-center gap-3 px-3 py-2 bg-[var(--color-surface)] text-[var(--color-text-primary)] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[var(--color-brand)] before:rounded-full">
<span className="material-symbols-outlined">calendar_today</span>Scheduled
</div>
<div className="flex items-center gap-3 px-3 py-2 text-[#87736D]">
<div className="flex items-center gap-3 px-3 py-2 text-[var(--color-text-secondary)]">
<span className="material-symbols-outlined">history</span>Today
{mockSessions.today.length > 0 && (
<span className="ml-auto text-[10px] text-[#87736D]">{mockSessions.today.length}</span>
<span className="ml-auto text-[10px] text-[var(--color-text-secondary)]">{mockSessions.today.length}</span>
)}
</div>
<div className="flex items-center gap-3 px-3 py-2 text-[#87736D]">
<div className="flex items-center gap-3 px-3 py-2 text-[var(--color-text-secondary)]">
<span className="material-symbols-outlined">event_note</span>Previous 7 Days
{mockSessions.previous7Days.length > 0 && (
<span className="ml-auto text-[10px] text-[#87736D]">{mockSessions.previous7Days.length}</span>
<span className="ml-auto text-[10px] text-[var(--color-text-secondary)]">{mockSessions.previous7Days.length}</span>
)}
</div>
</div>
@@ -317,25 +317,25 @@ export default function NewTaskModal() {
</main>
{/* ─── Footer / Status Bar ─────────────────────────────────── */}
<footer className="bg-[#FAF9F5] flex items-center justify-between px-4 z-50 fixed bottom-0 left-0 w-full h-8 border-t border-[#87736D]/20 font-[var(--font-body)] text-xs tracking-tight">
<footer className="bg-[var(--color-surface)] flex items-center justify-between px-4 z-50 fixed bottom-0 left-0 w-full h-8 border-t border-[var(--color-text-secondary)]/20 font-[var(--font-body)] text-xs tracking-tight">
<div className="flex items-center gap-3">
<span className="text-[#87736D]">
<span className="text-[var(--color-text-secondary)]">
{mockStatusBar.user} &bull; {mockStatusBar.username} &bull; {mockStatusBar.plan}
</span>
<div className="flex items-center gap-4 ml-4">
<span className="text-[#87736D] hover:bg-[#F4F4F0] px-2 py-0.5 rounded cursor-pointer transition-colors">
<span className="text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] px-2 py-0.5 rounded cursor-pointer transition-colors">
{mockStatusBar.branch}
</span>
<span className="text-[#87736D] hover:bg-[#F4F4F0] px-2 py-0.5 rounded cursor-pointer transition-colors">
<span className="text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] px-2 py-0.5 rounded cursor-pointer transition-colors">
{mockStatusBar.worktreeToggle}
</span>
</div>
</div>
<div className="flex items-center gap-4">
<span className="text-[#8F482F] font-bold cursor-pointer">
<span className="text-[var(--color-brand)] font-bold cursor-pointer">
{mockStatusBar.localSwitch}
</span>
<div className="flex items-center gap-1 text-[#87736D]">
<div className="flex items-center gap-1 text-[var(--color-text-secondary)]">
<span className="material-symbols-outlined text-[14px]">terminal</span>
<span>{mockStatusBar.status === 'Ready' ? 'Active' : mockStatusBar.status}</span>
</div>
@@ -4,50 +4,50 @@ import { mockStatusBar } from '../mocks/data'
export function ScheduledTasksEmpty() {
const t = useTranslation()
return (
<div className="bg-[#FAF9F5] text-[#1B1C1A] flex min-h-screen font-[Inter,sans-serif]">
<div className="bg-[var(--color-surface)] text-[var(--color-text-primary)] flex min-h-screen font-[Inter,sans-serif]">
{/* SideNavBar */}
<aside className="fixed left-0 top-0 h-full w-[280px] bg-[#F4F4F0] flex flex-col p-4 gap-2 text-sm font-medium z-40">
<div className="flex items-center gap-3 px-2 mb-6 mt-12">
<div className="w-8 h-8 rounded bg-[#E3E2DF] flex items-center justify-center">
<span className="material-symbols-outlined text-[#87736D]">filter_list</span>
<span className="material-symbols-outlined text-[var(--color-text-secondary)]">filter_list</span>
</div>
<div>
<div className="text-[#1B1C1A] font-bold">{t('sidebar.allProjects')}</div>
<div className="text-[10px] text-[#87736D] uppercase tracking-widest">{t('scheduledPage.activeSession')}</div>
<div className="text-[var(--color-text-primary)] font-bold">{t('sidebar.allProjects')}</div>
<div className="text-[10px] text-[var(--color-text-secondary)] uppercase tracking-widest">{t('scheduledPage.activeSession')}</div>
</div>
</div>
<nav className="flex-1 space-y-1">
<div className="px-3 py-2 text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<div className="px-3 py-2 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">add</span>
<span>{t('sidebar.newSession')}</span>
</div>
{/* Active State: Scheduled */}
<div className="px-3 py-2 bg-[#FAF9F5] text-[#1B1C1A] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[#8F482F] before:rounded-full cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<div className="px-3 py-2 bg-[var(--color-surface)] text-[var(--color-text-primary)] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[var(--color-brand)] before:rounded-full cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">calendar_today</span>
<span>{t('sidebar.scheduled')}</span>
</div>
<div className="px-3 py-2 text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<div className="px-3 py-2 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">history</span>
<span>{t('sidebar.timeGroup.today')}</span>
</div>
<div className="px-3 py-2 text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<div className="px-3 py-2 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">event_note</span>
<span>{t('sidebar.timeGroup.last7days')}</span>
</div>
<div className="px-3 py-2 text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<div className="px-3 py-2 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">archive</span>
<span>{t('sidebar.timeGroup.older')}</span>
</div>
</nav>
<div className="mt-auto pt-4 border-t border-[#87736D]/10">
<div className="text-[10px] text-[#87736D] uppercase tracking-widest px-3 mb-2">{t('scheduledPage.executionMode')}</div>
<div className="px-3 py-2 text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<div className="mt-auto pt-4 border-t border-[var(--color-text-secondary)]/10">
<div className="text-[10px] text-[var(--color-text-secondary)] uppercase tracking-widest px-3 mb-2">{t('scheduledPage.executionMode')}</div>
<div className="px-3 py-2 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">computer</span>
<span>{t('scheduledPage.localMode')}</span>
</div>
<div className="px-3 py-2 text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<div className="px-3 py-2 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg cursor-pointer duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">cloud</span>
<span>{t('scheduledPage.remoteMode')}</span>
</div>
@@ -57,29 +57,29 @@ export function ScheduledTasksEmpty() {
{/* Main Canvas */}
<main className="flex-1 ml-[280px] flex flex-col min-h-screen">
{/* TopAppBar */}
<header className="fixed top-0 right-0 left-[280px] z-30 bg-[#FAF9F5] flex justify-between items-center px-6 h-12 w-full border-b border-[#F4F4F0]">
<header className="fixed top-0 right-0 left-[280px] z-30 bg-[var(--color-surface)] flex justify-between items-center px-6 h-12 w-full border-b border-[#F4F4F0]">
<div className="flex items-center gap-6 h-full">
<div className="text-sm font-bold text-[#1B1C1A] uppercase tracking-tighter font-[Manrope,sans-serif]">Claude Code Companion</div>
<div className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-[0.18em] font-[Manrope,sans-serif]">Heicode</div>
<nav className="flex items-center gap-4 h-full font-[Manrope,sans-serif] font-semibold tracking-wide text-sm">
<span className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.code')}</span>
<span className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.terminal')}</span>
<span className="text-[#1B1C1A] border-b-2 border-[#8F482F] pb-1 h-full flex items-center pt-1">{t('titlebar.history')}</span>
<span className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.code')}</span>
<span className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70 h-full flex items-center">{t('titlebar.terminal')}</span>
<span className="text-[var(--color-text-primary)] border-b-2 border-[var(--color-brand)] pb-1 h-full flex items-center pt-1">{t('titlebar.history')}</span>
</nav>
</div>
<div className="flex items-center gap-4">
<div className="flex items-center gap-1">
<span className="material-symbols-outlined text-[#87736D] text-sm cursor-pointer">arrow_back_ios</span>
<span className="material-symbols-outlined text-[#87736D] text-sm cursor-pointer">arrow_forward_ios</span>
<span className="material-symbols-outlined text-[var(--color-text-secondary)] text-sm cursor-pointer">arrow_back_ios</span>
<span className="material-symbols-outlined text-[var(--color-text-secondary)] text-sm cursor-pointer">arrow_forward_ios</span>
</div>
<div className="h-4 w-[1px] bg-[#87736D]/20"></div>
<div className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer text-xs font-semibold uppercase tracking-wider">{t('sidebar.settings')}</div>
<div className="h-4 w-[1px] bg-[var(--color-text-secondary)]/20"></div>
<div className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer text-xs font-semibold uppercase tracking-wider">{t('sidebar.settings')}</div>
</div>
</header>
{/* Content Area */}
<div className="flex-1 mt-12 mb-8 flex flex-col items-center justify-center p-8 bg-[#FAF9F5]">
<div className="flex-1 mt-12 mb-8 flex flex-col items-center justify-center p-8 bg-[var(--color-surface)]">
<div className="max-w-2xl w-full text-center">
<h1 className="text-3xl font-[Manrope,sans-serif] font-extrabold text-[#1B1C1A] tracking-tight mb-16">{t('scheduledPage.title')}</h1>
<h1 className="text-3xl font-[Manrope,sans-serif] font-extrabold text-[var(--color-text-primary)] tracking-tight mb-16">{t('scheduledPage.title')}</h1>
{/* Empty State Illustration/Card */}
<div className="relative group">
@@ -89,7 +89,7 @@ export function ScheduledTasksEmpty() {
<div className="w-32 h-32 rounded-full bg-[#E9E8E4] flex items-center justify-center mb-10 shadow-sm">
<div className="w-20 h-20 rounded-full bg-white flex items-center justify-center border border-[#DAC1BA]/10">
<span
className="material-symbols-outlined text-[#8F482F] text-5xl"
className="material-symbols-outlined text-[var(--color-brand)] text-5xl"
style={{ fontVariationSettings: "'wght' 300" }}
>
schedule
@@ -99,7 +99,7 @@ export function ScheduledTasksEmpty() {
<p className="text-[#54433E] font-[Inter,sans-serif] text-lg max-w-sm mx-auto leading-relaxed mb-12">
{t('tasks.emptyTitle')} {t('tasks.emptyDesc')}
</p>
<button className="group relative px-8 py-4 bg-[#8F482F] text-white rounded-xl font-[Manrope,sans-serif] font-bold text-sm tracking-wide shadow-lg hover:shadow-[#8F482F]/20 transition-all flex items-center gap-3 overflow-hidden">
<button className="group relative px-8 py-4 bg-[var(--color-brand)] text-white rounded-xl font-[Manrope,sans-serif] font-bold text-sm tracking-wide shadow-lg hover:shadow-[var(--color-brand)]/20 transition-all flex items-center gap-3 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-white/10 to-transparent opacity-30"></div>
<span className="material-symbols-outlined text-lg">add_task</span>
<span>{t('tasks.newTask')}</span>
@@ -110,15 +110,15 @@ export function ScheduledTasksEmpty() {
{/* Subtle Decorative Bento Elements */}
<div className="grid grid-cols-3 gap-4 mt-20 opacity-40">
<div className="h-24 bg-[#F4F4F0] rounded-xl border border-[#DAC1BA]/10 flex flex-col items-center justify-center p-4">
<span className="material-symbols-outlined text-[#87736D] mb-2">commit</span>
<span className="material-symbols-outlined text-[var(--color-text-secondary)] mb-2">commit</span>
<div className="w-12 h-1 bg-[#DAC1BA]/30 rounded-full"></div>
</div>
<div className="h-24 bg-[#F4F4F0] rounded-xl border border-[#DAC1BA]/10 flex flex-col items-center justify-center p-4">
<span className="material-symbols-outlined text-[#87736D] mb-2">terminal</span>
<span className="material-symbols-outlined text-[var(--color-text-secondary)] mb-2">terminal</span>
<div className="w-8 h-1 bg-[#DAC1BA]/30 rounded-full"></div>
</div>
<div className="h-24 bg-[#F4F4F0] rounded-xl border border-[#DAC1BA]/10 flex flex-col items-center justify-center p-4">
<span className="material-symbols-outlined text-[#87736D] mb-2">code_blocks</span>
<span className="material-symbols-outlined text-[var(--color-text-secondary)] mb-2">code_blocks</span>
<div className="w-10 h-1 bg-[#DAC1BA]/30 rounded-full"></div>
</div>
</div>
@@ -126,21 +126,21 @@ export function ScheduledTasksEmpty() {
</div>
{/* Footer */}
<footer className="fixed bottom-0 left-0 w-full h-8 bg-[#FAF9F5] flex items-center justify-between px-4 z-50 border-t border-[#87736D]/20 font-[Inter,sans-serif] text-xs tracking-tight">
<div className="flex items-center gap-3 text-[#87736D]">
<footer className="fixed bottom-0 left-0 w-full h-8 bg-[var(--color-surface)] flex items-center justify-between px-4 z-50 border-t border-[var(--color-text-secondary)]/20 font-[Inter,sans-serif] text-xs tracking-tight">
<div className="flex items-center gap-3 text-[var(--color-text-secondary)]">
<div className="w-2 h-2 rounded-full bg-[#677B4E]"></div>
<span>{mockStatusBar.user} &bull; {mockStatusBar.username} &bull; {mockStatusBar.plan}</span>
</div>
<div className="flex items-center gap-6">
<span className="text-[#87736D] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors cursor-pointer flex items-center gap-1">
<span className="text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors cursor-pointer flex items-center gap-1">
<span className="material-symbols-outlined text-[14px]">account_tree</span>
{mockStatusBar.branch}
</span>
<span className="text-[#87736D] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors cursor-pointer flex items-center gap-1">
<span className="text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors cursor-pointer flex items-center gap-1">
<span className="material-symbols-outlined text-[14px]">workspaces</span>
{mockStatusBar.worktreeToggle}
</span>
<span className="text-[#8F482F] font-bold hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors cursor-pointer flex items-center gap-1">
<span className="text-[var(--color-brand)] font-bold hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors cursor-pointer flex items-center gap-1">
<span className="material-symbols-outlined text-[14px]">toggle_on</span>
{mockStatusBar.localSwitch}
</span>
@@ -9,7 +9,7 @@ export function ScheduledTasksList() {
const task2 = tasks[2]!
return (
<div className="bg-[#FAF9F5] text-[#1B1C1A] flex min-h-screen overflow-hidden font-[Inter,sans-serif]">
<div className="bg-[var(--color-surface)] text-[var(--color-text-primary)] flex min-h-screen overflow-hidden font-[Inter,sans-serif]">
{/* SideNavBar */}
<aside className="fixed left-0 top-0 h-full w-[280px] bg-[#F4F4F0] flex flex-col p-4 gap-2 z-40">
<div className="mb-6 px-2 flex items-center gap-3">
@@ -22,16 +22,16 @@ export function ScheduledTasksList() {
</span>
</div>
<div>
<h2 className="font-[Manrope,sans-serif] text-sm font-bold text-[#1B1C1A] uppercase tracking-tighter">{t('sidebar.allProjects')}</h2>
<p className="text-xs text-[#87736D] font-medium">{t('scheduledPage.activeSession')}</p>
<h2 className="font-[Manrope,sans-serif] text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter">{t('sidebar.allProjects')}</h2>
<p className="text-xs text-[var(--color-text-secondary)] font-medium">{t('scheduledPage.activeSession')}</p>
</div>
</div>
<button className="flex items-center gap-3 px-3 py-2 w-full text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<button className="flex items-center gap-3 px-3 py-2 w-full text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<span className="material-symbols-outlined">add</span>
{t('sidebar.newSession')}
</button>
<button className="flex items-center gap-3 px-3 py-2 w-full bg-[#FAF9F5] text-[#1B1C1A] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[#8F482F] before:rounded-full font-medium text-sm duration-200 ease-in-out">
<button className="flex items-center gap-3 px-3 py-2 w-full bg-[var(--color-surface)] text-[var(--color-text-primary)] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[var(--color-brand)] before:rounded-full font-medium text-sm duration-200 ease-in-out">
<span
className="material-symbols-outlined"
style={{ fontVariationSettings: "'FILL' 1" }}
@@ -40,32 +40,32 @@ export function ScheduledTasksList() {
</span>
{t('sidebar.scheduled')}
</button>
<button className="flex items-center gap-3 px-3 py-2 w-full text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<button className="flex items-center gap-3 px-3 py-2 w-full text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<span className="material-symbols-outlined">history</span>
{t('sidebar.timeGroup.today')}
</button>
<button className="flex items-center gap-3 px-3 py-2 w-full text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<button className="flex items-center gap-3 px-3 py-2 w-full text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<span className="material-symbols-outlined">event_note</span>
{t('sidebar.timeGroup.last7days')}
</button>
<button className="flex items-center gap-3 px-3 py-2 w-full text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<button className="flex items-center gap-3 px-3 py-2 w-full text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<span className="material-symbols-outlined">archive</span>
{t('sidebar.timeGroup.older')}
</button>
<div className="mt-auto pt-4 flex flex-col gap-2">
<div className="px-2 py-4">
<button className="w-full bg-[#E9E8E4] text-[#1B1C1A] font-[Manrope,sans-serif] text-xs font-bold py-2 rounded-lg flex items-center justify-center gap-2 hover:bg-[#E3E2DF] transition-colors">
<button className="w-full bg-[#E9E8E4] text-[var(--color-text-primary)] font-[Manrope,sans-serif] text-xs font-bold py-2 rounded-lg flex items-center justify-center gap-2 hover:bg-[#E3E2DF] transition-colors">
<span className="material-symbols-outlined text-[1rem]">search</span>
{t('sidebar.searchPlaceholder')}
</button>
</div>
<div className="h-[1px] bg-[#DAC1BA]/20 mx-2 mb-2"></div>
<button className="flex items-center gap-3 px-3 py-2 w-full text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<button className="flex items-center gap-3 px-3 py-2 w-full text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<span className="material-symbols-outlined">computer</span>
{t('scheduledPage.localMode')}
</button>
<button className="flex items-center gap-3 px-3 py-2 w-full text-[#87736D] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<button className="flex items-center gap-3 px-3 py-2 w-full text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] transition-all rounded-lg font-medium text-sm duration-200 ease-in-out">
<span className="material-symbols-outlined">cloud</span>
{t('scheduledPage.remoteMode')}
</button>
@@ -75,25 +75,25 @@ export function ScheduledTasksList() {
{/* Main Content Area */}
<main className="flex-1 flex flex-col ml-[280px] min-w-0 h-screen">
{/* TopAppBar */}
<header className="bg-[#FAF9F5] h-12 w-full flex justify-between items-center px-6 z-30">
<header className="bg-[var(--color-surface)] h-12 w-full flex justify-between items-center px-6 z-30">
<div className="flex items-center gap-8">
<div className="font-[Manrope,sans-serif] font-bold text-[#1B1C1A] uppercase tracking-tighter text-sm">Claude Code Companion</div>
<div className="font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)] uppercase tracking-[0.18em] text-sm">Heicode</div>
<nav className="flex items-center gap-6 font-[Manrope,sans-serif] font-semibold tracking-wide text-sm">
<a className="text-[#87736D] hover:text-[#8F482F] transition-colors" href="#">{t('titlebar.code')}</a>
<a className="text-[#87736D] hover:text-[#8F482F] transition-colors" href="#">{t('titlebar.terminal')}</a>
<a className="text-[#1B1C1A] border-b-2 border-[#8F482F] pb-1" href="#">{t('titlebar.history')}</a>
<a className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors" href="#">{t('titlebar.code')}</a>
<a className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors" href="#">{t('titlebar.terminal')}</a>
<a className="text-[var(--color-text-primary)] border-b-2 border-[var(--color-brand)] pb-1" href="#">{t('titlebar.history')}</a>
</nav>
</div>
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<button className="p-1 text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer active:opacity-70">
<button className="p-1 text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70">
<span className="material-symbols-outlined text-[1rem]">arrow_back_ios</span>
</button>
<button className="p-1 text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer active:opacity-70">
<button className="p-1 text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70">
<span className="material-symbols-outlined text-[1rem]">arrow_forward_ios</span>
</button>
</div>
<button className="font-[Manrope,sans-serif] font-semibold tracking-wide text-sm text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer active:opacity-70 flex items-center gap-1">
<button className="font-[Manrope,sans-serif] font-semibold tracking-wide text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70 flex items-center gap-1">
<span className="material-symbols-outlined text-[1.1rem]">settings</span>
{t('sidebar.settings')}
</button>
@@ -104,15 +104,15 @@ export function ScheduledTasksList() {
<div className="bg-[#F4F4F0] h-[1px] w-full"></div>
{/* Scrollable Content */}
<section className="flex-1 overflow-y-auto p-12 bg-[#FAF9F5]">
<section className="flex-1 overflow-y-auto p-12 bg-[var(--color-surface)]">
<div className="max-w-5xl mx-auto">
{/* Page Header */}
<div className="flex justify-between items-end mb-12">
<div className="space-y-1">
<h1 className="font-[Manrope,sans-serif] text-3xl font-bold tracking-tight text-[#1B1C1A]">{t('scheduledPage.title')}</h1>
<p className="text-[#87736D] text-sm">{t('scheduledPage.subtitle')}</p>
<h1 className="font-[Manrope,sans-serif] text-3xl font-bold tracking-tight text-[var(--color-text-primary)]">{t('scheduledPage.title')}</h1>
<p className="text-[var(--color-text-secondary)] text-sm">{t('scheduledPage.subtitle')}</p>
</div>
<button className="bg-[#8F482F] hover:bg-[#AD5F45] text-white px-5 py-2.5 rounded-lg flex items-center gap-2 transition-all shadow-sm font-medium text-sm">
<button className="bg-[var(--color-brand)] hover:bg-[#AD5F45] text-white px-5 py-2.5 rounded-lg flex items-center gap-2 transition-all shadow-sm font-medium text-sm">
<span className="material-symbols-outlined text-[1.1rem]">add_task</span>
{t('tasks.createNew')}
</button>
@@ -123,10 +123,10 @@ export function ScheduledTasksList() {
{/* Total Tasks */}
<div className="bg-[#F4F4F0] p-6 rounded-xl border border-[#DAC1BA]/10">
<div className="flex items-center justify-between mb-4">
<span className="text-xs font-bold uppercase tracking-widest text-[#87736D]">{t('tasks.totalTasks')}</span>
<span className="material-symbols-outlined text-[#8F482F]">analytics</span>
<span className="text-xs font-bold uppercase tracking-widest text-[var(--color-text-secondary)]">{t('tasks.totalTasks')}</span>
<span className="material-symbols-outlined text-[var(--color-brand)]">analytics</span>
</div>
<div className="text-4xl font-[Manrope,sans-serif] font-extrabold text-[#1B1C1A]">{stats.totalTasks}</div>
<div className="text-4xl font-[Manrope,sans-serif] font-extrabold text-[var(--color-text-primary)]">{stats.totalTasks}</div>
<div className="mt-2 flex items-center gap-1 text-[10px] text-[#4F6237] font-bold bg-[#677B4E]/20 px-2 py-0.5 rounded-full w-fit">
<span className="material-symbols-outlined text-[10px]">trending_up</span>
{t('scheduledPage.thisMonth', { count: '+2' })}
@@ -136,21 +136,21 @@ export function ScheduledTasksList() {
{/* Next Run */}
<div className="bg-[#F4F4F0] p-6 rounded-xl border border-[#DAC1BA]/10">
<div className="flex items-center justify-between mb-4">
<span className="text-xs font-bold uppercase tracking-widest text-[#87736D]">{t('scheduledPage.nextRun')}</span>
<span className="text-xs font-bold uppercase tracking-widest text-[var(--color-text-secondary)]">{t('scheduledPage.nextRun')}</span>
<span className="material-symbols-outlined text-[#2D628F]">schedule</span>
</div>
<div className="text-xl font-[Manrope,sans-serif] font-bold text-[#1B1C1A]">{stats.nextRun.name}</div>
<div className="text-xl font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)]">{stats.nextRun.name}</div>
<p className="text-sm font-[JetBrains_Mono,monospace] text-[#2D628F] mt-1">{stats.nextRun.time}</p>
</div>
{/* System Health */}
<div className="bg-[#F4F4F0] p-6 rounded-xl border border-[#DAC1BA]/10">
<div className="flex items-center justify-between mb-4">
<span className="text-xs font-bold uppercase tracking-widest text-[#87736D]">{t('scheduledPage.systemHealth')}</span>
<span className="text-xs font-bold uppercase tracking-widest text-[var(--color-text-secondary)]">{t('scheduledPage.systemHealth')}</span>
<span className="material-symbols-outlined text-[#4F6237]">check_circle</span>
</div>
<div className="text-4xl font-[Manrope,sans-serif] font-extrabold text-[#1B1C1A]">{stats.systemHealth}%</div>
<p className="text-xs text-[#87736D] mt-2 font-medium">{stats.healthPeriod}</p>
<div className="text-4xl font-[Manrope,sans-serif] font-extrabold text-[var(--color-text-primary)]">{stats.systemHealth}%</div>
<p className="text-xs text-[var(--color-text-secondary)] mt-2 font-medium">{stats.healthPeriod}</p>
</div>
</div>
@@ -171,12 +171,12 @@ export function ScheduledTasksList() {
<tr className="group hover:bg-[#F4F4F0]/30 transition-colors">
<td className="px-6 py-5">
<div className="flex items-center gap-3">
<div className="p-2 bg-[#FFDBD0] text-[#8F482F] rounded-lg">
<div className="p-2 bg-[#FFDBD0] text-[var(--color-brand)] rounded-lg">
<span className="material-symbols-outlined text-[1.2rem]">code_blocks</span>
</div>
<div>
<div className="font-[Manrope,sans-serif] font-bold text-[#1B1C1A] text-sm">{task0.name}</div>
<div className="text-xs text-[#87736D] font-medium">Root: /projects/companion/src</div>
<div className="font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)] text-sm">{task0.name}</div>
<div className="text-xs text-[var(--color-text-secondary)] font-medium">Root: /projects/companion/src</div>
</div>
</div>
</td>
@@ -199,13 +199,13 @@ export function ScheduledTasksList() {
</td>
<td className="px-6 py-5 text-right">
<div className="flex items-center justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
<button className="p-2 text-[#87736D] hover:text-[#8F482F] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">edit</span>
</button>
<button className="p-2 text-[#87736D] hover:text-[#BA1A1A] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[#BA1A1A] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">delete</span>
</button>
<button className="p-2 text-[#87736D] hover:text-[#1B1C1A] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">more_vert</span>
</button>
</div>
@@ -220,8 +220,8 @@ export function ScheduledTasksList() {
<span className="material-symbols-outlined text-[1.2rem]">cleaning_services</span>
</div>
<div>
<div className="font-[Manrope,sans-serif] font-bold text-[#1B1C1A] text-sm">{task1.name}</div>
<div className="text-xs text-[#87736D] font-medium">{task1.description}</div>
<div className="font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)] text-sm">{task1.name}</div>
<div className="text-xs text-[var(--color-text-secondary)] font-medium">{task1.description}</div>
</div>
</div>
</td>
@@ -244,13 +244,13 @@ export function ScheduledTasksList() {
</td>
<td className="px-6 py-5 text-right">
<div className="flex items-center justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
<button className="p-2 text-[#87736D] hover:text-[#8F482F] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">edit</span>
</button>
<button className="p-2 text-[#87736D] hover:text-[#BA1A1A] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[#BA1A1A] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">delete</span>
</button>
<button className="p-2 text-[#87736D] hover:text-[#1B1C1A] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">more_vert</span>
</button>
</div>
@@ -265,8 +265,8 @@ export function ScheduledTasksList() {
<span className="material-symbols-outlined text-[1.2rem]">database</span>
</div>
<div>
<div className="font-[Manrope,sans-serif] font-bold text-[#1B1C1A] text-sm">{task2.name}</div>
<div className="text-xs text-[#87736D] font-medium">{task2.description}</div>
<div className="font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)] text-sm">{task2.name}</div>
<div className="text-xs text-[var(--color-text-secondary)] font-medium">{task2.description}</div>
</div>
</div>
</td>
@@ -289,13 +289,13 @@ export function ScheduledTasksList() {
</td>
<td className="px-6 py-5 text-right">
<div className="flex items-center justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
<button className="p-2 text-[#87736D] hover:text-[#8F482F] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">edit</span>
</button>
<button className="p-2 text-[#87736D] hover:text-[#BA1A1A] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[#BA1A1A] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">delete</span>
</button>
<button className="p-2 text-[#87736D] hover:text-[#1B1C1A] transition-colors">
<button className="p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors">
<span className="material-symbols-outlined text-[1.1rem]">more_vert</span>
</button>
</div>
@@ -307,10 +307,10 @@ export function ScheduledTasksList() {
{/* End of list placeholder */}
<div className="p-12 text-center border-t border-[#DAC1BA]/10">
<div className="inline-flex items-center justify-center w-12 h-12 rounded-full bg-[#F4F4F0] mb-4">
<span className="material-symbols-outlined text-[#87736D]">history_toggle_off</span>
<span className="material-symbols-outlined text-[var(--color-text-secondary)]">history_toggle_off</span>
</div>
<h3 className="font-[Manrope,sans-serif] font-bold text-[#1B1C1A] text-base">{t('scheduledPage.endOfList')}</h3>
<p className="text-sm text-[#87736D] max-w-xs mx-auto mt-1">{t('scheduledPage.pausedTasks')}</p>
<h3 className="font-[Manrope,sans-serif] font-bold text-[var(--color-text-primary)] text-base">{t('scheduledPage.endOfList')}</h3>
<p className="text-sm text-[var(--color-text-secondary)] max-w-xs mx-auto mt-1">{t('scheduledPage.pausedTasks')}</p>
</div>
</div>
@@ -318,7 +318,7 @@ export function ScheduledTasksList() {
<div className="mt-12 flex flex-col md:flex-row gap-8 items-start">
{/* Recent Output Logs */}
<div className="flex-1 space-y-6">
<h2 className="font-[Manrope,sans-serif] text-lg font-bold text-[#1B1C1A]">{t('scheduledPage.recentLogs')}</h2>
<h2 className="font-[Manrope,sans-serif] text-lg font-bold text-[var(--color-text-primary)]">{t('scheduledPage.recentLogs')}</h2>
<div className="bg-[#DBDAD6] rounded-xl p-6 font-[JetBrains_Mono,monospace] text-[13px] leading-relaxed text-[#54433E] overflow-x-auto shadow-inner">
<div className="flex gap-4 opacity-50 mb-1">
<span className="w-32 shrink-0">2023-11-10 23:01</span>
@@ -342,27 +342,27 @@ export function ScheduledTasksList() {
</div>
<div className="mt-4 pt-4 border-t border-[#DAC1BA]/20 flex items-center justify-between">
<span className="text-[11px] uppercase tracking-tighter opacity-50">Log stream: active</span>
<button className="text-[#8F482F] font-bold text-xs hover:underline">{t('scheduledPage.viewArtifacts')}</button>
<button className="text-[var(--color-brand)] font-bold text-xs hover:underline">{t('scheduledPage.viewArtifacts')}</button>
</div>
</div>
</div>
{/* Resource Allocation Panel */}
<div className="w-full md:w-80 shrink-0">
<div className="bg-[#AD5F45]/10 p-6 rounded-xl border border-[#8F482F]/10">
<h3 className="font-[Manrope,sans-serif] font-bold text-[#8F482F] text-sm mb-3">{t('scheduledPage.resourceAllocation')}</h3>
<div className="bg-[#AD5F45]/10 p-6 rounded-xl border border-[var(--color-brand)]/10">
<h3 className="font-[Manrope,sans-serif] font-bold text-[var(--color-brand)] text-sm mb-3">{t('scheduledPage.resourceAllocation')}</h3>
<div className="space-y-4">
<div className="space-y-1">
<div className="flex justify-between text-[11px] font-bold text-[#87736D] uppercase tracking-wider">
<div className="flex justify-between text-[11px] font-bold text-[var(--color-text-secondary)] uppercase tracking-wider">
<span>{t('scheduledPage.cpuCapacity')}</span>
<span>42%</span>
</div>
<div className="w-full h-1 bg-[#DAC1BA]/30 rounded-full overflow-hidden">
<div className="h-full bg-[#8F482F]" style={{ width: '42%' }}></div>
<div className="h-full bg-[var(--color-brand)]" style={{ width: '42%' }}></div>
</div>
</div>
<div className="space-y-1">
<div className="flex justify-between text-[11px] font-bold text-[#87736D] uppercase tracking-wider">
<div className="flex justify-between text-[11px] font-bold text-[var(--color-text-secondary)] uppercase tracking-wider">
<span>{t('scheduledPage.memoryLoad')}</span>
<span>68%</span>
</div>
@@ -381,10 +381,10 @@ export function ScheduledTasksList() {
</section>
{/* Footer */}
<footer className="bg-[#FAF9F5] border-t border-[#87736D]/20 fixed bottom-0 left-0 w-full h-8 flex items-center justify-between px-4 z-50">
<footer className="bg-[var(--color-surface)] border-t border-[var(--color-text-secondary)]/20 fixed bottom-0 left-0 w-full h-8 flex items-center justify-between px-4 z-50">
<div className="flex items-center gap-4">
<span className="font-[Inter,sans-serif] text-xs tracking-tight text-[#87736D]">{mockStatusBar.user} &bull; {mockStatusBar.username} &bull; {mockStatusBar.plan}</span>
<div className="h-3 w-[1px] bg-[#87736D]/30"></div>
<span className="font-[Inter,sans-serif] text-xs tracking-tight text-[var(--color-text-secondary)]">{mockStatusBar.user} &bull; {mockStatusBar.username} &bull; {mockStatusBar.plan}</span>
<div className="h-3 w-[1px] bg-[var(--color-text-secondary)]/30"></div>
<div className="flex items-center gap-2">
<span
className="material-symbols-outlined text-[10px] text-[#4F6237]"
@@ -392,19 +392,19 @@ export function ScheduledTasksList() {
>
fiber_manual_record
</span>
<span className="font-[Inter,sans-serif] text-xs tracking-tight text-[#1B1C1A]">{t('scheduledPage.connectedLocal')}</span>
<span className="font-[Inter,sans-serif] text-xs tracking-tight text-[var(--color-text-primary)]">{t('scheduledPage.connectedLocal')}</span>
</div>
</div>
<div className="flex items-center gap-6">
<button className="font-[Inter,sans-serif] text-xs tracking-tight text-[#87736D] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors flex items-center gap-1">
<button className="font-[Inter,sans-serif] text-xs tracking-tight text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors flex items-center gap-1">
<span className="material-symbols-outlined text-[12px]">account_tree</span>
{mockStatusBar.branch}
</button>
<button className="font-[Inter,sans-serif] text-xs tracking-tight text-[#87736D] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors flex items-center gap-1">
<button className="font-[Inter,sans-serif] text-xs tracking-tight text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors flex items-center gap-1">
<span className="material-symbols-outlined text-[12px]">layers</span>
{mockStatusBar.worktreeToggle}
</button>
<button className="font-[Inter,sans-serif] text-xs tracking-tight text-[#8F482F] font-bold hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors flex items-center gap-1">
<button className="font-[Inter,sans-serif] text-xs tracking-tight text-[var(--color-brand)] font-bold hover:bg-[#F4F4F0] px-2 py-0.5 rounded transition-colors flex items-center gap-1">
<span className="material-symbols-outlined text-[12px]">toggle_on</span>
{mockStatusBar.localSwitch}
</button>
+18 -18
View File
@@ -39,31 +39,31 @@ export default function SessionControls() {
return (
<div className="h-screen w-screen bg-background text-on-surface font-body selection:bg-primary-fixed overflow-hidden relative">
{/* ─── TopAppBar ─────────────────────────────────────────── */}
<header className="bg-[#FAF9F5] font-headline font-semibold tracking-wide text-sm fixed top-0 left-0 right-0 flex justify-between items-center px-6 h-12 z-40">
<header className="bg-[var(--color-surface)] font-headline font-semibold tracking-wide text-sm fixed top-0 left-0 right-0 flex justify-between items-center px-6 h-12 z-40">
<div className="flex items-center gap-6">
<span className="text-sm font-bold text-[#1B1C1A] uppercase tracking-tighter">
Claude Code Companion
<span className="text-sm font-bold text-[var(--color-text-primary)] uppercase tracking-tighter">
Heicode
</span>
<nav className="hidden md:flex gap-4">
<a className="text-[#1B1C1A] border-b-2 border-[#8F482F] pb-1 cursor-pointer active:opacity-70">
<a className="text-[var(--color-text-primary)] border-b-2 border-[var(--color-brand)] pb-1 cursor-pointer active:opacity-70">
Code
</a>
<a className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer active:opacity-70">
<a className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70">
Terminal
</a>
<a className="text-[#87736D] hover:text-[#8F482F] transition-colors cursor-pointer active:opacity-70">
<a className="text-[var(--color-text-secondary)] hover:text-[var(--color-brand)] transition-colors cursor-pointer active:opacity-70">
History
</a>
</nav>
</div>
<div className="flex items-center gap-3">
<span className="material-symbols-outlined text-[#87736D] cursor-pointer">
<span className="material-symbols-outlined text-[var(--color-text-secondary)] cursor-pointer">
arrow_back_ios
</span>
<span className="material-symbols-outlined text-[#87736D] cursor-pointer">
<span className="material-symbols-outlined text-[var(--color-text-secondary)] cursor-pointer">
arrow_forward_ios
</span>
<button className="ml-2 px-3 py-1 bg-surface-container-high rounded text-[#8F482F] hover:bg-surface-container-highest transition-colors">
<button className="ml-2 px-3 py-1 bg-surface-container-high rounded text-[var(--color-brand)] hover:bg-surface-container-highest transition-colors">
Settings
</button>
</div>
@@ -92,23 +92,23 @@ export default function SessionControls() {
</div>
{/* Nav items */}
<button className="w-full text-left p-2.5 bg-[#FAF9F5] text-[#1B1C1A] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[#8F482F] before:rounded-full before:top-1/2 before:-translate-y-1/2 transition-all duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined text-[#8F482F]">add</span>
<button className="w-full text-left p-2.5 bg-[var(--color-surface)] text-[var(--color-text-primary)] rounded-lg relative before:content-[''] before:absolute before:left-[-8px] before:w-1 before:h-4 before:bg-[var(--color-brand)] before:rounded-full before:top-1/2 before:-translate-y-1/2 transition-all duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined text-[var(--color-brand)]">add</span>
<span>New session</span>
</button>
<button className="w-full text-left p-2.5 text-[#87736D] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3">
<button className="w-full text-left p-2.5 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3">
<span className="material-symbols-outlined">calendar_today</span>
<span>Scheduled</span>
</button>
<button className="w-full text-left p-2.5 text-[#87736D] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3" data-count={mockSessions.today.length}>
<button className="w-full text-left p-2.5 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3" data-count={mockSessions.today.length}>
<span className="material-symbols-outlined">history</span>
<span>Today</span>
</button>
<button className="w-full text-left p-2.5 text-[#87736D] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3" data-count={mockSessions.previous7Days.length}>
<button className="w-full text-left p-2.5 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3" data-count={mockSessions.previous7Days.length}>
<span className="material-symbols-outlined">event_note</span>
<span>Previous 7 Days</span>
</button>
<button className="w-full text-left p-2.5 text-[#87736D] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3" data-count={mockSessions.older.length}>
<button className="w-full text-left p-2.5 text-[var(--color-text-secondary)] hover:bg-[#EBEBE6] rounded-lg transition-all duration-200 ease-in-out flex items-center gap-3" data-count={mockSessions.older.length}>
<span className="material-symbols-outlined">archive</span>
<span>Older</span>
</button>
@@ -427,7 +427,7 @@ export default function SessionControls() {
</div>
{/* ─── Footer / Status Bar ───────────────────────────────── */}
<footer className="bg-[#FAF9F5] font-body text-xs tracking-tight fixed bottom-0 left-0 w-full h-8 border-t border-[#87736D]/20 flex items-center justify-between px-4 z-[60]">
<footer className="bg-[var(--color-surface)] font-body text-xs tracking-tight fixed bottom-0 left-0 w-full h-8 border-t border-[var(--color-text-secondary)]/20 flex items-center justify-between px-4 z-[60]">
<div className="flex items-center gap-3">
<div className="flex items-center gap-1.5">
<div className="w-4 h-4 rounded-full bg-primary-fixed flex items-center justify-center">
@@ -447,10 +447,10 @@ export default function SessionControls() {
<button className="text-primary font-bold hover:bg-[#F4F4F0] transition-colors px-2 py-0.5 rounded">
{mockStatusBar.branch}
</button>
<button className="text-[#87736D] hover:bg-[#F4F4F0] transition-colors px-2 py-0.5 rounded">
<button className="text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] transition-colors px-2 py-0.5 rounded">
{mockStatusBar.worktreeToggle}
</button>
<button className="text-[#87736D] hover:bg-[#F4F4F0] transition-colors px-2 py-0.5 rounded">
<button className="text-[var(--color-text-secondary)] hover:bg-[#F4F4F0] transition-colors px-2 py-0.5 rounded">
{mockStatusBar.localSwitch}
</button>
</div>
+3 -3
View File
@@ -96,7 +96,7 @@ function TabButton({ icon, label, active, onClick }: { icon: string; label: stri
// ─── Provider Settings ──────────────────────────────────────
function ProviderSettings() {
export function ProviderSettings() {
const {
providers,
activeId,
@@ -1632,8 +1632,8 @@ function AboutSettings() {
return (
<div className="w-full min-w-0 max-w-lg mx-auto flex flex-col items-center py-6">
{/* Logo + App Name + Version */}
<img src="/app-icon.png" alt="Claude Code Haha" className="w-20 h-20 mb-4" />
<h1 className="text-xl font-bold text-[var(--color-text-primary)]">Claude Code Haha</h1>
<img src="/app-icon.png" alt="Heicode" className="w-20 h-20 mb-4" />
<h1 className="text-xl font-bold text-[var(--color-text-primary)]">Heicode</h1>
{version && (
<div className="mt-1 flex items-center gap-2 text-xs text-[var(--color-text-tertiary)]">
<span>{t('settings.about.version')} {version}</span>
+2 -2
View File
@@ -1,14 +1,14 @@
import { create } from 'zustand'
import type { ThemeMode } from '../types/settings'
const THEME_STORAGE_KEY = 'cc-haha-theme'
const THEME_STORAGE_KEY = 'heicode-theme'
function getStoredTheme(): ThemeMode {
try {
const stored = localStorage.getItem(THEME_STORAGE_KEY)
if (stored === 'light' || stored === 'dark') return stored
} catch { /* localStorage unavailable */ }
return 'light'
return 'dark'
}
export function applyTheme(theme: ThemeMode) {
+205 -202
View File
@@ -108,47 +108,49 @@
outline: none;
}
/* ─── Tailwind Theme Override (matches prototype design system) ─── */
/* ─── Tailwind Theme Override — Heicode Premium Black ─── */
@theme {
--color-primary: #8F482F;
--color-primary-container: #AD5F45;
--color-primary-fixed: #FFDBD0;
--color-primary-fixed-dim: #FFB59D;
/* Brand accent — restrained warm gold, used sparingly */
--color-primary: #C5A572;
--color-primary-container: #A38247;
--color-primary-fixed: #E0C896;
--color-primary-fixed-dim: #C5A572;
--color-on-primary: #FFFFFF;
--color-on-surface: #1B1C1A;
--color-on-surface-variant: #54433E;
--color-on-primary: #1A1410;
--color-on-surface: #ECECEE;
--color-on-surface-variant: #B0B0B5;
--color-surface: #FAF9F5;
--color-surface-bright: #FAF9F5;
--color-surface-dim: #DBDAD6;
--color-surface-container: #EFEEEA;
--color-surface-container-low: #F4F4F0;
--color-surface-container-high: #E9E8E4;
--color-surface-container-highest: #E3E2DF;
--color-surface-container-lowest: #FFFFFF;
--color-surface-variant: #E3E2DF;
/* Black surface stack — near-black with slight warm tint, low-contrast layering */
--color-surface: #141418;
--color-surface-bright: #1F1F25;
--color-surface-dim: #0A0A0C;
--color-surface-container: #1A1A1F;
--color-surface-container-low: #16161A;
--color-surface-container-high: #1F1F25;
--color-surface-container-highest: #26262E;
--color-surface-container-lowest: #0A0A0C;
--color-surface-variant: #1F1F25;
--color-background: #FAF9F5;
--color-background: #0A0A0C;
--color-outline: #87736D;
--color-outline-variant: #DAC1BA;
--color-outline: #5A5A62;
--color-outline-variant: #2A2A30;
--color-secondary: #2D628F;
--color-secondary-container: #9ACBFE;
--color-tertiary: #4F6237;
--color-tertiary-container: #677B4E;
--color-secondary: #8B95A8;
--color-secondary-container: #2A2F3A;
--color-tertiary: #C5A572;
--color-tertiary-container: #2A241A;
--color-error: #BA1A1A;
--color-error-container: #FFDAD6;
--color-on-error-container: #410002;
--color-error: #E5484D;
--color-error-container: #3A1517;
--color-on-error-container: #FECDCD;
--color-inverse-surface: #2F312E;
--color-inverse-on-surface: #F2F1ED;
--color-inverse-primary: #FFB59D;
--color-inverse-surface: #ECECEE;
--color-inverse-on-surface: #14140C;
--color-inverse-primary: #8E7547;
--color-success: #16A34A;
--color-warning: #CA8A04;
--color-success: #2EA86E;
--color-warning: #E5A23E;
--font-headline: 'Manrope', sans-serif;
--font-body: 'Inter', sans-serif;
@@ -156,10 +158,10 @@
--font-mono: 'JetBrains Mono', monospace;
}
/* ─── Semantic Aliases (used by layout & infrastructure components) ── */
/* ─── Semantic Aliases — DEFAULT IS DARK (Heicode Premium Black) ─── */
:root,
[data-theme="light"] {
color-scheme: light;
[data-theme="dark"] {
color-scheme: dark;
/* Layout dimensions */
--sidebar-width: 280px;
@@ -170,101 +172,103 @@
--motion-sidebar-easing: cubic-bezier(0.22, 1, 0.36, 1);
/* Surface aliases */
--color-surface-sidebar: var(--color-surface-container-low);
--color-surface-sidebar: #101014;
--color-surface-hover: var(--color-surface-container-high);
--color-surface-selected: var(--color-surface-container);
--color-model-option-selected-bg: var(--color-primary-fixed);
--color-model-option-selected-border: rgba(143, 72, 47, 0.2);
--color-sidebar-filter-bg: transparent;
--color-sidebar-filter-border: rgba(218, 193, 186, 0.92);
--color-surface-selected: var(--color-surface-container-highest);
--color-model-option-selected-bg: rgba(197, 165, 114, 0.10);
--color-model-option-selected-border: rgba(197, 165, 114, 0.32);
--color-sidebar-filter-bg: rgba(255, 255, 255, 0.02);
--color-sidebar-filter-border: rgba(255, 255, 255, 0.06);
--color-sidebar-filter-icon-bg: transparent;
--color-sidebar-search-bg: rgba(255, 255, 255, 0.78);
--color-sidebar-search-border: rgba(218, 193, 186, 0.88);
--color-sidebar-item-hover: rgba(239, 238, 234, 0.82);
--color-sidebar-item-active: rgba(239, 238, 234, 0.94);
--color-sidebar-item-active-border: rgba(143, 72, 47, 0.12);
--sidebar-panel-bg-image: none;
--color-sidebar-search-bg: rgba(255, 255, 255, 0.03);
--color-sidebar-search-border: rgba(255, 255, 255, 0.06);
--color-sidebar-item-hover: rgba(255, 255, 255, 0.04);
--color-sidebar-item-active: rgba(255, 255, 255, 0.07);
--color-sidebar-item-active-border: rgba(197, 165, 114, 0.18);
--sidebar-panel-bg-image:
radial-gradient(circle at top left, rgba(197, 165, 114, 0.04), transparent 38%),
linear-gradient(180deg, rgba(255, 255, 255, 0.015), rgba(255, 255, 255, 0));
/* Border aliases */
--color-border: var(--color-outline-variant);
--color-border: rgba(255, 255, 255, 0.08);
--color-border-focus: var(--color-primary);
--color-border-separator: var(--color-outline-variant);
--color-border-separator: rgba(255, 255, 255, 0.06);
/* Text aliases */
--color-text-primary: var(--color-on-surface);
--color-text-secondary: var(--color-on-surface-variant);
--color-text-tertiary: var(--color-outline);
--color-text-tertiary: #8B8B92;
/* Info surface (for team status bar, notifications) */
--color-surface-info: var(--color-surface-container-low);
/* Info surface */
--color-surface-info: rgba(20, 20, 24, 0.88);
/* Brand & accents */
--color-brand: var(--color-primary);
--color-text-accent: var(--color-secondary);
--color-text-accent: var(--color-primary);
/* Shadows */
--shadow-dropdown: 0 4px 20px rgba(27, 28, 26, 0.04), 0 12px 40px rgba(27, 28, 26, 0.08);
/* Shadows — soft ambient, deeper for floaty cards */
--shadow-dropdown: 0 8px 24px rgba(0, 0, 0, 0.40), 0 24px 60px rgba(0, 0, 0, 0.50);
--shadow-sidebar-filter: none;
--shadow-focus-ring: 0 0 0 1px rgba(143, 72, 47, 0.16);
--shadow-error-ring: 0 0 0 1px rgba(186, 26, 26, 0.18);
--shadow-button-primary: 0 8px 24px rgba(143, 72, 47, 0.18);
--shadow-focus-ring: 0 0 0 1px rgba(197, 165, 114, 0.40);
--shadow-error-ring: 0 0 0 1px rgba(229, 72, 77, 0.32);
--shadow-button-primary: 0 6px 20px rgba(197, 165, 114, 0.18);
/* Button colors */
/* Button colors — solid gold, no garish gradient */
--color-btn-primary-fg: var(--color-on-primary);
--gradient-btn-primary: linear-gradient(135deg, var(--color-primary), var(--color-primary-container));
--gradient-btn-primary-hover: linear-gradient(135deg, var(--color-primary-container), var(--color-primary));
--gradient-btn-primary: linear-gradient(180deg, var(--color-primary), var(--color-primary-container));
--gradient-btn-primary-hover: linear-gradient(180deg, var(--color-primary-fixed), var(--color-primary));
/* User message bubble */
--color-surface-user-msg: var(--color-surface-container);
--color-surface-user-msg: var(--color-surface-container-high);
/* Glass / overlays */
--color-overlay-scrim: rgba(27, 28, 26, 0.48);
--color-surface-glass: rgba(255, 255, 255, 0.84);
--color-surface-glass-border: rgba(218, 193, 186, 0.22);
--color-overlay-scrim: rgba(0, 0, 0, 0.62);
--color-surface-glass: rgba(20, 20, 24, 0.78);
--color-surface-glass-border: rgba(255, 255, 255, 0.06);
/* Code + diff */
--color-code-bg: #FDFCF9;
--color-code-fg: #24201E;
--color-code-comment: #5C6B7A;
--color-code-string: #437220;
--color-code-keyword: #B8533B;
--color-code-function: #1D5A8C;
--color-code-number: #1B7A6A;
--color-code-property: #7A3E20;
--color-code-type: #7E5520;
--color-code-parameter: #5C3D2E;
--color-code-punctuation: #5C504A;
--color-code-inserted: #1A7F37;
--color-code-deleted: #CF222E;
/* Code + diff (dark) */
--color-code-bg: #0E0E12;
--color-code-fg: #D8D8DC;
--color-code-comment: #6B6B72;
--color-code-string: #98C97A;
--color-code-keyword: #C9A572;
--color-code-function: #82B0F0;
--color-code-number: #7DD3C0;
--color-code-property: #E5BB85;
--color-code-type: #C9A8E0;
--color-code-parameter: #D8D8DC;
--color-code-punctuation: #888892;
--color-code-inserted: #6FCB8B;
--color-code-deleted: #E5848A;
--color-diff-added-bg: #E8F5E2;
--color-diff-added-word: #B8E4A8;
--color-diff-added-gutter: #D4EDCA;
--color-diff-added-text: #1A7F37;
--color-diff-removed-bg: #FDECEA;
--color-diff-removed-word: #F5B8B4;
--color-diff-removed-gutter: #F9D4D0;
--color-diff-removed-text: #CF222E;
--color-diff-highlight-bg: #FFF5D6;
--color-diff-highlight-gutter: #FFECB3;
--color-diff-title-bg: #F4F4F0;
--color-diff-title-color: #87736D;
--color-diff-title-border: #DAC1BA;
--color-diff-added-bg: rgba(46, 168, 110, 0.10);
--color-diff-added-word: rgba(46, 168, 110, 0.22);
--color-diff-added-gutter: rgba(46, 168, 110, 0.16);
--color-diff-added-text: #6FCB8B;
--color-diff-removed-bg: rgba(229, 72, 77, 0.10);
--color-diff-removed-word: rgba(229, 72, 77, 0.22);
--color-diff-removed-gutter: rgba(229, 72, 77, 0.16);
--color-diff-removed-text: #E5848A;
--color-diff-highlight-bg: rgba(197, 165, 114, 0.10);
--color-diff-highlight-gutter: rgba(197, 165, 114, 0.16);
--color-diff-title-bg: var(--color-surface-container-low);
--color-diff-title-color: var(--color-text-tertiary);
--color-diff-title-border: rgba(255, 255, 255, 0.06);
/* Terminal */
--color-terminal-header: #2D2D2D;
--color-terminal-bg: #1E1E1E;
--color-terminal-border: #1A1A1A;
--color-terminal-fg: #D4D4D4;
--color-terminal-muted: #999999;
--color-terminal-accent: #28C840;
--color-terminal-danger: #FF5F57;
--color-terminal-warning: #FEBC2E;
--color-terminal-header: #1A1A1F;
--color-terminal-bg: #0E0E12;
--color-terminal-border: #16161A;
--color-terminal-fg: #D8D8DC;
--color-terminal-muted: #6B6B72;
--color-terminal-accent: #6FCB8B;
--color-terminal-danger: #E5484D;
--color-terminal-warning: #E5A23E;
/* Misc */
--color-window-close-hover: #E81123;
--color-selection-bg: rgba(255, 219, 208, 0.9);
--color-selection-fg: #390C00;
--color-window-close-hover: #C63B44;
--color-selection-bg: rgba(197, 165, 114, 0.28);
--color-selection-fg: #ECECEE;
/* Radii */
--radius-sm: 4px;
@@ -274,132 +278,131 @@
--radius-full: 9999px;
}
[data-theme="dark"] {
color-scheme: dark;
/* ─── Optional Light Theme Override ─────────────────────────────── */
[data-theme="light"] {
color-scheme: light;
--color-primary: #FFB59F;
--color-primary-container: #FF6E40;
--color-primary-fixed: #FFD9CF;
--color-primary-fixed-dim: #FFB59F;
--color-primary: #8E7547;
--color-primary-container: #6F5A35;
--color-primary-fixed: #E0C896;
--color-primary-fixed-dim: #C5A572;
--color-on-primary: #2C120B;
--color-on-surface: #E5E2E1;
--color-on-surface-variant: #B7AAA5;
--color-on-primary: #FFFFFF;
--color-on-surface: #1B1B1F;
--color-on-surface-variant: #5A5A62;
--color-surface: #131313;
--color-surface-bright: #201F1F;
--color-surface-dim: #0E0E0E;
--color-surface-container: #201F1F;
--color-surface-container-low: #1C1B1B;
--color-surface-container-high: #2A2929;
--color-surface-container-highest: #353534;
--color-surface-container-lowest: #0E0E0E;
--color-surface-variant: #252120;
--color-background: #0E0E0E;
--color-surface: #FAFAFB;
--color-surface-bright: #FFFFFF;
--color-surface-dim: #EEEEF0;
--color-surface-container: #F4F4F6;
--color-surface-container-low: #F8F8FA;
--color-surface-container-high: #ECECEF;
--color-surface-container-highest: #E5E5E8;
--color-surface-container-lowest: #FFFFFF;
--color-surface-variant: #ECECEF;
--color-background: #FAFAFB;
--color-outline: #8D7F7A;
--color-outline-variant: #5A4138;
--color-outline: #8B8B92;
--color-outline-variant: rgba(0, 0, 0, 0.08);
--color-secondary: #CDBDFF;
--color-secondary-container: #3A3050;
--color-tertiary: #00DAF3;
--color-tertiary-container: #003D44;
--color-secondary: #5A6B82;
--color-secondary-container: #DDE3EC;
--color-tertiary: #8E7547;
--color-tertiary-container: #F0E5D0;
--color-error: #FFB4AB;
--color-error-container: #93000A;
--color-on-error-container: #FFDAD6;
--color-error: #C92A30;
--color-error-container: #FCD9DA;
--color-on-error-container: #410002;
--color-inverse-surface: #E5E2E1;
--color-inverse-on-surface: #1B1C1A;
--color-inverse-primary: #8F482F;
--color-inverse-surface: #1B1B1F;
--color-inverse-on-surface: #FAFAFB;
--color-inverse-primary: #C5A572;
--color-success: #7EDB8B;
--color-warning: #F7C46C;
--color-success: #2E9F69;
--color-warning: #C9881F;
--color-surface-sidebar: #171615;
--color-surface-hover: var(--color-surface-container-highest);
--color-surface-sidebar: #F4F4F6;
--color-surface-hover: var(--color-surface-container-high);
--color-surface-selected: var(--color-surface-container);
--color-model-option-selected-bg: rgba(255, 181, 159, 0.13);
--color-model-option-selected-border: rgba(255, 181, 159, 0.34);
--color-sidebar-filter-bg: rgba(255, 255, 255, 0.01);
--color-sidebar-filter-border: rgba(255, 255, 255, 0.08);
--color-model-option-selected-bg: rgba(142, 117, 71, 0.10);
--color-model-option-selected-border: rgba(142, 117, 71, 0.28);
--color-sidebar-filter-bg: transparent;
--color-sidebar-filter-border: rgba(0, 0, 0, 0.08);
--color-sidebar-filter-icon-bg: transparent;
--color-sidebar-search-bg: rgba(255, 255, 255, 0.03);
--color-sidebar-search-border: rgba(255, 255, 255, 0.06);
--color-sidebar-item-hover: rgba(255, 255, 255, 0.04);
--color-sidebar-item-active: rgba(255, 255, 255, 0.06);
--color-sidebar-item-active-border: rgba(255, 181, 159, 0.14);
--sidebar-panel-bg-image:
radial-gradient(circle at top left, rgba(255, 181, 159, 0.045), transparent 34%),
linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0));
--color-sidebar-search-bg: rgba(255, 255, 255, 0.85);
--color-sidebar-search-border: rgba(0, 0, 0, 0.08);
--color-sidebar-item-hover: rgba(0, 0, 0, 0.03);
--color-sidebar-item-active: rgba(0, 0, 0, 0.05);
--color-sidebar-item-active-border: rgba(142, 117, 71, 0.16);
--sidebar-panel-bg-image: none;
--color-border: rgba(90, 65, 56, 0.18);
--color-border-focus: rgba(255, 181, 159, 0.55);
--color-border-separator: rgba(90, 65, 56, 0.12);
--color-border: rgba(0, 0, 0, 0.08);
--color-border-focus: var(--color-primary);
--color-border-separator: rgba(0, 0, 0, 0.06);
--color-text-primary: var(--color-on-surface);
--color-text-secondary: var(--color-on-surface-variant);
--color-text-tertiary: #8F827D;
--color-text-tertiary: #8B8B92;
--color-surface-info: rgba(32, 31, 31, 0.88);
--color-surface-info: var(--color-surface-container-low);
--color-brand: var(--color-primary);
--color-text-accent: var(--color-tertiary);
--color-text-accent: var(--color-secondary);
--shadow-dropdown: 0 16px 40px rgba(0, 0, 0, 0.42);
--shadow-dropdown: 0 4px 20px rgba(0, 0, 0, 0.04), 0 12px 40px rgba(0, 0, 0, 0.08);
--shadow-sidebar-filter: none;
--shadow-focus-ring: 0 0 0 1px rgba(255, 181, 159, 0.32);
--shadow-error-ring: 0 0 0 1px rgba(255, 180, 171, 0.26);
--shadow-button-primary: 0 12px 24px rgba(255, 110, 64, 0.18);
--shadow-focus-ring: 0 0 0 1px rgba(142, 117, 71, 0.28);
--shadow-error-ring: 0 0 0 1px rgba(201, 42, 48, 0.20);
--shadow-button-primary: 0 6px 20px rgba(142, 117, 71, 0.20);
--gradient-btn-primary: linear-gradient(135deg, var(--color-primary), var(--color-primary-container));
--gradient-btn-primary-hover: linear-gradient(135deg, var(--color-primary-container), var(--color-primary));
--color-btn-primary-fg: var(--color-on-primary);
--gradient-btn-primary: linear-gradient(180deg, var(--color-primary), var(--color-primary-container));
--gradient-btn-primary-hover: linear-gradient(180deg, var(--color-primary-fixed-dim), var(--color-primary));
--color-surface-user-msg: rgba(32, 31, 31, 0.92);
--color-surface-user-msg: var(--color-surface-container);
--color-overlay-scrim: rgba(20, 20, 24, 0.50);
--color-surface-glass: rgba(255, 255, 255, 0.85);
--color-surface-glass-border: rgba(0, 0, 0, 0.06);
--color-overlay-scrim: rgba(6, 6, 6, 0.56);
--color-surface-glass: rgba(32, 31, 31, 0.8);
--color-surface-glass-border: rgba(90, 65, 56, 0.18);
--color-code-bg: #FAFAFB;
--color-code-fg: #1B1B1F;
--color-code-comment: #6B6B72;
--color-code-string: #2E7A3E;
--color-code-keyword: #8E5530;
--color-code-function: #1D5A8C;
--color-code-number: #1B7A6A;
--color-code-property: #7A4E20;
--color-code-type: #5E3F8C;
--color-code-parameter: #1B1B1F;
--color-code-punctuation: #6B6B72;
--color-code-inserted: #2E9F69;
--color-code-deleted: #C92A30;
--color-code-bg: #0E0E0E;
--color-code-fg: #E5E2E1;
--color-code-comment: #8F8683;
--color-code-string: #88C988;
--color-code-keyword: #FF8F70;
--color-code-function: #00DAF3;
--color-code-number: #74E0F7;
--color-code-property: #FFC9B8;
--color-code-type: #CDBDFF;
--color-code-parameter: #E5E2E1;
--color-code-punctuation: #9B908C;
--color-code-inserted: #8EEA9A;
--color-code-deleted: #FFB59F;
--color-diff-added-bg: rgba(126, 219, 139, 0.12);
--color-diff-added-word: rgba(126, 219, 139, 0.22);
--color-diff-added-gutter: rgba(126, 219, 139, 0.18);
--color-diff-added-text: #8EEA9A;
--color-diff-removed-bg: rgba(255, 110, 64, 0.12);
--color-diff-removed-word: rgba(255, 110, 64, 0.24);
--color-diff-removed-gutter: rgba(255, 110, 64, 0.18);
--color-diff-removed-text: #FFB59F;
--color-diff-highlight-bg: rgba(205, 189, 255, 0.12);
--color-diff-highlight-gutter: rgba(205, 189, 255, 0.16);
--color-diff-added-bg: #E8F5E2;
--color-diff-added-word: #B8E4A8;
--color-diff-added-gutter: #D4EDCA;
--color-diff-added-text: #2E9F69;
--color-diff-removed-bg: #FDECEA;
--color-diff-removed-word: #F5B8B4;
--color-diff-removed-gutter: #F9D4D0;
--color-diff-removed-text: #C92A30;
--color-diff-highlight-bg: #FFF5D6;
--color-diff-highlight-gutter: #FFECB3;
--color-diff-title-bg: var(--color-surface-container-low);
--color-diff-title-color: var(--color-text-tertiary);
--color-diff-title-border: rgba(90, 65, 56, 0.15);
--color-diff-title-border: rgba(0, 0, 0, 0.06);
--color-terminal-header: #242323;
--color-terminal-bg: #121212;
--color-terminal-border: #1A1919;
--color-terminal-fg: #D7D2D0;
--color-terminal-muted: #8F8683;
--color-terminal-accent: #7EF18A;
--color-terminal-danger: #FF6D67;
--color-terminal-warning: #F8C55F;
--color-terminal-header: #2D2D2D;
--color-terminal-bg: #1E1E1E;
--color-terminal-border: #1A1A1A;
--color-terminal-fg: #D4D4D4;
--color-terminal-muted: #999999;
--color-terminal-accent: #28C840;
--color-terminal-danger: #FF5F57;
--color-terminal-warning: #FEBC2E;
--color-window-close-hover: #C63B44;
--color-selection-bg: rgba(255, 181, 159, 0.32);
--color-selection-fg: #FBE7E1;
--color-window-close-hover: #E81123;
--color-selection-bg: rgba(197, 165, 114, 0.30);
--color-selection-fg: #1B1B1F;
}
/* ─── Material Symbols ─────────────────────────────────────────── */
@@ -33,26 +33,5 @@
"API_TIMEOUT_MS": "3000000",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
}
},
{
"id": "clawdrouter",
"name": "ClawdRouter",
"baseUrl": "https://api.clawdrouter.com",
"apiFormat": "anthropic",
"defaultModels": {
"main": "claude-sonnet-4-6",
"haiku": "claude-haiku-4-5-20251001",
"sonnet": "claude-sonnet-4-6",
"opus": "claude-opus-4-6"
},
"needsApiKey": true,
"websiteUrl": "https://www.clawdrouter.com",
"apiKeyUrl": "https://www.clawdrouter.com/dashboard/keys",
"promoText": "ClawdRouter 双协议聚合网关,同时支持 Anthropic /v1/messages 与 OpenAI /v1/chat/completions,覆盖 OpenAI / Anthropic / Google 全家桶。",
"featured": true,
"defaultEnv": {
"API_TIMEOUT_MS": "3000000",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
}
}
]
+4 -19
View File
@@ -316,7 +316,10 @@ export class ProviderService {
source: 'cc-haha-provider' | 'original-settings' | 'env' | 'none'
activeProvider?: string
}> {
// 1. Check cc-haha active provider
// Heicode 只认通过登录页拿到的 provider 凭据。
// 不再 fallback 到 ~/.claude/settings.json 或 ANTHROPIC_* 环境变量 ——
// 用户必须显式走一次 Heicode 登录流程(TaijiAICloud),避免 Claude Code CLI 老用户
// 因系统里残留 token 被误判为已登录。
const index = await this.readIndex()
if (index.activeId) {
const provider = index.providers.find(p => p.id === index.activeId)
@@ -325,24 +328,6 @@ export class ProviderService {
}
}
// 2. Check process.env (covers .env file + inherited env)
if (process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN) {
return { hasAuth: true, source: 'env' }
}
// 3. Check original ~/.claude/settings.json
try {
const originalPath = path.join(this.getConfigDir(), 'settings.json')
const raw = await fs.readFile(originalPath, 'utf-8')
const settings = JSON.parse(raw) as { env?: Record<string, string> }
const env = settings.env ?? {}
if (env.ANTHROPIC_AUTH_TOKEN || env.ANTHROPIC_API_KEY) {
return { hasAuth: true, source: 'original-settings' }
}
} catch {
// File doesn't exist or invalid
}
return { hasAuth: false, source: 'none' }
}