mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
182 lines
5.0 KiB
TypeScript
182 lines
5.0 KiB
TypeScript
'use client'
|
|
|
|
import React, { useState } from 'react'
|
|
import { Star, Check, ExternalLink } from 'lucide-react'
|
|
import { Text, XStack, YStack } from '@hanzo/ui'
|
|
import { useI18n } from '@hanzo/i18n/react'
|
|
|
|
export interface DualStarButtonProps {
|
|
owner: string
|
|
repo: string
|
|
initialStars?: number
|
|
forgeUrl?: string
|
|
githubUrl?: string
|
|
size?: 'sm' | 'md'
|
|
}
|
|
|
|
export default function DualStarButton({
|
|
owner,
|
|
repo,
|
|
initialStars = 1420,
|
|
forgeUrl,
|
|
githubUrl,
|
|
size = 'md',
|
|
}: DualStarButtonProps) {
|
|
const { t } = useI18n()
|
|
const [starred, setStarred] = useState(false)
|
|
const [count, setCount] = useState(initialStars)
|
|
const [activeTooltip, setActiveTooltip] = useState(false)
|
|
|
|
const gh = githubUrl || `https://github.com/${owner}/${repo}`
|
|
const forge = forgeUrl || `https://forge.hanzo.ai/${owner}/${repo}`
|
|
|
|
const handleDualStar = (e: React.MouseEvent) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
|
|
if (!starred) {
|
|
setStarred(true)
|
|
setCount((prev) => prev + 1)
|
|
setActiveTooltip(true)
|
|
setTimeout(() => setActiveTooltip(false), 3000)
|
|
|
|
// Open GitHub star tab so user stars on GitHub simultaneously
|
|
try {
|
|
const ghWin = window.open(gh, '_blank', 'noopener,noreferrer')
|
|
if (ghWin) ghWin.blur()
|
|
window.focus()
|
|
} catch (_) {}
|
|
|
|
// Call Hanzo Forge star API
|
|
try {
|
|
fetch(`https://forge.hanzo.ai/api/v1/user/starred/${owner}/${repo}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'include',
|
|
}).catch(() => {})
|
|
} catch (_) {}
|
|
} else {
|
|
setStarred(false)
|
|
setCount((prev) => Math.max(0, prev - 1))
|
|
}
|
|
}
|
|
|
|
const isSm = size === 'sm'
|
|
|
|
return (
|
|
<XStack items="center" gap={6} position="relative">
|
|
<XStack
|
|
render={
|
|
<button
|
|
type="button"
|
|
onClick={handleDualStar}
|
|
title={t('Dual-Star on Hanzo Forge and GitHub')}
|
|
/>
|
|
}
|
|
items="center"
|
|
gap={6}
|
|
px={isSm ? 10 : 13}
|
|
py={isSm ? 5 : 7}
|
|
rounded={8}
|
|
borderWidth={1}
|
|
borderColor={starred ? '#39bd7d' : 'var(--border)'}
|
|
bg={starred ? 'rgba(57, 189, 125, 0.12)' : 'rgba(255, 255, 255, 0.04)'}
|
|
hoverStyle={{
|
|
borderColor: starred ? '#56e36d' : 'var(--border-strong)',
|
|
bg: starred ? 'rgba(57, 189, 125, 0.2)' : 'rgba(255, 255, 255, 0.08)',
|
|
}}
|
|
cursor="pointer"
|
|
$platform-web={{
|
|
borderRadius: '8px',
|
|
borderStyle: 'solid',
|
|
transition: 'all 0.18s ease-in-out',
|
|
boxShadow: starred ? '0 0 12px rgba(57, 189, 125, 0.35)' : undefined,
|
|
}}
|
|
>
|
|
<Star
|
|
width={isSm ? 13 : 15}
|
|
height={isSm ? 13 : 15}
|
|
color={starred ? '#39bd7d' : 'var(--muted-foreground)'}
|
|
fill={starred ? '#39bd7d' : 'none'}
|
|
/>
|
|
<Text
|
|
fontSize={isSm ? 11 : 12}
|
|
fontWeight="600"
|
|
color={starred ? '#39bd7d' : 'var(--foreground)'}
|
|
>
|
|
{starred ? t('Starred') : t('Star')}
|
|
</Text>
|
|
<XStack
|
|
items="center"
|
|
px={6}
|
|
py={1}
|
|
rounded={4}
|
|
bg="rgba(255, 255, 255, 0.06)"
|
|
$platform-web={{ borderRadius: '4px' }}
|
|
>
|
|
<Text
|
|
fontFamily="$mono"
|
|
fontSize={isSm ? 10 : 11}
|
|
fontWeight="600"
|
|
color="var(--muted-foreground)"
|
|
>
|
|
{count.toLocaleString('en-US')}
|
|
</Text>
|
|
</XStack>
|
|
</XStack>
|
|
|
|
{/* Dual Badge indicating Forge + GitHub sync */}
|
|
<XStack
|
|
items="center"
|
|
gap={4}
|
|
px={6}
|
|
py={3}
|
|
rounded={6}
|
|
borderWidth={1}
|
|
borderColor="var(--border)"
|
|
bg="rgba(0, 0, 0, 0.4)"
|
|
$platform-web={{ borderRadius: '6px' }}
|
|
>
|
|
<Text fontSize={10} fontFamily="$mono" color="#39bd7d" fontWeight="700">
|
|
FORGE
|
|
</Text>
|
|
<Text fontSize={9} color="var(--muted-foreground)">
|
|
+
|
|
</Text>
|
|
<Text fontSize={10} fontFamily="$mono" color="var(--muted-foreground)" fontWeight="600">
|
|
GH
|
|
</Text>
|
|
</XStack>
|
|
|
|
{/* Instant Notification Tooltip */}
|
|
{activeTooltip && (
|
|
<YStack
|
|
position="absolute"
|
|
b="100%"
|
|
mb={8}
|
|
l="50%"
|
|
p={8}
|
|
rounded={6}
|
|
bg="#101214"
|
|
borderWidth={1}
|
|
borderColor="#39bd7d"
|
|
z={50}
|
|
$platform-web={{
|
|
borderRadius: '6px',
|
|
transform: 'translateX(-50%)',
|
|
boxShadow: '0 8px 24px rgba(0,0,0,0.6)',
|
|
whiteSpace: 'nowrap',
|
|
}}
|
|
>
|
|
<XStack items="center" gap={6}>
|
|
<Check width={12} height={12} color="#39bd7d" />
|
|
<Text fontSize={11} fontWeight="600" color="var(--foreground)">
|
|
{t('Starred on Hanzo Forge & GitHub!')}
|
|
</Text>
|
|
</XStack>
|
|
</YStack>
|
|
)}
|
|
</XStack>
|
|
)
|
|
}
|