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