From f92ef01353cbb011d91a50d78a5d82dcc53b9198 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sun, 6 Feb 2022 22:34:21 +0300 Subject: [PATCH] feat: online user status --- src/App.tsx | 5 +++- src/components/Layout/Layout.tsx | 6 ++--- src/components/UserProfile/Avatar/Avatar.tsx | 2 +- src/hooks/useSocket.ts | 7 ++++- src/pages/main/main.tsx | 19 ++------------ src/pages/user/user.tsx | 3 ++- src/stores/OnlineStore.ts | 27 ++++++++++++++++++++ src/stores/RootStore.ts | 4 +++ src/stores/UserStore.ts | 1 - 9 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 src/stores/OnlineStore.ts diff --git a/src/App.tsx b/src/App.tsx index 4adffc2..7b72a12 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,11 @@ -import React, { useContext, useEffect } from 'react'; +import React from 'react'; import { Router, Switch } from 'react-router-dom'; import { routes } from './routes.config'; /** * Hooks */ +import { useContext } from 'react'; import { useRootStore } from '@educt/hooks/useRootStore'; /** @@ -18,6 +19,7 @@ import { SocketContext } from './contexts'; const App = () => { const { uiStore: { history }, + onlineStore, } = useRootStore(); const { socket } = useContext(SocketContext); @@ -33,6 +35,7 @@ const App = () => { socket.userId = userId; } }); + useSocketEvent('user:online', online => onlineStore.loadOnline(online)); return ( diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx index 4c8172d..7823ab1 100644 --- a/src/components/Layout/Layout.tsx +++ b/src/components/Layout/Layout.tsx @@ -1,7 +1,6 @@ -import React, { Suspense, useContext } from 'react'; +import React, { Suspense } from 'react'; import { observer } from 'mobx-react'; import { Redirect } from 'react-router'; -import { useErrorHandler } from 'react-error-boundary'; import { userContainRoles } from '@educt/helpers'; import { Flex, Box } from '@chakra-ui/react'; @@ -20,7 +19,8 @@ import NavDesktop from '@educt/components/Nav/Desktop'; /** * Hooks */ -import { useEffect } from 'react'; +import { useEffect, useContext } from 'react'; +import { useErrorHandler } from 'react-error-boundary'; import { useRootStore } from '@educt/hooks/useRootStore'; /** diff --git a/src/components/UserProfile/Avatar/Avatar.tsx b/src/components/UserProfile/Avatar/Avatar.tsx index cc6ba4d..b0f7ede 100644 --- a/src/components/UserProfile/Avatar/Avatar.tsx +++ b/src/components/UserProfile/Avatar/Avatar.tsx @@ -10,7 +10,7 @@ const Avatar: React.FC = props => { return ( - {isOnline && } + {isOnline !== undefined && } {props.children} diff --git a/src/hooks/useSocket.ts b/src/hooks/useSocket.ts index 9a39ea7..4aead93 100644 --- a/src/hooks/useSocket.ts +++ b/src/hooks/useSocket.ts @@ -5,7 +5,12 @@ export const useSocket = (url: string) => { const [socket, setSocket] = useState(null); useEffect(() => { - const socketClient = io(url, { autoConnect: false, withCredentials: true }); + const socketClient = io(url, { + autoConnect: false, + withCredentials: true, + transports: ['websocket'], + upgrade: false, + }); setSocket(socketClient); diff --git a/src/pages/main/main.tsx b/src/pages/main/main.tsx index ceb9684..4bce30c 100644 --- a/src/pages/main/main.tsx +++ b/src/pages/main/main.tsx @@ -25,9 +25,7 @@ import { observer } from 'mobx-react'; /** * Hooks */ -import { useEffect, useState } from 'react'; import { useFetchCourses, useFetchStat } from '@educt/hooks/queries'; -import { useSocketEvent } from '@educt/hooks/useSocketEvent'; /** * Main page @@ -35,23 +33,10 @@ import { useSocketEvent } from '@educt/hooks/useSocketEvent'; const MainPage: React.FC = () => { const { userStore: { me }, + onlineStore, } = useRootStore(); const { data: courses } = useFetchCourses({ limit: 3 }); const { data: stat } = useFetchStat(); - const [online, setOnline] = useState(0); - - /** - * Update online state on socket event - */ - useSocketEvent('user:online', online => setOnline(online)); - - // useSocketEvent('user:connected', user => console.table(user)); - - useEffect(() => { - if (stat) { - setOnline(stat.online); - } - }, [stat]); if (me === null || courses === null || stat === null) return ; @@ -63,7 +48,7 @@ const MainPage: React.FC = () => { Online - {online} + {onlineStore.count} diff --git a/src/pages/user/user.tsx b/src/pages/user/user.tsx index b17b985..bd7a4c2 100644 --- a/src/pages/user/user.tsx +++ b/src/pages/user/user.tsx @@ -17,6 +17,7 @@ const UserPage: React.FC = () => { const params = useParams<{ id: string }>(); const { userStore: { me }, + onlineStore, } = useRootStore(); const { data: user, error, isLoading } = useFetchUser(params.id); @@ -34,7 +35,7 @@ const UserPage: React.FC = () => { - + diff --git a/src/stores/OnlineStore.ts b/src/stores/OnlineStore.ts new file mode 100644 index 0000000..1aab713 --- /dev/null +++ b/src/stores/OnlineStore.ts @@ -0,0 +1,27 @@ +import { makeAutoObservable } from 'mobx'; +import RootStore from './RootStore'; + +export default class OnlineStore { + public root: RootStore; + + public online: Set; + + constructor(root: RootStore) { + this.root = root; + this.online = new Set(); + + makeAutoObservable(this); + } + + public loadOnline(online: string[]) { + this.online = new Set(online); + } + + public isOnline(id: string) { + return this.online.has(id); + } + + public get count() { + return this.online.size; + } +} diff --git a/src/stores/RootStore.ts b/src/stores/RootStore.ts index eb8d077..34b4a8b 100644 --- a/src/stores/RootStore.ts +++ b/src/stores/RootStore.ts @@ -9,6 +9,7 @@ import UIStore from './UIStore'; import CategoryStore from './CategoryStore'; import CourseStore from './CourseStore'; import PageStore from './PageStore'; +import OnlineStore from './OnlineStore'; export default class RootStore { public pageStore: PageStore; @@ -23,6 +24,8 @@ export default class RootStore { public userStore: UserStore; + public onlineStore: OnlineStore; + constructor() { /** * Stores @@ -33,6 +36,7 @@ export default class RootStore { this.pageStore = new PageStore(this); this.uiStore = new UIStore(this); this.userStore = new UserStore(this); + this.onlineStore = new OnlineStore(this); makeAutoObservable(this); } diff --git a/src/stores/UserStore.ts b/src/stores/UserStore.ts index 44df66a..8d7ca7f 100644 --- a/src/stores/UserStore.ts +++ b/src/stores/UserStore.ts @@ -8,7 +8,6 @@ import { CreateUserParamsType, FetchUsersParamsType, UpdateUserContactsParamsType, - UpdateUserInfoParamsType, UpdateUserParamsType, } from '@educt/types'; import { IUser, IMe, IPaginationMeta } from '@educt/interfaces';