mirror of https://github.com/msgbyte/tailchat
feat: group preview component
parent
0d21980e40
commit
030adfa4b3
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import { useSocket } from './useSocket';
|
||||
|
||||
/**
|
||||
* A Component for Group Preview Entry
|
||||
*/
|
||||
export const GroupPreview: React.FC<{
|
||||
groupId: string;
|
||||
}> = React.memo((props) => {
|
||||
useSocket(props.groupId);
|
||||
|
||||
return null;
|
||||
});
|
||||
GroupPreview.displayName = 'GroupPreview';
|
@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import { ChatMessageList } from '../ChatBox/ChatMessageList';
|
||||
|
||||
interface GroupPreviewMessageListProps {
|
||||
groupId: string;
|
||||
converseId: string;
|
||||
}
|
||||
export const GroupPreviewMessageList: React.FC<GroupPreviewMessageListProps> =
|
||||
React.memo(() => {
|
||||
return (
|
||||
<ChatMessageList
|
||||
messages={[]}
|
||||
isLoadingMore={false}
|
||||
hasMoreMessage={false}
|
||||
onLoadMore={async () => {}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
GroupPreviewMessageList.displayName = 'GroupPreviewMessageList';
|
@ -0,0 +1,3 @@
|
||||
Preview Group Message like Discord.
|
||||
|
||||
NOTICE: GroupPreview should has independent context because its should can run in non-main page.
|
@ -0,0 +1 @@
|
||||
export { GroupPreview } from './GroupPreview';
|
@ -0,0 +1,29 @@
|
||||
import { create } from 'zustand';
|
||||
import type { model } from 'tailchat-shared';
|
||||
|
||||
interface ChatConverseState extends model.converse.ChatConverseInfo {
|
||||
messages: model.message.LocalChatMessage[];
|
||||
}
|
||||
|
||||
interface GroupPreviewState {
|
||||
groupInfo: model.group.GroupInfo | null;
|
||||
converses: Record<string, ChatConverseState>;
|
||||
}
|
||||
|
||||
function getDefaultState() {
|
||||
return {
|
||||
groupInfo: null,
|
||||
converses: {},
|
||||
};
|
||||
}
|
||||
|
||||
export const useGroupPreviewStore = create<GroupPreviewState>((get) => ({
|
||||
...getDefaultState(),
|
||||
}));
|
||||
|
||||
/**
|
||||
* 重置状态
|
||||
*/
|
||||
export function resetGroupPreviewState() {
|
||||
useGroupPreviewStore.setState(getDefaultState());
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import { useSocketContext } from '@/context/SocketContext';
|
||||
import { useEffect } from 'react';
|
||||
import { GroupInfo, GroupPanelType } from 'tailchat-shared';
|
||||
import { resetGroupPreviewState, useGroupPreviewStore } from './store';
|
||||
|
||||
export function useSocket(groupId: string) {
|
||||
const socket = useSocketContext();
|
||||
|
||||
useEffect(() => {
|
||||
socket.request('group.preview.joinGroupRooms', {
|
||||
groupId,
|
||||
});
|
||||
|
||||
socket
|
||||
.request<GroupInfo>('group.preview.getGroupInfo', {
|
||||
groupId,
|
||||
})
|
||||
.then((groupInfo) => {
|
||||
console.log('groupInfo', groupInfo);
|
||||
useGroupPreviewStore.setState({
|
||||
groupInfo,
|
||||
});
|
||||
|
||||
if (Array.isArray(groupInfo.panels)) {
|
||||
const textPanels = groupInfo.panels.map(
|
||||
(p) => p.type === GroupPanelType.TEXT
|
||||
);
|
||||
|
||||
// TODO
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
socket.request('group.preview.leaveGroupRooms', {
|
||||
groupId,
|
||||
});
|
||||
|
||||
resetGroupPreviewState();
|
||||
};
|
||||
}, [groupId]);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import { GroupPreview } from '@/components/GroupPreview';
|
||||
import { NotFound } from '@/components/NotFound';
|
||||
import React from 'react';
|
||||
import { Route, Routes, useParams } from 'react-router';
|
||||
import { t } from 'tailchat-shared';
|
||||
import { MainProvider } from '../Main/Provider';
|
||||
|
||||
const PreviewRoute: React.FC = React.memo(() => {
|
||||
return (
|
||||
<MainProvider>
|
||||
<Routes>
|
||||
<Route path="/:groupId" element={<GroupPreviewRoute />} />
|
||||
|
||||
<Route path="/*" element={t('未知的页面')} />
|
||||
</Routes>
|
||||
</MainProvider>
|
||||
);
|
||||
});
|
||||
PreviewRoute.displayName = 'PreviewRoute';
|
||||
|
||||
const GroupPreviewRoute: React.FC = React.memo(() => {
|
||||
const { groupId } = useParams<{
|
||||
groupId: string;
|
||||
}>();
|
||||
|
||||
if (!groupId) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
return <GroupPreview groupId={groupId} />;
|
||||
});
|
||||
GroupPreviewRoute.displayName = 'GroupPreviewRoute';
|
||||
|
||||
export default PreviewRoute;
|
@ -0,0 +1,78 @@
|
||||
import { TcService, TcContext, call } from 'tailchat-server-sdk';
|
||||
|
||||
class GroupPreviewService extends TcService {
|
||||
get serviceName(): string {
|
||||
return 'group.preview';
|
||||
}
|
||||
|
||||
onInit(): void {
|
||||
/**
|
||||
* TODO: 这里的action都应当判断一下群组是否支持预览
|
||||
*/
|
||||
this.registerAction('joinGroupRooms', this.joinGroupRooms, {
|
||||
params: {
|
||||
groupId: 'string',
|
||||
},
|
||||
});
|
||||
this.registerAction('leaveGroupRooms', this.leaveGroupRooms, {
|
||||
params: {
|
||||
groupId: 'string',
|
||||
},
|
||||
});
|
||||
this.registerAction('getGroupInfo', this.getGroupInfo, {
|
||||
params: {
|
||||
groupId: 'string',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async joinGroupRooms(ctx: TcContext<{ groupId: string }>) {
|
||||
const groupId = ctx.params.groupId;
|
||||
|
||||
const { textPanelIds, subscribeFeaturePanelIds } = await ctx.call<
|
||||
{
|
||||
textPanelIds: string[];
|
||||
subscribeFeaturePanelIds: string[];
|
||||
},
|
||||
{ groupId: string }
|
||||
>('group.getGroupSocketRooms', {
|
||||
groupId,
|
||||
});
|
||||
|
||||
await call(ctx).joinSocketIORoom([
|
||||
groupId,
|
||||
...textPanelIds,
|
||||
...subscribeFeaturePanelIds,
|
||||
]);
|
||||
}
|
||||
|
||||
async leaveGroupRooms(ctx: TcContext<{ groupId: string }>) {
|
||||
const groupId = ctx.params.groupId;
|
||||
|
||||
const { textPanelIds, subscribeFeaturePanelIds } = await ctx.call<
|
||||
{
|
||||
textPanelIds: string[];
|
||||
subscribeFeaturePanelIds: string[];
|
||||
},
|
||||
{ groupId: string }
|
||||
>('group.getGroupSocketRooms', {
|
||||
groupId,
|
||||
});
|
||||
|
||||
await call(ctx).leaveSocketIORoom([
|
||||
groupId,
|
||||
...textPanelIds,
|
||||
...subscribeFeaturePanelIds,
|
||||
]);
|
||||
}
|
||||
|
||||
async getGroupInfo(ctx: TcContext<{ groupId: string }>) {
|
||||
const groupId = ctx.params.groupId;
|
||||
|
||||
const groupInfo = await call(ctx).getGroupInfo(groupId);
|
||||
|
||||
return groupInfo;
|
||||
}
|
||||
}
|
||||
|
||||
export default GroupPreviewService;
|
Loading…
Reference in New Issue