feat: 增加pin面板的功能,并移除useCurrentGroupPanelInfo

pull/81/head
moonrailgun 3 years ago
parent 1db87df614
commit c903b3adaa

@ -28,6 +28,7 @@ export interface GroupInfo {
owner: string; owner: string;
members: GroupMember[]; members: GroupMember[];
panels: GroupPanel[]; panels: GroupPanel[];
pinnedPanelId?: string; // 被钉选的面板Id
} }
/** /**

@ -42,6 +42,39 @@ const groupSlice = createSlice({
const groupId = action.payload; const groupId = action.payload;
delete state.groups[groupId]; delete state.groups[groupId];
}, },
pinGroupPanel(
state,
action: PayloadAction<{
groupId: string;
panelId: string;
}>
) {
const { groupId, panelId } = action.payload;
if (state.groups[groupId]) {
// NOTICE: updateGroup 只会去更新,不会去添加新的
state.groups[groupId] = {
...state.groups[groupId],
pinnedPanelId: panelId,
};
}
},
unpinGroupPanel(
state,
action: PayloadAction<{
groupId: string;
}>
) {
const { groupId } = action.payload;
if (state.groups[groupId]) {
// NOTICE: updateGroup 只会去更新,不会去添加新的
state.groups[groupId] = {
...state.groups[groupId],
pinnedPanelId: undefined,
};
}
},
}, },
}); });

@ -1,17 +1,18 @@
import React from 'react'; import React from 'react';
import { regGroupPanel, useCurrentGroupPanelInfo } from '@capital/common'; import { regGroupPanel } from '@capital/common';
import { Translate } from './translate'; import { Translate } from './translate';
import _get from 'lodash/get';
const PLUGIN_NAME = 'com.msgbyte.webview'; const PLUGIN_NAME = 'com.msgbyte.webview';
const GroupWebPanelRender = () => { const GroupWebPanelRender: React.FC<{ panelInfo: any }> = (props) => {
const groupPanelInfo = useCurrentGroupPanelInfo(); const panelInfo = props.panelInfo;
if (!groupPanelInfo) { if (!panelInfo) {
return <div>{Translate.notfound}</div>; return <div>{Translate.notfound}</div>;
} }
const url = groupPanelInfo.meta?.url; const url = _get(panelInfo, 'meta.url');
return ( return (
<iframe key={String(url)} className="w-full h-full bg-white" src={url} /> <iframe key={String(url)} className="w-full h-full bg-white" src={url} />

@ -61,7 +61,7 @@ export const GroupPluginPanel: React.FC<GroupPluginPanelProps> = React.memo(
panelId={props.panelId} panelId={props.panelId}
showHeader={false} showHeader={false}
> >
<Component /> <Component panelInfo={panelInfo} />
</GroupPanelWrapper> </GroupPanelWrapper>
); );
} }

@ -5,10 +5,7 @@
import _pick from 'lodash/pick'; import _pick from 'lodash/pick';
export * from './reg'; export * from './reg';
export { export { useGroupPanelParams } from '@/routes/Main/Content/Group/utils';
useGroupPanelParams,
useCurrentGroupPanelInfo,
} from '@/routes/Main/Content/Group/utils';
export { export {
openModal, openModal,
closeModal, closeModal,

@ -4,6 +4,7 @@ import {
buildRegList, buildRegList,
ChatMessage, ChatMessage,
FastFormFieldMeta, FastFormFieldMeta,
GroupPanel,
regSocketEventListener, regSocketEventListener,
} from 'tailchat-shared'; } from 'tailchat-shared';
@ -71,7 +72,7 @@ export interface PluginGroupPanel {
/** /**
* *
*/ */
render: React.ComponentType; render: React.ComponentType<{ panelInfo: GroupPanel }>;
} }
export const [pluginGroupPanel, regGroupPanel] = export const [pluginGroupPanel, regGroupPanel] =
buildRegList<PluginGroupPanel>(); buildRegList<PluginGroupPanel>();

@ -11,47 +11,60 @@ import {
} from 'tailchat-shared'; } from 'tailchat-shared';
import { useGroupPanelParams } from './utils'; import { useGroupPanelParams } from './utils';
export const GroupPanelRender: React.FC = React.memo(() => { interface GroupPanelRenderProps {
const { groupId, panelId } = useGroupPanelParams(); groupId: string;
const groupInfo = useGroupInfo(groupId); panelId: string;
const panelInfo = useGroupPanel(groupId, panelId); }
export const GroupPanelRender: React.FC<GroupPanelRenderProps> = React.memo(
(props) => {
const { groupId, panelId } = props;
const groupInfo = useGroupInfo(groupId);
const panelInfo = useGroupPanel(groupId, panelId);
if (groupInfo === null) { if (groupInfo === null) {
return ( return (
<Alert <Alert
className="w-full text-center" className="w-full text-center"
type="error" type="error"
message={t('群组不存在')} message={t('群组不存在')}
/> />
); );
} }
if (panelInfo === null) {
return (
<Alert
className="w-full text-center"
type="error"
message={t('面板不存在')}
/>
);
}
if (panelInfo.type === GroupPanelType.TEXT) {
return (
<GroupInfoContextProvider groupInfo={groupInfo}>
<TextPanel groupId={groupId} panelId={panelInfo.id} />
</GroupInfoContextProvider>
);
} else if (panelInfo.type === GroupPanelType.PLUGIN) {
return <GroupPluginPanel groupId={groupId} panelId={panelInfo.id} />;
}
if (panelInfo === null) {
return ( return (
<Alert <Alert
className="w-full text-center" className="w-full text-center"
type="error" type="error"
message={t('面板不存在')} message={t('未知的面板类型')}
/> />
); );
} }
);
GroupPanelRender.displayName = 'GroupPanelRender';
if (panelInfo.type === GroupPanelType.TEXT) { export const GroupPanelRoute: React.FC = React.memo(() => {
return ( const { groupId, panelId } = useGroupPanelParams();
<GroupInfoContextProvider groupInfo={groupInfo}>
<TextPanel groupId={groupId} panelId={panelInfo.id} />
</GroupInfoContextProvider>
);
} else if (panelInfo.type === GroupPanelType.PLUGIN) {
return <GroupPluginPanel groupId={groupId} panelId={panelInfo.id} />;
}
return ( return <GroupPanelRender groupId={groupId} panelId={panelId} />;
<Alert
className="w-full text-center"
type="error"
message={t('未知的面板类型')}
/>
);
}); });
GroupPanelRender.displayName = 'GroupPanelRender'; GroupPanelRoute.displayName = 'GroupPanelRoute';

@ -1,10 +1,20 @@
import React from 'react'; import React from 'react';
import { GroupPanel, GroupPanelType, showToasts, t } from 'tailchat-shared'; import {
groupActions,
GroupPanel,
GroupPanelType,
isValidStr,
showToasts,
t,
useAppDispatch,
useGroupInfo,
} from 'tailchat-shared';
import { GroupPanelItem } from '@/components/GroupPanelItem'; import { GroupPanelItem } from '@/components/GroupPanelItem';
import { GroupTextPanelItem } from './TextPanelItem'; import { GroupTextPanelItem } from './TextPanelItem';
import { Dropdown, Menu } from 'antd'; import { Dropdown, Menu } from 'antd';
import copy from 'copy-to-clipboard'; import copy from 'copy-to-clipboard';
import { usePanelWindow } from '@/hooks/usePanelWindow'; import { usePanelWindow } from '@/hooks/usePanelWindow';
import { LoadingSpinner } from '@/components/LoadingSpinner';
/** /**
* *
@ -17,6 +27,12 @@ export const SidebarItem: React.FC<{
const { hasOpenedPanel, openPanelWindow } = usePanelWindow( const { hasOpenedPanel, openPanelWindow } = usePanelWindow(
`/panel/group/${groupId}/${panel.id}` `/panel/group/${groupId}/${panel.id}`
); );
const groupInfo = useGroupInfo(groupId);
const dispatch = useAppDispatch();
if (!groupInfo) {
return <LoadingSpinner />;
}
const menu = ( const menu = (
<Menu> <Menu>
@ -33,6 +49,34 @@ export const SidebarItem: React.FC<{
<Menu.Item disabled={hasOpenedPanel} onClick={openPanelWindow}> <Menu.Item disabled={hasOpenedPanel} onClick={openPanelWindow}>
{t('在新窗口打开')} {t('在新窗口打开')}
</Menu.Item> </Menu.Item>
{isValidStr(groupInfo.pinnedPanelId) &&
groupInfo.pinnedPanelId === panel.id ? (
<Menu.Item
onClick={() => {
dispatch(
groupActions.unpinGroupPanel({
groupId,
})
);
}}
>
{t('Unpin')}
</Menu.Item>
) : (
<Menu.Item
onClick={() => {
dispatch(
groupActions.pinGroupPanel({
groupId,
panelId: panel.id,
})
);
}}
>
{t('Pin')}
</Menu.Item>
)}
</Menu> </Menu>
); );

@ -1,24 +1,48 @@
import { LoadingSpinner } from '@/components/LoadingSpinner';
import { SplitPanel } from '@/components/SplitPanel';
import React from 'react'; import React from 'react';
import { Route, Switch } from 'react-router-dom'; import { Route, Switch, useParams } from 'react-router-dom';
import { isValidStr, useGroupInfo } from 'tailchat-shared';
import { PageContent } from '../PageContent'; import { PageContent } from '../PageContent';
import { GroupPanelRender } from './Panel'; import { GroupPanelRender, GroupPanelRoute } from './Panel';
import { GroupPanelRedirect } from './PanelRedirect'; import { GroupPanelRedirect } from './PanelRedirect';
import { Sidebar } from './Sidebar'; import { Sidebar } from './Sidebar';
export const Group: React.FC = React.memo(() => { export const Group: React.FC = React.memo(() => {
const { groupId } = useParams<{
groupId: string;
}>();
const groupInfo = useGroupInfo(groupId);
if (!groupInfo) {
return <LoadingSpinner />;
}
const pinnedPanelId = groupInfo.pinnedPanelId;
const routeMatch = (
<Switch>
<Route path="/main/group/:groupId/:panelId" component={GroupPanelRoute} />
<Route
path="/main/group/:groupId"
exact={true}
component={GroupPanelRedirect}
/>
</Switch>
);
return ( return (
<PageContent data-tc-role="content-group" sidebar={<Sidebar />}> <PageContent data-tc-role="content-group" sidebar={<Sidebar />}>
<Switch> {isValidStr(pinnedPanelId) ? (
<Route <SplitPanel className="flex-auto">
path="/main/group/:groupId/:panelId" <div>{routeMatch}</div>
component={GroupPanelRender} <div>
/> <GroupPanelRender groupId={groupId} panelId={pinnedPanelId} />
<Route </div>
path="/main/group/:groupId" </SplitPanel>
exact={true} ) : (
component={GroupPanelRedirect} routeMatch
/> )}
</Switch>
</PageContent> </PageContent>
); );
}); });

@ -15,10 +15,3 @@ export function useGroupPanelParams(): {
return { groupId, panelId }; return { groupId, panelId };
} }
export function useCurrentGroupPanelInfo(): GroupPanel | null {
const { groupId, panelId } = useGroupPanelParams();
const panelInfo = useGroupPanel(groupId, panelId);
return panelInfo;
}

Loading…
Cancel
Save