You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/web/src/routes/Main/Content/Group/SidebarItem.tsx

134 lines
3.2 KiB
TypeScript

import React from 'react';
import {
groupActions,
GroupPanel,
GroupPanelType,
isValidStr,
showToasts,
t,
useAppDispatch,
useConverseAck,
useGroupInfo,
} from 'tailchat-shared';
import { GroupPanelItem } from '@/components/GroupPanelItem';
import { GroupTextPanelItem } from './TextPanelItem';
import { Dropdown, Menu } from 'antd';
import copy from 'copy-to-clipboard';
import { usePanelWindow } from '@/hooks/usePanelWindow';
import { LoadingSpinner } from '@/components/LoadingSpinner';
import { Icon } from '@/components/Icon';
const GroupAckMenuItem: React.FC<{
panelId: string;
}> = (props) => {
const { markConverseAllAck } = useConverseAck(props.panelId);
return (
<Menu.Item
icon={<Icon icon="mdi:message-badge-outline" />}
onClick={() => {
markConverseAllAck();
}}
>
{t('标记为已读')}
</Menu.Item>
);
};
GroupAckMenuItem.displayName = 'GroupAckMenuItem';
/**
* 群组面板侧边栏组件
*/
export const SidebarItem: React.FC<{
groupId: string;
panel: GroupPanel;
}> = React.memo((props) => {
const { groupId, panel } = props;
const { hasOpenedPanel, openPanelWindow } = usePanelWindow(
`/panel/group/${groupId}/${panel.id}`
);
const groupInfo = useGroupInfo(groupId);
const dispatch = useAppDispatch();
if (!groupInfo) {
return <LoadingSpinner />;
}
const isPinned =
isValidStr(groupInfo.pinnedPanelId) && groupInfo.pinnedPanelId === panel.id;
const menu = (
<Menu>
<Menu.Item
icon={<Icon icon="mdi:content-copy" />}
onClick={() => {
copy(`${location.origin}/main/group/${groupId}/${panel.id}`);
showToasts(t('已复制到剪切板'));
}}
>
{t('复制链接')}
</Menu.Item>
<Menu.Item
icon={<Icon icon="mdi:dock-window" />}
disabled={hasOpenedPanel}
onClick={openPanelWindow}
>
{t('在新窗口打开')}
</Menu.Item>
{isPinned ? (
<Menu.Item
icon={<Icon icon="mdi:pin-off" />}
onClick={() => {
dispatch(
groupActions.unpinGroupPanel({
groupId,
})
);
}}
>
{t('Unpin')}
</Menu.Item>
) : (
<Menu.Item
icon={<Icon icon="mdi:pin" />}
onClick={() => {
dispatch(
groupActions.pinGroupPanel({
groupId,
panelId: panel.id,
})
);
}}
>
{t('Pin')}
</Menu.Item>
)}
{panel.type === GroupPanelType.TEXT && (
<GroupAckMenuItem panelId={panel.id} />
)}
</Menu>
);
const icon = isPinned ? <Icon icon="mdi:pin" /> : <Icon icon="mdi:pound" />;
return (
<Dropdown overlay={menu} trigger={['contextMenu']}>
<div>
{panel.type === GroupPanelType.TEXT ? (
<GroupTextPanelItem icon={icon} groupId={groupId} panel={panel} />
) : (
<GroupPanelItem
name={panel.name}
icon={icon}
to={`/main/group/${groupId}/${panel.id}`}
/>
)}
</div>
</Dropdown>
);
});
SidebarItem.displayName = 'SidebarItem';