mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
feat(desktop): add About page in settings with app info and author links
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8617a4b9c9
commit
bd604429ec
1
desktop/public/icons/bilibili.svg
Normal file
1
desktop/public/icons/bilibili.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M17.813 4.653h.854c1.51.054 2.769.578 3.773 1.574 1.004.995 1.524 2.249 1.56 3.76v7.36c-.036 1.51-.556 2.769-1.56 3.773s-2.262 1.524-3.773 1.56H5.333c-1.51-.036-2.769-.556-3.773-1.56S.036 18.858 0 17.347v-7.36c.036-1.511.556-2.765 1.56-3.76 1.004-.996 2.262-1.52 3.773-1.574h.774l-1.174-1.12a1.234 1.234 0 0 1-.373-.906c0-.356.124-.658.373-.907l.027-.027c.267-.249.573-.373.92-.373.347 0 .653.124.92.373L9.653 4.44c.071.071.134.142.187.213h4.267a.836.836 0 0 1 .16-.213l2.853-2.747c.267-.249.573-.373.92-.373.347 0 .662.151.929.4.267.249.391.551.391.907 0 .355-.124.657-.373.906zM5.333 7.24c-.746.018-1.373.276-1.88.773-.506.498-.769 1.13-.786 1.894v7.52c.017.764.28 1.395.786 1.893.507.498 1.134.756 1.88.773h13.334c.746-.017 1.373-.275 1.88-.773.506-.498.769-1.129.786-1.893v-7.52c-.017-.765-.28-1.396-.786-1.894-.507-.497-1.134-.755-1.88-.773zM8 11.107c.373 0 .684.124.933.373.25.249.383.569.4.96v1.173c-.017.391-.15.711-.4.96-.249.25-.56.374-.933.374s-.684-.125-.933-.374c-.25-.249-.383-.569-.4-.96V12.44c0-.373.129-.689.386-.947.258-.257.574-.386.947-.386zm8 0c.373 0 .684.124.933.373.25.249.383.569.4.96v1.173c-.017.391-.15.711-.4.96-.249.25-.56.374-.933.374s-.684-.125-.933-.374c-.25-.249-.383-.569-.4-.96V12.44c.017-.391.15-.711.4-.96.249-.249.56-.373.933-.373Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
desktop/public/icons/douyin.svg
Normal file
1
desktop/public/icons/douyin.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><title>Douyin</title><path d="M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z"/></svg>
|
||||
|
After Width: | Height: | Size: 728 B |
3
desktop/public/icons/github.svg
Normal file
3
desktop/public/icons/github.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor">
|
||||
<path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 697 B |
1
desktop/public/icons/xiaohongshu.svg
Normal file
1
desktop/public/icons/xiaohongshu.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M22.405 9.879c.002.016.01.02.07.019h.725a.797.797 0 0 0 .78-.972.794.794 0 0 0-.884-.618.795.795 0 0 0-.692.794c0 .101-.002.666.001.777zm-11.509 4.808c-.203.001-1.353.004-1.685.003a2.528 2.528 0 0 1-.766-.126.025.025 0 0 0-.03.014L7.7 16.127a.025.025 0 0 0 .01.032c.111.06.336.124.495.124.66.01 1.32.002 1.981 0 .01 0 .02-.006.023-.015l.712-1.545a.025.025 0 0 0-.024-.036zM.477 9.91c-.071 0-.076.002-.076.01a.834.834 0 0 0-.01.08c-.027.397-.038.495-.234 3.06-.012.24-.034.389-.135.607-.026.057-.033.042.003.112.046.092.681 1.523.787 1.74.008.015.011.02.017.02.008 0 .033-.026.047-.044.147-.187.268-.391.371-.606.306-.635.44-1.325.486-1.706.014-.11.021-.22.03-.33l.204-2.616.022-.293c.003-.029 0-.033-.03-.034zm7.203 3.757a1.427 1.427 0 0 1-.135-.607c-.004-.084-.031-.39-.235-3.06a.443.443 0 0 0-.01-.082c-.004-.011-.052-.008-.076-.008h-1.48c-.03.001-.034.005-.03.034l.021.293c.076.982.153 1.964.233 2.946.05.4.186 1.085.487 1.706.103.215.223.419.37.606.015.018.037.051.048.049.02-.003.742-1.642.804-1.765.036-.07.03-.055.003-.112zm3.861-.913h-.872a.126.126 0 0 1-.116-.178l1.178-2.625a.025.025 0 0 0-.023-.035l-1.318-.003a.148.148 0 0 1-.135-.21l.876-1.954a.025.025 0 0 0-.023-.035h-1.56c-.01 0-.02.006-.024.015l-.926 2.068c-.085.169-.314.634-.399.938a.534.534 0 0 0-.02.191.46.46 0 0 0 .23.378.981.981 0 0 0 .46.119h.59c.041 0-.688 1.482-.834 1.972a.53.53 0 0 0-.023.172.465.465 0 0 0 .23.398c.15.092.342.12.475.12l1.66-.001c.01 0 .02-.006.023-.015l.575-1.28a.025.025 0 0 0-.024-.035zm-6.93-4.937H3.1a.032.032 0 0 0-.034.033c0 1.048-.01 2.795-.01 6.829 0 .288-.269.262-.28.262h-.74c-.04.001-.044.004-.04.047.001.037.465 1.064.555 1.263.01.02.03.033.051.033.157.003.767.009.938-.014.153-.02.3-.06.438-.132.3-.156.49-.419.595-.765.052-.172.075-.353.075-.533.002-2.33 0-4.66-.007-6.991a.032.032 0 0 0-.032-.032zm11.784 6.896c0-.014-.01-.021-.024-.022h-1.465c-.048-.001-.049-.002-.05-.049v-4.66c0-.072-.005-.07.07-.07h.863c.08 0 .075.004.075-.074V8.393c0-.082.006-.076-.08-.076h-3.5c-.064 0-.075-.006-.075.073v1.445c0 .083-.006.077.08.077h.854c.075 0 .07-.004.07.07v4.624c0 .095.008.084-.085.084-.37 0-1.11-.002-1.304 0-.048.001-.06.03-.06.03l-.697 1.519s-.014.025-.008.036c.006.01.013.008.058.008 1.748.003 3.495.002 5.243.002.03-.001.034-.006.035-.033v-1.539zm4.177-3.43c0 .013-.007.023-.02.024-.346.006-.692.004-1.037.004-.014-.002-.022-.01-.022-.024-.005-.434-.007-.869-.01-1.303 0-.072-.006-.071.07-.07l.733-.003c.041 0 .081.002.12.015.093.025.16.107.165.204.006.431.002 1.153.001 1.153zm2.67.244a1.953 1.953 0 0 0-.883-.222h-.18c-.04-.001-.04-.003-.042-.04V10.21c0-.132-.007-.263-.025-.394a1.823 1.823 0 0 0-.153-.53 1.533 1.533 0 0 0-.677-.71 2.167 2.167 0 0 0-1-.258c-.153-.003-.567 0-.72 0-.07 0-.068.004-.068-.065V7.76c0-.031-.01-.041-.046-.039H17.93s-.016 0-.023.007c-.006.006-.008.012-.008.023v.546c-.008.036-.057.015-.082.022h-.95c-.022.002-.028.008-.03.032v1.481c0 .09-.004.082.082.082h.913c.082 0 .072.128.072.128V11.19s.003.117-.06.117h-1.482c-.068 0-.06.082-.06.082v1.445s-.01.068.064.068h1.457c.082 0 .076-.006.076.079v3.225c0 .088-.007.081.082.081h1.43c.09 0 .082.007.082-.08v-3.27c0-.029.006-.035.033-.035l2.323-.003c.098 0 .191.02.28.061a.46.46 0 0 1 .274.407c.008.395.003.79.003 1.185 0 .259-.107.367-.33.367h-1.218c-.023.002-.029.008-.028.033.184.437.374.871.57 1.303a.045.045 0 0 0 .04.026c.17.005.34.002.51.003.15-.002.517.004.666-.01a2.03 2.03 0 0 0 .408-.075c.59-.18.975-.698.976-1.313v-1.981c0-.128-.01-.254-.034-.38 0 .078-.029-.641-.724-.998z"/></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@ -224,6 +224,14 @@ export const en = {
|
||||
'settings.skills.source.mcp': 'MCP',
|
||||
'settings.skills.source.bundled': 'Built-in',
|
||||
|
||||
// Settings > About
|
||||
'settings.tab.about': 'About',
|
||||
'settings.about.version': 'Version',
|
||||
'settings.about.repo': 'GitHub Repository',
|
||||
'settings.about.starHint': 'If this project helps you, consider giving it a Star',
|
||||
'settings.about.author': 'Author',
|
||||
'settings.about.socialMedia': 'Social Media',
|
||||
|
||||
// Settings > General
|
||||
'settings.general.languageTitle': 'Language',
|
||||
'settings.general.languageDescription': 'Choose the display language for the application.',
|
||||
|
||||
@ -226,6 +226,14 @@ export const zh: Record<TranslationKey, string> = {
|
||||
'settings.skills.source.mcp': 'MCP',
|
||||
'settings.skills.source.bundled': '内置',
|
||||
|
||||
// Settings > About
|
||||
'settings.tab.about': '关于',
|
||||
'settings.about.version': '版本',
|
||||
'settings.about.repo': 'GitHub 仓库',
|
||||
'settings.about.starHint': '如果这个项目对你有帮助,欢迎给个 Star',
|
||||
'settings.about.author': '作者',
|
||||
'settings.about.socialMedia': '社交媒体',
|
||||
|
||||
// Settings > General
|
||||
'settings.general.languageTitle': '语言',
|
||||
'settings.general.languageDescription': '选择应用程序的显示语言。',
|
||||
|
||||
@ -19,7 +19,7 @@ import { useSkillStore } from '../stores/skillStore'
|
||||
import { SkillList } from '../components/skills/SkillList'
|
||||
import { SkillDetail } from '../components/skills/SkillDetail'
|
||||
|
||||
type SettingsTab = 'providers' | 'permissions' | 'general' | 'adapters' | 'agents' | 'skills'
|
||||
type SettingsTab = 'providers' | 'permissions' | 'general' | 'adapters' | 'agents' | 'skills' | 'about'
|
||||
|
||||
export function Settings() {
|
||||
const [activeTab, setActiveTab] = useState<SettingsTab>('providers')
|
||||
@ -29,13 +29,18 @@ export function Settings() {
|
||||
<div className="flex-1 flex flex-col overflow-hidden bg-[var(--color-surface)]">
|
||||
<div className="flex-1 flex overflow-hidden">
|
||||
{/* Tab navigation */}
|
||||
<div className="w-[180px] border-r border-[var(--color-border)] py-3 flex-shrink-0">
|
||||
<TabButton icon="dns" label={t('settings.tab.providers')} active={activeTab === 'providers'} onClick={() => setActiveTab('providers')} />
|
||||
<TabButton icon="shield" label={t('settings.tab.permissions')} active={activeTab === 'permissions'} onClick={() => setActiveTab('permissions')} />
|
||||
<TabButton icon="tune" label={t('settings.tab.general')} active={activeTab === 'general'} onClick={() => setActiveTab('general')} />
|
||||
<TabButton icon="chat" label={t('settings.tab.adapters')} active={activeTab === 'adapters'} onClick={() => setActiveTab('adapters')} />
|
||||
<TabButton icon="smart_toy" label={t('settings.tab.agents')} active={activeTab === 'agents'} onClick={() => setActiveTab('agents')} />
|
||||
<TabButton icon="auto_awesome" label={t('settings.tab.skills')} active={activeTab === 'skills'} onClick={() => setActiveTab('skills')} />
|
||||
<div className="w-[180px] border-r border-[var(--color-border)] py-3 flex-shrink-0 flex flex-col">
|
||||
<div className="flex-1">
|
||||
<TabButton icon="dns" label={t('settings.tab.providers')} active={activeTab === 'providers'} onClick={() => setActiveTab('providers')} />
|
||||
<TabButton icon="shield" label={t('settings.tab.permissions')} active={activeTab === 'permissions'} onClick={() => setActiveTab('permissions')} />
|
||||
<TabButton icon="tune" label={t('settings.tab.general')} active={activeTab === 'general'} onClick={() => setActiveTab('general')} />
|
||||
<TabButton icon="chat" label={t('settings.tab.adapters')} active={activeTab === 'adapters'} onClick={() => setActiveTab('adapters')} />
|
||||
<TabButton icon="smart_toy" label={t('settings.tab.agents')} active={activeTab === 'agents'} onClick={() => setActiveTab('agents')} />
|
||||
<TabButton icon="auto_awesome" label={t('settings.tab.skills')} active={activeTab === 'skills'} onClick={() => setActiveTab('skills')} />
|
||||
</div>
|
||||
<div className="border-t border-[var(--color-border)]/40 pt-1">
|
||||
<TabButton icon="info" label={t('settings.tab.about')} active={activeTab === 'about'} onClick={() => setActiveTab('about')} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tab content */}
|
||||
@ -46,6 +51,7 @@ export function Settings() {
|
||||
{activeTab === 'adapters' && <AdapterSettings />}
|
||||
{activeTab === 'agents' && <AgentsSettings />}
|
||||
{activeTab === 'skills' && <SkillSettings />}
|
||||
{activeTab === 'about' && <AboutSettings />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1178,3 +1184,94 @@ function SkillSettings() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ─── About Settings ──────────────────────────────────────
|
||||
|
||||
const GITHUB_REPO = 'https://github.com/NanmiCoder/cc-haha'
|
||||
const AUTHOR_GITHUB = 'https://github.com/NanmiCoder'
|
||||
const SOCIAL_LINKS = [
|
||||
{ name: 'Bilibili', icon: '/icons/bilibili.svg', url: 'https://space.bilibili.com/434377496', label: '程序员阿江-Relakkes' },
|
||||
{ name: 'Douyin', icon: '/icons/douyin.svg', url: 'https://www.douyin.com/user/MS4wLjABAAAATJPY7LAlaa5X-c8uNdWkvz0jUGgpw4eeXIwu_8BhvqE', label: '程序员阿江-Relakkes' },
|
||||
{ name: 'Xiaohongshu', icon: '/icons/xiaohongshu.svg', url: 'https://www.xiaohongshu.com/user/profile/5f58bd990000000001003753', label: '程序员阿江-Relakkes' },
|
||||
] as const
|
||||
|
||||
function AboutSettings() {
|
||||
const t = useTranslation()
|
||||
const [version, setVersion] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
import('@tauri-apps/api/app').then((mod) => mod.getVersion()).then(setVersion).catch(() => setVersion('0.1.0'))
|
||||
}, [])
|
||||
|
||||
const openUrl = (url: string) => {
|
||||
import('@tauri-apps/plugin-shell').then((mod) => mod.open(url)).catch(() => window.open(url, '_blank'))
|
||||
}
|
||||
|
||||
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.jpg" alt="Claude Code Haha" className="w-20 h-20 rounded-2xl shadow-md mb-4" />
|
||||
<h1 className="text-xl font-bold text-[var(--color-text-primary)]">Claude Code Haha</h1>
|
||||
{version && (
|
||||
<span className="text-xs text-[var(--color-text-tertiary)] mt-1">{t('settings.about.version')} {version}</span>
|
||||
)}
|
||||
|
||||
{/* GitHub Repo */}
|
||||
<div className="mt-6 w-full">
|
||||
<button
|
||||
onClick={() => openUrl(GITHUB_REPO)}
|
||||
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl border border-[var(--color-border)] hover:bg-[var(--color-surface-hover)] transition-colors cursor-pointer"
|
||||
>
|
||||
<img src="/icons/github.svg" alt="GitHub" className="w-5 h-5 opacity-70" />
|
||||
<div className="flex-1 text-left">
|
||||
<div className="text-sm font-medium text-[var(--color-text-primary)]">NanmiCoder/cc-haha</div>
|
||||
<div className="text-xs text-[var(--color-text-tertiary)]">{t('settings.about.starHint')}</div>
|
||||
</div>
|
||||
<span className="material-symbols-outlined text-[16px] text-[var(--color-text-tertiary)]">open_in_new</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="w-full border-t border-[var(--color-border)]/40 my-6" />
|
||||
|
||||
{/* Author */}
|
||||
<div className="w-full">
|
||||
<h3 className="text-xs font-medium text-[var(--color-text-tertiary)] uppercase tracking-wider mb-3">{t('settings.about.author')}</h3>
|
||||
<button
|
||||
onClick={() => openUrl(AUTHOR_GITHUB)}
|
||||
className="w-full flex items-center gap-3 px-4 py-2.5 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors cursor-pointer"
|
||||
>
|
||||
<img src="/icons/github.svg" alt="GitHub" className="w-4 h-4 opacity-60" />
|
||||
<span className="text-sm text-[var(--color-text-primary)]">程序员阿江-Relakkes</span>
|
||||
<span className="text-xs text-[var(--color-text-tertiary)] ml-auto">GitHub</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Social Media */}
|
||||
<div className="w-full mt-4">
|
||||
<h3 className="text-xs font-medium text-[var(--color-text-tertiary)] uppercase tracking-wider mb-3">{t('settings.about.socialMedia')}</h3>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
{SOCIAL_LINKS.map((link) => (
|
||||
<button
|
||||
key={link.name}
|
||||
onClick={() => openUrl(link.url)}
|
||||
className="w-full flex items-center gap-3 px-4 py-2.5 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors cursor-pointer"
|
||||
>
|
||||
<img src={link.icon} alt={link.name} className="w-4 h-4 opacity-60" />
|
||||
<span className="text-sm text-[var(--color-text-primary)]">{link.label}</span>
|
||||
<span className="text-xs text-[var(--color-text-tertiary)] ml-auto">{link.name}</span>
|
||||
</button>
|
||||
))}
|
||||
<button
|
||||
onClick={() => openUrl('mailto:relakkes@gmail.com')}
|
||||
className="w-full flex items-center gap-3 px-4 py-2.5 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors cursor-pointer"
|
||||
>
|
||||
<span className="material-symbols-outlined text-[16px] opacity-60">mail</span>
|
||||
<span className="text-sm text-[var(--color-text-primary)]">relakkes@gmail.com</span>
|
||||
<span className="text-xs text-[var(--color-text-tertiary)] ml-auto">Email</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user