mirror of https://github.com/msgbyte/tailchat
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.
134 lines
3.2 KiB
TypeScript
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';
|