Skip to content

Commit 151d092

Browse files
committed
feat: add GitHub link component and update README with floating buddies preview
1 parent feac3d2 commit 151d092

7 files changed

Lines changed: 63 additions & 16 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Vibebud gives your coding agents a visible presence: a floating companion on you
1818

1919
Instead of letting AI agent work disappear into terminals, logs, and background processes, Vibebud makes it feel present and easy to follow.
2020

21-
> Screenshot coming soon. For now: imagine a small animated avatar in the corner of your screen, blinking at you, occasionally popping a chat bubble.
21+
![Vibebud floating buddies preview](./assets/buds.png)
2222

2323
## The Idea
2424

README.zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Vibebud 会给你的 AI 编程智能体一个可见的存在感:它可以作
1717

1818
AI 智能体的工作不应该只藏在终端、日志和后台进程里。Vibebud 想让这些工作变得更可见、更容易跟进,也更有陪伴感。
1919

20-
> 截图即将补充。现在你可以先想象一个小小的动画头像待在屏幕角落,偶尔眨眨眼,弹出一个聊天气泡。
20+
![Vibebud 漂浮小伙伴预览](./assets/buds.png)
2121

2222
## 核心想法
2323

assets/buds.png

47.4 KB
Loading

core/app/components/Buddy.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import BuddyInstance, { type BuddyInstanceState } from './BuddyInstance';
55
import BuddyGroup from './BuddyGroup';
66
import AppSettings from './AppSettings';
77
import LanguageSelector from './LanguageSelector';
8+
import GitHubLink from './GitHubLink';
89
import SignInStatus from './SignInStatus';
910
import { VARIANTS } from './avatars';
1011
import { normalizeGamification } from './gamification';
@@ -1934,6 +1935,7 @@ export default function Buddy() {
19341935
in the in-app Capacitor BridgeActivity WebView and the web build. */}
19351936
{adapter.id !== 'electron' && !isAndroidOverlay && (
19361937
<div className="fixed right-3 top-3 z-[70] flex items-center gap-2">
1938+
<GitHubLink />
19371939
<LanguageSelector />
19381940
<SignInStatus />
19391941
{/* QR shortcut: triggers the same scanQrForPair as AppSettings,

core/app/components/GitHubLink.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
import { useTranslations } from '../../lib/hooks/use-translations';
5+
6+
const GITHUB_REPO_URL = 'https://github.com/shellishack/vibebud';
7+
const GITHUB_REPO_API_URL = 'https://api.github.com/repos/shellishack/vibebud';
8+
9+
function formatStars(count: number) {
10+
if (count >= 1000) {
11+
const rounded = Math.round(count / 100) / 10;
12+
return `${Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(1)}k`;
13+
}
14+
return String(count);
15+
}
16+
17+
export default function GitHubLink() {
18+
const { t } = useTranslations();
19+
const [stars, setStars] = useState<number | null>(null);
20+
21+
useEffect(() => {
22+
let cancelled = false;
23+
fetch(GITHUB_REPO_API_URL)
24+
.then((res) => res.ok ? res.json() : null)
25+
.then((data: { stargazers_count?: unknown } | null) => {
26+
if (cancelled || typeof data?.stargazers_count !== 'number') return;
27+
setStars(data.stargazers_count);
28+
})
29+
.catch(() => {});
30+
return () => { cancelled = true; };
31+
}, []);
32+
33+
return (
34+
<a
35+
data-buddy-interactive
36+
href={GITHUB_REPO_URL}
37+
target="_blank"
38+
rel="noreferrer"
39+
className="inline-flex h-9 items-center gap-2 rounded-full bg-white/85 px-3 text-sm font-medium text-zinc-600 shadow-md ring-1 ring-zinc-200 backdrop-blur-md hover:bg-white hover:text-zinc-900 dark:bg-zinc-900/85 dark:text-zinc-300 dark:ring-zinc-700 dark:hover:bg-zinc-800 dark:hover:text-zinc-50"
40+
>
41+
<svg viewBox="0 0 24 24" className="h-4 w-4 shrink-0" fill="currentColor" aria-hidden>
42+
<path fillRule="evenodd" clipRule="evenodd" d="M12 2C6.48 2 2 6.58 2 12.22c0 4.51 2.87 8.34 6.84 9.69.5.09.68-.22.68-.49 0-.24-.01-1.04-.01-1.89-2.78.62-3.37-1.22-3.37-1.22-.45-1.18-1.11-1.49-1.11-1.49-.91-.64.07-.63.07-.63 1 .07 1.53 1.05 1.53 1.05.89 1.56 2.34 1.11 2.91.85.09-.66.35-1.11.63-1.36-2.22-.26-4.56-1.14-4.56-5.06 0-1.12.39-2.03 1.03-2.75-.1-.26-.45-1.3.1-2.71 0 0 .84-.28 2.75 1.05A9.28 9.28 0 0 1 12 6.92c.85 0 1.7.12 2.5.34 1.91-1.33 2.75-1.05 2.75-1.05.55 1.41.2 2.45.1 2.71.64.72 1.03 1.63 1.03 2.75 0 3.93-2.34 4.8-4.57 5.06.36.32.68.94.68 1.9 0 1.37-.01 2.48-.01 2.82 0 .27.18.59.69.49A10.15 10.15 0 0 0 22 12.22C22 6.58 17.52 2 12 2Z" />
43+
</svg>
44+
<span>{t('home.github')}</span>
45+
<span className="h-4 w-px bg-zinc-200 dark:bg-zinc-700" />
46+
<span className="inline-flex items-center gap-1 text-zinc-500 dark:text-zinc-400">
47+
<svg viewBox="0 0 24 24" className="h-3.5 w-3.5" fill="currentColor" aria-hidden>
48+
<path d="m12 2.25 2.94 5.96 6.58.96-4.76 4.64 1.12 6.55L12 17.27l-5.88 3.09 1.12-6.55-4.76-4.64 6.58-.96L12 2.25Z" />
49+
</svg>
50+
{stars === null ? 'Stars' : formatStars(stars)}
51+
</span>
52+
</a>
53+
);
54+
}

core/app/components/InstallButton.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { usePlatform } from './hooks/usePlatform';
1111

1212
type Target = { id: string; label: string; href: string; ext: string; directDownload?: boolean };
1313

14-
const LATEST_RELEASE_URL = 'https://github.com/Shellishack/vibemoji/releases/latest';
14+
const LATEST_RELEASE_URL = 'https://github.com/shellishack/vibebud/releases/latest';
1515
const LATEST_RELEASE_DOWNLOAD_URL = `${LATEST_RELEASE_URL}/download`;
1616

1717
const TARGETS: Target[] = [
@@ -52,11 +52,13 @@ export default function InstallButton() {
5252
const { t } = useTranslations();
5353
const adapter = usePlatform();
5454
const insideElectron = adapter.id === 'electron';
55-
const [target, setTarget] = useState<Target>(TARGETS[0]);
55+
const [detectedTarget, setDetectedTarget] = useState<Target | null>(null);
5656
const [open, setOpen] = useState(false);
57+
const target = detectedTarget ?? TARGETS[0];
5758

5859
useEffect(() => {
59-
setTarget(detectTarget());
60+
const id = window.setTimeout(() => setDetectedTarget(detectTarget()), 0);
61+
return () => window.clearTimeout(id);
6062
}, []);
6163

6264
const handleDownload = () => {

core/app/page.tsx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,6 @@ export default function Home() {
4141
>
4242
{t('home.manageAvatars')}
4343
</Link>
44-
<a
45-
href="https://github.com/shellishack/vibebud"
46-
target="_blank"
47-
rel="noreferrer"
48-
className="inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-white/70 px-4 py-2 text-sm font-medium text-zinc-700 backdrop-blur transition-colors hover:border-zinc-300 hover:bg-white dark:border-zinc-700 dark:bg-zinc-900/60 dark:text-zinc-200 dark:hover:border-zinc-500"
49-
>
50-
<svg viewBox="0 0 24 24" className="h-4 w-4" fill="currentColor" aria-hidden>
51-
<path fillRule="evenodd" clipRule="evenodd" d="M12 2C6.48 2 2 6.58 2 12.22c0 4.51 2.87 8.34 6.84 9.69.5.09.68-.22.68-.49 0-.24-.01-1.04-.01-1.89-2.78.62-3.37-1.22-3.37-1.22-.45-1.18-1.11-1.49-1.11-1.49-.91-.64.07-.63.07-.63 1 .07 1.53 1.05 1.53 1.05.89 1.56 2.34 1.11 2.91.85.09-.66.35-1.11.63-1.36-2.22-.26-4.56-1.14-4.56-5.06 0-1.12.39-2.03 1.03-2.75-.1-.26-.45-1.3.1-2.71 0 0 .84-.28 2.75 1.05A9.28 9.28 0 0 1 12 6.92c.85 0 1.7.12 2.5.34 1.91-1.33 2.75-1.05 2.75-1.05.55 1.41.2 2.45.1 2.71.64.72 1.03 1.63 1.03 2.75 0 3.93-2.34 4.8-4.57 5.06.36.32.68.94.68 1.9 0 1.37-.01 2.48-.01 2.82 0 .27.18.59.69.49A10.15 10.15 0 0 0 22 12.22C22 6.58 17.52 2 12 2Z" />
52-
</svg>
53-
{t('home.github')}
54-
</a>
5544
<span className="text-xs text-zinc-500 dark:text-zinc-400">{t('home.downloadMeta')}</span>
5645
</div>
5746

0 commit comments

Comments
 (0)