lobehub/src/features/ChatInput/ActionBar/SaveTopic/index.tsx
Innei d2197f4c30
♻️ refactor(desktop): consolidate global shortcuts (LOBE-7181) (#13880)
* ♻️ refactor(desktop): consolidate global shortcuts and remove default showApp hotkey

- Add desktopGlobalShortcuts.ts as single source for Electron + renderer defaults
- Wire ShortcutManager and store to DEFAULT_ELECTRON_DESKTOP_SHORTCUTS
- Use DesktopHotkeyId for @shortcut; drop local shortcuts barrel
- Stop re-exporting DESKTOP_HOTKEYS_REGISTRATION from hotkeys

Fixes LOBE-7181

Made-with: Cursor

*  feat(desktop): introduce new stubs for business constants and types

- Added `@lobechat/business-const` and `@lobechat/types` packages to support workspace dependency resolution.
- Updated `package.json` and `pnpm-workspace.yaml` to include new stubs.
- Refactored imports in `index.ts` to utilize the new constants structure.
- Enhanced `desktopGlobalShortcuts.ts` with improved type definitions for hotkeys.

This change streamlines the management of constants and types across the desktop application.

Signed-off-by: Innei <tukon479@gmail.com>

* ♻️ refactor(hotkeys): consolidate desktop global shortcut definitions (LOBE-7181)

Made-with: Cursor

*  feat(session, user): replace direct type imports with constants

- Updated session.ts to use constants for session types instead of direct imports from @lobechat/types.
- Updated user.ts to use a constant for the default topic display mode, enhancing consistency and maintainability.

This change improves code clarity and reduces dependencies on external type definitions.

Signed-off-by: Innei <tukon479@gmail.com>

---------

Signed-off-by: Innei <tukon479@gmail.com>
2026-04-17 00:32:05 +08:00

77 lines
2.4 KiB
TypeScript

import { HotkeyEnum } from '@lobechat/const/hotkeys';
import { ActionIcon, Flexbox, Hotkey } from '@lobehub/ui';
import { Popconfirm } from 'antd';
import { LucideGalleryVerticalEnd, LucideMessageSquarePlus } from 'lucide-react';
import { memo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useIsMobile } from '@/hooks/useIsMobile';
import { useActionSWR } from '@/libs/swr';
import { useChatStore } from '@/store/chat';
import { useUserStore } from '@/store/user';
import { settingsSelectors } from '@/store/user/selectors';
const SaveTopic = memo(() => {
const { t } = useTranslation('chat');
const hotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.SaveTopic));
const [hasTopic, openNewTopicOrSaveTopic] = useChatStore((s) => [
!!s.activeTopicId,
s.openNewTopicOrSaveTopic,
]);
const mobile = useIsMobile();
const { mutate, isValidating } = useActionSWR('openNewTopicOrSaveTopic', openNewTopicOrSaveTopic);
const [confirmOpened, setConfirmOpened] = useState(false);
const icon = hasTopic ? LucideMessageSquarePlus : LucideGalleryVerticalEnd;
const desc = t(hasTopic ? 'topic.openNewTopic' : 'topic.saveCurrentMessages');
if (mobile) {
return (
<Popconfirm
arrow={false}
okButtonProps={{ danger: false, type: 'primary' }}
open={confirmOpened}
placement={'top'}
title={
<Flexbox horizontal align={'center'} style={{ marginBottom: 8 }}>
<div style={{ marginRight: '16px', whiteSpace: 'pre-line', wordBreak: 'break-word' }}>
{t(hasTopic ? 'topic.checkOpenNewTopic' : 'topic.checkSaveCurrentMessages')}
</div>
<Hotkey keys={hotkey} />
</Flexbox>
}
onConfirm={() => mutate()}
onOpenChange={setConfirmOpened}
>
<ActionIcon
aria-label={desc}
icon={icon}
loading={isValidating}
onClick={() => setConfirmOpened(true)}
/>
</Popconfirm>
);
} else {
return (
<ActionIcon
aria-label={desc}
icon={icon}
loading={isValidating}
size={{ blockSize: 32, size: 16, strokeWidth: 2.3 }}
title={desc}
variant={'outlined'}
tooltipProps={{
hotkey,
}}
onClick={() => mutate()}
/>
);
}
});
SaveTopic.displayName = 'SaveTopic';
export default SaveTopic;