feat: support display of online user list

This commit is contained in:
molvqingtai 2024-10-08 19:38:03 +08:00
parent 8ee9ed6259
commit 4c7137d045
5 changed files with 9735 additions and 7903 deletions

View file

@ -1,2 +1,2 @@
npx commitlint --edit "$1" pnpm commitlint --edit "$1"

View file

@ -45,19 +45,19 @@
"homepage": "https://github.com/molvqingtai/WebChat", "homepage": "https://github.com/molvqingtai/WebChat",
"dependencies": { "dependencies": {
"@hookform/resolvers": "^3.9.0", "@hookform/resolvers": "^3.9.0",
"@lottiefiles/dotlottie-react": "^0.9.0", "@lottiefiles/dotlottie-react": "^0.9.1",
"@perfsee/jsonr": "^1.13.0", "@perfsee/jsonr": "^1.13.0",
"@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-avatar": "^1.1.1",
"@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-hover-card": "^1.1.1", "@radix-ui/react-hover-card": "^1.1.2",
"@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0", "@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-popover": "^1.1.2",
"@radix-ui/react-radio-group": "^1.2.0", "@radix-ui/react-radio-group": "^1.2.1",
"@radix-ui/react-scroll-area": "^1.1.0", "@radix-ui/react-scroll-area": "^1.2.0",
"@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-switch": "^1.1.1",
"@resreq/event-hub": "^1.6.0", "@resreq/event-hub": "^1.6.0",
"@resreq/timer": "^1.1.6", "@resreq/timer": "^1.1.6",
"@rtco/client": "^0.2.17", "@rtco/client": "^0.2.17",
@ -67,9 +67,9 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"danmaku": "^2.0.7", "danmaku": "^2.0.7",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"framer-motion": "^11.9.0", "framer-motion": "^11.11.1",
"idb-keyval": "^6.2.1", "idb-keyval": "^6.2.1",
"lucide-react": "^0.446.0", "lucide-react": "^0.449.0",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"next-themes": "^0.3.0", "next-themes": "^0.3.0",
"react": "^18.3.1", "react": "^18.3.1",
@ -85,51 +85,51 @@
"remesh-react": "^4.1.2", "remesh-react": "^4.1.2",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"sonner": "^1.5.0", "sonner": "^1.5.0",
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.3",
"trystero": "^0.20.0", "trystero": "^0.20.0",
"type-fest": "^4.26.1", "type-fest": "^4.26.1",
"unstorage": "1.11.0", "unstorage": "1.12.0",
"valibot": "^0.42.1" "valibot": "1.0.0-beta.0"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^19.5.0", "@commitlint/cli": "^19.5.0",
"@commitlint/config-conventional": "^19.5.0", "@commitlint/config-conventional": "^19.5.0",
"@eslint-react/eslint-plugin": "^1.14.3", "@eslint-react/eslint-plugin": "^1.14.3",
"@eslint/js": "^9.11.1", "@eslint/js": "^9.12.0",
"@semantic-release/changelog": "^6.0.3", "@semantic-release/changelog": "^6.0.3",
"@semantic-release/exec": "^6.0.3", "@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1", "@semantic-release/git": "^10.0.1",
"@types/eslint": "^9.6.1", "@types/eslint": "^9.6.1",
"@types/eslint-plugin-tailwindcss": "^3.17.0", "@types/eslint-plugin-tailwindcss": "^3.17.0",
"@types/eslint__js": "^8.42.3", "@types/eslint__js": "^8.42.3",
"@types/node": "^22.7.4", "@types/node": "^22.7.5",
"@types/react": "^18.3.10", "@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@typescript-eslint/parser": "^8.7.0", "@typescript-eslint/parser": "^8.8.1",
"@vitejs/plugin-react": "^4.3.2", "@vitejs/plugin-react": "^4.3.2",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^9.11.1", "eslint": "^9.12.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-tailwindcss": "^3.17.4", "eslint-plugin-tailwindcss": "^3.17.4",
"globals": "^15.9.0", "globals": "^15.10.0",
"husky": "^9.1.6", "husky": "^9.1.6",
"jiti": "^2.0.0", "jiti": "^2.3.3",
"lint-staged": "^15.2.10", "lint-staged": "^15.2.10",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"postcss": "^8.4.47", "postcss": "^8.4.47",
"postcss-rem-to-responsive-pixel": "^6.0.2", "postcss-rem-to-responsive-pixel": "^6.0.2",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"rimraf": "^5.0.10", "rimraf": "^6.0.1",
"semantic-release": "^24.1.2", "semantic-release": "^24.1.2",
"tailwindcss": "^3.4.13", "tailwindcss": "^3.4.13",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"typescript": "^5.6.2", "typescript": "^5.6.2",
"typescript-eslint": "^8.7.0", "typescript-eslint": "^8.8.1",
"vite-plugin-svgr": "^4.2.0", "vite-plugin-svgr": "^4.2.0",
"webext-bridge": "^6.0.1", "webext-bridge": "^6.0.1",
"wxt": "^0.19.10" "wxt": "^0.19.11"
}, },
"lint-staged": { "lint-staged": {
"*.{js,jsx,ts,tsx}": "eslint --fix --flag unstable_ts_config" "*.{js,jsx,ts,tsx}": "eslint --fix --flag unstable_ts_config"

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,7 @@ const EmojiButton: FC<EmojiButtonProps> = ({ onSelect }) => {
<SmileIcon size={20} /> <SmileIcon size={20} />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="z-infinity w-72 px-0" onCloseAutoFocus={handleCloseAutoFocus}> <PopoverContent className="z-infinity w-72 rounded-xl px-0" onCloseAutoFocus={handleCloseAutoFocus}>
<ScrollArea className="size-72 px-3"> <ScrollArea className="size-72 px-3">
{emojiGroups.map((group, index) => { {emojiGroups.map((group, index) => {
return ( return (

View file

@ -6,6 +6,7 @@ import { Button } from '@/components/ui/Button'
import { cn, getSiteInfo } from '@/utils' import { cn, getSiteInfo } from '@/utils'
import { useRemeshDomain, useRemeshQuery } from 'remesh-react' import { useRemeshDomain, useRemeshQuery } from 'remesh-react'
import RoomDomain from '@/domain/Room' import RoomDomain from '@/domain/Room'
import { ScrollArea } from '@/components/ui/ScrollArea'
const Header: FC = () => { const Header: FC = () => {
const siteInfo = getSiteInfo() const siteInfo = getSiteInfo()
@ -29,7 +30,7 @@ const Header: FC = () => {
</span> </span>
</Button> </Button>
</HoverCardTrigger> </HoverCardTrigger>
<HoverCardContent className="w-80"> <HoverCardContent className="w-80 rounded-lg">
<div className="grid grid-cols-[auto_1fr] gap-x-4"> <div className="grid grid-cols-[auto_1fr] gap-x-4">
<Avatar className="size-14"> <Avatar className="size-14">
<AvatarImage src={siteInfo.icon} alt="favicon" /> <AvatarImage src={siteInfo.icon} alt="favicon" />
@ -46,23 +47,44 @@ const Header: FC = () => {
</div> </div>
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
<div className="flex items-center gap-x-1 text-sm text-slate-500"> <HoverCard>
<span className="relative flex size-2"> <HoverCardTrigger asChild>
<span <Button className="overflow-hidden" variant="link">
className={cn( <div className="flex items-center gap-x-1 text-nowrap text-sm text-slate-500">
'absolute inline-flex size-full animate-ping rounded-full opacity-75', <span className="relative flex size-2">
onlineCount > 1 ? 'bg-green-400' : 'bg-orange-400' <span
)} className={cn(
></span> 'absolute inline-flex size-full animate-ping rounded-full opacity-75',
<span onlineCount > 1 ? 'bg-green-400' : 'bg-orange-400'
className={cn( )}
'relative inline-flex size-2 rounded-full', ></span>
onlineCount > 1 ? 'bg-green-500' : 'bg-orange-500' <span
)} className={cn(
></span> 'relative inline-flex size-2 rounded-full',
</span> onlineCount > 1 ? 'bg-green-500' : 'bg-orange-500'
<span>ONLINE {onlineCount > 99 ? '99+' : onlineCount}</span> )}
</div> ></span>
</span>
<span>ONLINE {onlineCount > 99 ? '99+' : onlineCount}</span>
</div>
</Button>
</HoverCardTrigger>
<HoverCardContent className="w-44 rounded-lg p-2">
<ScrollArea className="max-h-80">
{userList.map((user) => (
<div className="flex items-center gap-x-2 p-2 [content-visibility:auto]" key={user.userId}>
<Avatar className="size-6 shrink-0">
<AvatarImage src={user.userAvatar} alt="avatar" />
<AvatarFallback>{user.username.at(0)}</AvatarFallback>
</Avatar>
<div className="flex-1 overflow-hidden text-ellipsis text-nowrap text-sm text-slate-500">
{user.username}
</div>
</div>
))}
</ScrollArea>
</HoverCardContent>
</HoverCard>
</div> </div>
) )
} }