Skip to content

Commit

Permalink
fix(demo): header components (#473)
Browse files Browse the repository at this point in the history
* refine header

* feat: support gh stars
  • Loading branch information
shczhen authored Dec 12, 2024
1 parent e6948b8 commit 2939566
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 98 deletions.
1 change: 1 addition & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"react-redux": "^9.1.0",
"redux": "^5.0.1",
"sonner": "^1.5.0",
"swr": "^2.2.5",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.8"
Expand Down
14 changes: 14 additions & 0 deletions demo/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion demo/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { StoreProvider } from "@/store"
import type { Metadata, Viewport } from "next"
import "./global.css"
import { Toaster } from "@/components/ui/sonner"
import { Roboto } from "next/font/google"
import { cn } from "@/lib/utils"

const roboto = Roboto({
subsets: ["latin"],
weight: ["400", "700"],
variable: "--font-roboto",
display: "swap",
})

export const metadata: Metadata = {
title: "TEN Agent",
Expand Down Expand Up @@ -29,7 +38,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className="dark">
<body className={cn("dark", "antialiased", roboto.variable)}>
{/* <ConfigProvider
theme={{
components: {
Expand Down
5 changes: 3 additions & 2 deletions demo/src/common/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
ICozeSettings,
} from "@/types"
export const GITHUB_URL = "https://github.com/TEN-framework/TEN-Agent"
export const API_GH_GET_REPO_INFO =
"https://api.github.com/repos/TEN-framework/TEN-Agent"
export const OPTIONS_KEY = "__options__"
export const AGENT_SETTINGS_KEY = "__agent_settings__"
export const COZE_SETTINGS_KEY = "__coze_settings__"
Expand Down Expand Up @@ -34,8 +36,7 @@ export const DEFAULT_COZE_SETTINGS: ICozeSettings = {
base_url: ECozeBaseUrl.GLOBAL,
}

export const DESCRIPTION =
"A Realtime Conversational AI Agent powered by TEN"
export const DESCRIPTION = "A Realtime Conversational AI Agent powered by TEN"
export const LANGUAGE_OPTIONS: LanguageOptionItem[] = [
{
label: "English",
Expand Down
16 changes: 16 additions & 0 deletions demo/src/components/Icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ import * as React from "react"

import { cn } from "@/lib/utils"

export function TenLogo(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 48 34"
fill="none"
{...props}
>
<path
d="M40.0724 0.706698H40.1247L39.3918 0.052348H38.5543L8.9515 0L8.74211 0.602002L0 25.9646L7.32871 34L16.6205 33.9738L25.8861 7.0408L16.097 6.98845L9.57968 0.602002L39.2348 0.706698L46.4588 7.66898L35.0208 7.25019L25.8075 33.9738L38.2664 33.843L47.2702 7.69515L40.0724 0.706698Z"
fill="currentColor"
/>
</svg>
)
}

export const GitHubIcon = (props: React.SVGProps<SVGSVGElement>) => {
return (
<svg
Expand Down
9 changes: 5 additions & 4 deletions demo/src/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LogoIcon, SmallLogoIcon } from "@/components/Icon"
import { HeaderRoomInfo, HeaderActions } from "./HeaderComponents"
// import { LogoIcon, SmallLogoIcon } from "@/components/Icon"
import { HeaderActions } from "./HeaderComponents"
import { TenLogo } from "@/components/Icon"
import { cn } from "@/lib/utils"

export default function Header(props: { className?: string }) {
Expand All @@ -9,16 +10,16 @@ export default function Header(props: { className?: string }) {
{/* Header */}
<header
className={cn(
"flex items-center justify-between bg-[#181a1d] p-2 md:p-4",
"flex items-center justify-between bg-[#181a1d] p-2 font-roboto md:p-4",
className,
)}
>
<div className="flex items-center space-x-2">
<TenLogo className="h-3 md:h-5" />
{/* <LogoIcon className="hidden h-5 md:block" />
<SmallLogoIcon className="block h-4 md:hidden" /> */}
<h1 className="text-sm font-bold md:text-xl">TEN Agent</h1>
</div>
<HeaderRoomInfo />
<HeaderActions />
</header>
</>
Expand Down
112 changes: 81 additions & 31 deletions demo/src/components/Layout/HeaderComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,61 +13,76 @@ import {
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import { InfoIcon, GitHubIcon, PaletteIcon } from "@/components/Icon"
import { Button } from "@/components/ui/button"
import { GitHubIcon, PaletteIcon } from "@/components/Icon"
import {
useAppSelector,
useAppDispatch,
GITHUB_URL,
COLOR_LIST,
// getRandomUserId,
// getRandomChannel,
// genRandomString,
API_GH_GET_REPO_INFO,
} from "@/common"
import { setThemeColor } from "@/store/reducers/global"
import { setThemeColor, setOptions } from "@/store/reducers/global"
import { cn } from "@/lib/utils"
import { HexColorPicker } from "react-colorful"
import dynamic from "next/dynamic"
import { useCancelableSWR } from "@/hooks"
import { formatNumber } from "@/lib/utils"

import styles from "./Header.module.css"

export function HeaderRoomInfo() {
const dispatch = useAppDispatch()

const options = useAppSelector((state) => state.global.options)
const { channel, userId } = options

const roomConnected = useAppSelector((state) => state.global.roomConnected)
const agentConnected = useAppSelector((state) => state.global.agentConnected)

const roomConnectedText = React.useMemo(() => {
return roomConnected ? "TRUE" : "FALSE"
}, [roomConnected])

const agentConnectedText = React.useMemo(() => {
return agentConnected ? "TRUE" : "FALSE"
}, [agentConnected])
// const handleRegenerateChannelAndUserId = () => {
// const newOptions = {
// userName: genRandomString(8),
// channel: getRandomChannel(),
// userId: getRandomUserId(),
// }
// dispatch(setOptions(newOptions))
// }

return (
<>
<TooltipProvider delayDuration={200}>
<Tooltip>
<TooltipTrigger className="flex items-center space-x-2 text-lg font-semibold">
<InfoIcon className="h-4 w-4 md:h-5 md:w-5" />
<span className="hidden text-sm md:inline-block">
Channel Name:{" "}
</span>
<span className="max-w-24 truncate text-ellipsis text-sm md:text-base">
{channel}
</span>
<TooltipTrigger className="flex items-center space-x-2 text-xs font-semibold md:text-sm">
<span className="max-w-24 truncate text-ellipsis">{channel}</span>
</TooltipTrigger>
<TooltipContent className="bg-[var(--background-color,#1C1E22)] text-gray-600">
<TooltipContent
className="bg-[var(--background-color,#1C1E22)] text-gray-600"
align="end"
>
<table className="border-collapse">
<tbody>
<tr>
{/* <tr>
<td className="pr-2 font-bold text-primary">INFO</td>
<td></td>
</tr>
<td>
<Button
size="sm"
disabled={roomConnected || agentConnected}
onClick={handleRegenerateChannelAndUserId}
>
Regenerate
</Button>
</td>
</tr> */}
<tr>
<td className="pr-2">Room:</td>
<td className="pr-2">ChannelName</td>
<td className="text-[#0888FF]">{channel}</td>
</tr>
<tr>
<td className="pr-2">Participant:</td>
<td className="pr-2">UserID</td>
<td className="text-[#0888FF]">{userId}</td>
</tr>
<tr>
Expand All @@ -81,12 +96,16 @@ export function HeaderRoomInfo() {
</td>
</tr>
<tr>
<td className="pr-2">Room connected:</td>
<td className="text-[#0888FF]">{roomConnectedText}</td>
<td className="pr-2">Room</td>
<td className="text-[#0888FF]">
{roomConnected ? "Connected" : "Disconnected"}
</td>
</tr>
<tr>
<td className="pr-2">Agent connected:</td>
<td className="text-[#0888FF]">{agentConnectedText}</td>
<td className="pr-2">Agent</td>
<td className="text-[#0888FF]">
{agentConnected ? "Connected" : "Disconnected"}
</td>
</tr>
</tbody>
</table>
Expand All @@ -100,12 +119,14 @@ export function HeaderRoomInfo() {
export function HeaderActions() {
return (
<div className="flex space-x-2 md:space-x-4">
<NextLink href={GITHUB_URL} target="_blank">
{/* <NextLink href={GITHUB_URL} target="_blank">
<GitHubIcon className="h-4 w-4 md:h-5 md:w-5" />
<span className="sr-only">GitHub</span>
</NextLink>
<ThemePalettePopover />
<NetworkIndicator />
</NextLink> */}
<GitHubStar />
<HeaderRoomInfo />
{/* <ThemePalettePopover />
<NetworkIndicator /> */}
</div>
)
}
Expand Down Expand Up @@ -203,3 +224,32 @@ const NetworkIndicator = dynamic(
ssr: false,
},
)

export const GitHubStar = () => {
const [{ data, error, isLoading }] = useCancelableSWR<{
stargazers_count: number
}>(API_GH_GET_REPO_INFO, {
refreshInterval: 1000 * 60 * 60, // 1 hour
revalidateOnFocus: false,
revalidateOnReconnect: false,
})

const starsCntMemo = React.useMemo(() => {
if (!data || !data.stargazers_count) return null
return formatNumber(data?.stargazers_count || 0)
}, [data?.stargazers_count])

return (
<Button size="sm" variant="ghost" asChild>
<NextLink href={GITHUB_URL} target="_blank">
<GitHubIcon className="h-4 w-4 md:h-5 md:w-5" />
<span className="sr-only">GitHub</span>
{starsCntMemo && (
<span className="text-xs font-semibold md:text-sm">
{starsCntMemo}
</span>
)}
</NextLink>
</Button>
)
}
32 changes: 32 additions & 0 deletions demo/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use client"

import { type SWRResponse, type SWRConfiguration } from "swr"
import useSWR from "swr"

// https://github.com/vercel/swr/discussions/2330#discussioncomment-4460054
export function useCancelableSWR<T>(
key: string,
opts?: SWRConfiguration,
): [SWRResponse<T>, AbortController] {
const controller = new AbortController()
return [
useSWR(
key,
(url: string) =>
fetch(url, { signal: controller.signal }).then((res) => res.json()),
{
// revalidateOnFocus: false,
errorRetryCount: 3,
refreshInterval: 1000 * 60,
// dedupingInterval: 30000,
// focusThrottleInterval: 60000,
...opts,
},
),
controller,
]
// to use it:
// const [{ data }, controller] = useCancelableSWR('/api')
// ...
// controller.abort()
}
14 changes: 14 additions & 0 deletions demo/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,17 @@ export function useIsMobileScreen(breakpoint?: string) {

return isMobileScreen
}

export function formatNumber(num: number, decimals: number = 1): string {
if (num === 0) return "0"

const k = 1000
const sizes = ["", "K", "M", "B", "T"]

const i = Math.floor(Math.log(Math.abs(num)) / Math.log(k))

if (i === 0) return num.toString()

const scaled = num / Math.pow(k, i)
return `${scaled.toFixed(decimals)}${sizes[i]}`
}
Loading

0 comments on commit 2939566

Please sign in to comment.