feat: add socket state

This commit is contained in:
moonrailgun 2024-09-01 01:16:51 +08:00
parent 5588aca522
commit e095a081b9
5 changed files with 56 additions and 12 deletions

View File

@ -7,8 +7,10 @@ import { useIsLogined } from '../store/user';
const useSocketStore = create<{ const useSocketStore = create<{
socket: Socket | null; socket: Socket | null;
connected: boolean;
}>(() => ({ }>(() => ({
socket: null, socket: null,
connected: false,
})); }));
export function createSocketIOClient(workspaceId: string) { export function createSocketIOClient(workspaceId: string) {
@ -23,6 +25,24 @@ export function createSocketIOClient(workspaceId: string) {
forceNew: true, forceNew: true,
}); });
socket.on('connect', () => {
useSocketStore.setState({
connected: true,
});
});
socket.on('disconnect', () => {
useSocketStore.setState({
connected: false,
});
});
socket.on('connect_error', () => {
useSocketStore.setState({
connected: false,
});
});
useSocketStore.setState({ useSocketStore.setState({
socket, socket,
}); });
@ -111,6 +131,10 @@ export function useSocketSubscribe<T>(
return data; return data;
} }
export function useSocketConnected() {
return useSocketStore((state) => state.connected);
}
interface UseSocketSubscribeListOptions<K, T> { interface UseSocketSubscribeListOptions<K, T> {
filter?: (data: T) => boolean; filter?: (data: T) => boolean;
} }

View File

@ -10,8 +10,10 @@ interface CommonHeaderProps {
export const CommonHeader: React.FC<CommonHeaderProps> = React.memo((props) => { export const CommonHeader: React.FC<CommonHeaderProps> = React.memo((props) => {
return ( return (
<div className="flex w-full items-center"> <div className="flex w-full items-center">
<div className="flex flex-1 items-center"> <div className="flex flex-1 flex-shrink items-center overflow-hidden">
<h1 className="text-xl font-bold">{props.title}</h1> <h1 className="overflow-hidden text-ellipsis whitespace-nowrap text-xl font-bold">
{props.title}
</h1>
{props.desc && ( {props.desc && (
<span className="text-muted-foreground ml-2 self-end text-sm"> <span className="text-muted-foreground ml-2 self-end text-sm">

View File

@ -1,4 +1,4 @@
import { AppRouterOutput, trpc } from '@/api/trpc'; import { AppRouterOutput } from '@/api/trpc';
import React from 'react'; import React from 'react';
import { Badge } from '../ui/badge'; import { Badge } from '../ui/badge';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -6,8 +6,6 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
import { MarkdownViewer } from '../MarkdownEditor'; import { MarkdownViewer } from '../MarkdownEditor';
import { FeedIcon } from './FeedIcon'; import { FeedIcon } from './FeedIcon';
import { cn } from '@/utils/style'; import { cn } from '@/utils/style';
import { useCurrentWorkspaceId } from '@/store/user';
import { useTranslation } from '@i18next-toolkit/react';
type FeedEventItemType = type FeedEventItemType =
AppRouterOutput['feed']['fetchEventsByCursor']['items'][number]; AppRouterOutput['feed']['fetchEventsByCursor']['items'][number];
@ -43,8 +41,10 @@ export const FeedEventItem: React.FC<{
<Badge variant="secondary">{event.eventName}</Badge> <Badge variant="secondary">{event.eventName}</Badge>
{event.tags.map((tag) => ( {event.tags.map((tag, i) => (
<Badge variant="outline">{tag}</Badge> <Badge key={i} variant="outline">
{tag}
</Badge>
))} ))}
</div> </div>

View File

@ -29,6 +29,8 @@ import { version } from '@/utils/env';
import React from 'react'; import React from 'react';
import { LuMoreVertical } from 'react-icons/lu'; import { LuMoreVertical } from 'react-icons/lu';
import { trpc } from '@/api/trpc'; import { trpc } from '@/api/trpc';
import { useSocketConnected } from '@/api/socketio';
import { cn } from '@/utils/style';
interface UserConfigProps { interface UserConfigProps {
isCollapsed: boolean; isCollapsed: boolean;
@ -57,6 +59,7 @@ export const UserConfig: React.FC<UserConfigProps> = React.memo((props) => {
setUserInfo(userInfo); setUserInfo(userInfo);
}, },
}); });
const socketConnected = useSocketConnected();
const handleChangeColorSchema = useEvent((colorScheme) => { const handleChangeColorSchema = useEvent((colorScheme) => {
useSettingsStore.setState({ useSettingsStore.setState({
@ -67,10 +70,21 @@ export const UserConfig: React.FC<UserConfigProps> = React.memo((props) => {
const nickname = userInfo?.nickname ?? userInfo?.username ?? ''; const nickname = userInfo?.nickname ?? userInfo?.username ?? '';
const avatar = ( const avatar = (
<div className="relative">
<Avatar size={props.isCollapsed ? 'sm' : 'default'}> <Avatar size={props.isCollapsed ? 'sm' : 'default'}>
<AvatarImage src={userInfo?.avatar ?? undefined} /> {userInfo?.avatar && <AvatarImage src={userInfo.avatar} />}
<AvatarFallback>{nickname.substring(0, 2).toUpperCase()}</AvatarFallback>
<AvatarFallback>
{nickname.substring(0, 2).toUpperCase()}
</AvatarFallback>
</Avatar> </Avatar>
<div
className={cn(
'absolute bottom-0 right-0 h-2 w-2 rounded-full border border-white border-opacity-50',
socketConnected ? 'bg-green-400' : 'bg-gray-400'
)}
/>
</div>
); );
const name = ( const name = (

View File

@ -50,7 +50,11 @@ export const feedRouter = router({
include: { include: {
_count: { _count: {
select: { select: {
events: true, events: {
where: {
archived: false,
},
},
}, },
}, },
}, },