mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 02:09:08 +03:00
feat: sort online users in chat & added types to socket data events
This commit is contained in:
parent
cfd1137c2d
commit
3b15e47cfe
11
src/App.tsx
11
src/App.tsx
@ -15,6 +15,7 @@ import PrivateRoute from '@educt/components/PrivateRoute';
|
|||||||
import PublicRoute from '@educt/components/PublicRoute';
|
import PublicRoute from '@educt/components/PublicRoute';
|
||||||
import { useSocketEvent } from './hooks/useSocketEvent';
|
import { useSocketEvent } from './hooks/useSocketEvent';
|
||||||
import { SocketContext } from './contexts';
|
import { SocketContext } from './contexts';
|
||||||
|
import { UserOnlineListType, UserSeesionType } from './types';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const {
|
const {
|
||||||
@ -26,16 +27,16 @@ const App = () => {
|
|||||||
useSocketEvent('connect', () => console.info('[WebSocket]: Connected.'));
|
useSocketEvent('connect', () => console.info('[WebSocket]: Connected.'));
|
||||||
useSocketEvent('disconnect', () => console.info('[WebSocket]: Disconnected.'));
|
useSocketEvent('disconnect', () => console.info('[WebSocket]: Disconnected.'));
|
||||||
useSocketEvent('connect_error', err => console.error(err));
|
useSocketEvent('connect_error', err => console.error(err));
|
||||||
useSocketEvent('user:session', data => {
|
useSocketEvent<UserSeesionType>('user:session', data => {
|
||||||
if (socket) {
|
if (socket) {
|
||||||
const { sessionId, userId } = data;
|
const { sessionId } = data;
|
||||||
|
if (sessionId) {
|
||||||
socket.auth = { sessionId };
|
socket.auth = { sessionId };
|
||||||
window.localStorage.setItem('sessionId', sessionId);
|
window.localStorage.setItem('sessionId', sessionId);
|
||||||
// TODO fix types
|
}
|
||||||
socket.userId = userId;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
useSocketEvent('user:online', online => onlineStore.loadOnline(online));
|
useSocketEvent<UserOnlineListType>('user:online', online => onlineStore.loadOnline(online));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
|
|||||||
@ -17,10 +17,13 @@ const Wrapper: React.FC<StackProps> = ({ children }) => {
|
|||||||
|
|
||||||
const Users: React.FC = observer(() => {
|
const Users: React.FC = observer(() => {
|
||||||
const { data: users } = useFetchUsers();
|
const { data: users } = useFetchUsers();
|
||||||
const { onlineStore } = useRootStore();
|
const {
|
||||||
|
userStore: { me },
|
||||||
|
onlineStore,
|
||||||
|
} = useRootStore();
|
||||||
const { search } = useChatContext();
|
const { search } = useChatContext();
|
||||||
|
|
||||||
if (users === null)
|
if (users === null || me === null)
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Skeleton h='90px' borderRadius={'lg'} />
|
<Skeleton h='90px' borderRadius={'lg'} />
|
||||||
@ -28,20 +31,31 @@ const Users: React.FC = observer(() => {
|
|||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
const filtered = (!search ? users : users.filter(u => u.fullname.toLocaleLowerCase().includes(search))).sort(user =>
|
const filtered = (!search ? users : users.filter(u => u.fullname.toLocaleLowerCase().includes(search)))
|
||||||
!onlineStore.isOnline(user.id) ? 1 : -1
|
.concat()
|
||||||
);
|
.sort(u => (onlineStore.isOnline(u.id) ? -1 : 1));
|
||||||
|
|
||||||
const isEmpty = filtered.length === 0;
|
const isEmpty = filtered.length === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
|
{/* Favorites */}
|
||||||
|
<User id={me.id}>
|
||||||
|
<User.Avatar isOnline fullname={me.fullname} />
|
||||||
|
<User.Info fullname={me.fullname} lastMessage={''} />
|
||||||
|
</User>
|
||||||
|
|
||||||
|
{/* User list */}
|
||||||
{!isEmpty ? (
|
{!isEmpty ? (
|
||||||
filtered.map(user => (
|
filtered.map(
|
||||||
|
user =>
|
||||||
|
user.id !== me.id && (
|
||||||
<User key={user.id} id={user.id}>
|
<User key={user.id} id={user.id}>
|
||||||
<User.Avatar isOnline={onlineStore.isOnline(user.id) || false} fullname={user.fullname} />
|
<User.Avatar isOnline={onlineStore.isOnline(user.id) || false} fullname={user.fullname} />
|
||||||
<User.Info fullname={user.fullname} lastMessage={''} />
|
<User.Info fullname={user.fullname} lastMessage={''} />
|
||||||
</User>
|
</User>
|
||||||
))
|
)
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<Box textAlign={'center'}>
|
<Box textAlign={'center'}>
|
||||||
<Text userSelect={'none'} color='gray.500'>
|
<Text userSelect={'none'} color='gray.500'>
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import {
|
|||||||
import { MdOutlineChat, MdSend } from 'react-icons/md';
|
import { MdOutlineChat, MdSend } from 'react-icons/md';
|
||||||
import { MessageList } from './Message';
|
import { MessageList } from './Message';
|
||||||
import { SocketContext } from '@educt/contexts';
|
import { SocketContext } from '@educt/contexts';
|
||||||
import { MessageType } from '@educt/types';
|
import { HistoryMessageType, MessageType } from '@educt/types';
|
||||||
import { UserServiceInstance } from '@educt/services';
|
import { UserServiceInstance } from '@educt/services';
|
||||||
import { IUser } from '@educt/interfaces';
|
import { IUser } from '@educt/interfaces';
|
||||||
import LoadingList from '@educt/components/LoadingList';
|
import LoadingList from '@educt/components/LoadingList';
|
||||||
@ -120,11 +120,10 @@ const Window: React.FC = props => {
|
|||||||
}
|
}
|
||||||
}, [chatId]);
|
}, [chatId]);
|
||||||
|
|
||||||
// TODO add types for this event
|
|
||||||
/**
|
/**
|
||||||
* Event on accept new messages
|
* Event on accept new messages
|
||||||
*/
|
*/
|
||||||
useSocketEvent('chat:message', data => {
|
useSocketEvent<HistoryMessageType>('chat:message', data => {
|
||||||
const user = onlineStore.getUser(data.from);
|
const user = onlineStore.getUser(data.from);
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
@ -134,6 +133,18 @@ const Window: React.FC = props => {
|
|||||||
*/
|
*/
|
||||||
if (data.to === data.from) return;
|
if (data.to === data.from) return;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify user about new message
|
||||||
|
*/
|
||||||
|
// toast({
|
||||||
|
// title: `${user.userName}`,
|
||||||
|
// description: data.content,
|
||||||
|
// variant: 'left-accent',
|
||||||
|
// position: 'bottom-right',
|
||||||
|
// status: 'info',
|
||||||
|
// duration: 5000,
|
||||||
|
// });
|
||||||
|
|
||||||
const message: MessageType = {
|
const message: MessageType = {
|
||||||
content: data.content,
|
content: data.content,
|
||||||
userName: user.userName,
|
userName: user.userName,
|
||||||
|
|||||||
@ -2,10 +2,11 @@ import { createContext } from 'react';
|
|||||||
import { ChangeEmailPageContextType, CoursesPageContextType, UsersPageContextType } from '@educt/types';
|
import { ChangeEmailPageContextType, CoursesPageContextType, UsersPageContextType } from '@educt/types';
|
||||||
import RootStore from '../stores/RootStore';
|
import RootStore from '../stores/RootStore';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
|
import { ClientToServerEvents, ServerToClientEvents } from '@educt/interfaces';
|
||||||
|
|
||||||
export const StoreContext = createContext<RootStore | undefined>(undefined);
|
export const StoreContext = createContext<RootStore | undefined>(undefined);
|
||||||
|
|
||||||
export const SocketContext = createContext<{ socket: Socket | null }>({
|
export const SocketContext = createContext<{ socket: Socket<ServerToClientEvents, ClientToServerEvents> | null }>({
|
||||||
socket: null,
|
socket: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useContext, useEffect } from 'react';
|
import { useContext, useEffect } from 'react';
|
||||||
import { SocketContext } from '@educt/contexts';
|
import { SocketContext } from '@educt/contexts';
|
||||||
|
|
||||||
export const useSocketEvent = (event: string, callback: (...args: unknown[]) => void) => {
|
export const useSocketEvent = <T>(event: string, callback: (data: T) => void) => {
|
||||||
const { socket } = useContext(SocketContext);
|
const { socket } = useContext(SocketContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
7
src/types/index.d.ts
vendored
7
src/types/index.d.ts
vendored
@ -76,6 +76,13 @@ export type HistoryMessageType = {
|
|||||||
time: string;
|
time: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UserSeesionType = {
|
||||||
|
sessionId: string | undefined;
|
||||||
|
userId: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserOnlineListType = [string, { userId: string; userName: string }][];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change email page context
|
* Change email page context
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user