refactor(button): migrate button from antd to heroui (#10292)
* fix(eslint): add Button to restricted antd imports * feat(ui): add Button component with Storybook stories Implement a reusable Button component wrapping HeroUIButton with proper TypeScript props. Add comprehensive Storybook stories demonstrating all button variants, colors, sizes and states. * refactor(components): update ActionIconButton implementation and usage Replace onClick with onPress prop and move icon into icon prop Update component to use @cherrystudio/ui Button instead of antd Simplify props interface and add displayName * refactor(ui): migrate antd buttons to @cherrystudio/ui components update button components across multiple files to use @cherrystudio/ui's Button component replace antd button props with equivalent @cherrystudio/ui props * refactor(InputEmbeddingDimension): replace antd Button with custom Button component Update the Button component to use the custom @cherrystudio/ui Button with updated props for better consistency and maintainability * refactor(components): migrate buttons from antd to @cherrystudio/ui Update button components in LocalBackupModals and LocalBackupManager to use @cherrystudio/ui instead of antd Add flex styling to modal footers for better button alignment * refactor(ProviderSetting): migrate Button components from antd to @cherrystudio/ui Update Button components to use @cherrystudio/ui implementation with new props like variant, color, and startContent Replace onClick handlers with onPress and adjust disabled states * refactor(ui): migrate antd buttons to cherrystudio ui buttons Update button components across multiple files to use @cherrystudio/ui Button instead of antd Button Standardize button props and behavior while maintaining existing functionality * refactor(NutstorePathSelector): update button props to use cherrystudio ui Replace antd Button with cherrystudio ui Button component and update props * refactor(S3BackupManager): migrate antd buttons to @cherrystudio/ui Update button components from antd to @cherrystudio/ui library Change button props to match new library's API (variant, color, onPress, etc) Adjust table props for consistency with new component library * refactor(TranslateButton): replace styled Button with cherrystudio Button component The custom styled Button was replaced with the cherrystudio Button component to maintain consistency across the UI and reduce custom styling code. The functionality remains the same but uses the library's built-in props for styling. * refactor(WebdavBackupManager): replace antd buttons with cherrystudio ui buttons Update button components to use cherrystudio ui library for consistency * refactor(ui): migrate buttons from antd to @cherrystudio/ui Update button components across multiple editor components to use @cherrystudio/ui's Button component instead of antd's. This includes updating props like size, variant, and event handlers to match the new component's API. * refactor(components): migrate buttons from antd to @cherrystudio/ui Update button components in HtmlArtifactsCard and HtmlArtifactsPopup to use @cherrystudio/ui's Button component instead of antd's Button. This includes updating props like icon to startContent, onClick to onPress, and type to variant/color. * refactor(ui): migrate button components from antd to hero ui - replace antd Button with hero ui Button component - update button props interface to extend hero ui props - adjust button props in OAuthButton and MinappPopupContainer * refactor(MultiSelectionPopup): migrate button components to @cherrystudio/ui Update button props to match new component library requirements * refactor(ApiKeyItem): migrate antd buttons to cherrystudio ui components Update button components in ApiKeyItem to use cherrystudio ui library instead of antd * refactor(ApiKeyListPopup): update button props to use new UI library syntax Update button components to use the new syntax from @cherrystudio/ui library, replacing antd Button props with the new variant, color, and isDisabled props. Also adjust icon placement and button types to match the new library's API. * refactor(SelectModelButton): replace antd Button with custom Button component Simplify button implementation by using custom Button component from ui library instead of antd. Remove unused styled component and event handling. * refactor(Preview): migrate ImageToolButton to use @cherrystudio/ui Update ImageToolButton component to use Button from @cherrystudio/ui instead of antd Change onClick prop to onPress to match new Button component API Update related usage in ImageToolbar component * refactor(ui): migrate buttons from antd to cherrystudio ui components Update button components across multiple files to use cherrystudio's Button component instead of antd's. This includes updating props like onClick to onPress and adjusting button styling props to match the new component's API. * refactor(ui): migrate antd buttons to @cherrystudio/ui buttons Update button components from antd to @cherrystudio/ui library Adjust button props to match new component API * refactor(components): update prop names and component usage - Rename onClick to onPress in ImageToolButton test props - Update isLoading to loading in S3BackupManager table props - Change ghost to variant in ProviderSetting button props - Replace antd Button with cherrystudio Button in PreferenceBasicTests * refactor(ImageToolButton): migrate from antd to @cherrystudio/ui * refactor(FilesPage): migrate Button components from antd to @cherrystudio/ui * refactor(SearchMessage): migrate Button components from antd to @cherrystudio/ui * refactor(TopicMessages): migrate Button components from antd to @cherrystudio/ui * refactor(TopicsHistory): migrate Button components from antd to @cherrystudio/ui * refactor(ChatNavigation): migrate Button components from antd to @cherrystudio/ui * refactor(CitationsList): migrate Button components from antd to @cherrystudio/ui * refactor(MessageGroupMenuBar): migrate Button components from antd to @cherrystudio/ui * refactor: reorganize button imports and adjust class order Consolidate Button imports from @cherrystudio/ui to be grouped with other imports Standardize className order for consistency across components * refactor(SelectModelPopup): replace HStack with Flex component for layout * feat: migrate PrivacyPopup from antd Button to @cherrystudio/ui Button - Replace antd Button import with @cherrystudio/ui Button - Update onClick to onPress event handler - Update type="primary" to variant="solid" color="primary" - Maintain existing functionality while following Hero UI API 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate NewTopicButton from antd Button to @cherrystudio/ui Button - Replace antd Button import with @cherrystudio/ui Button - Update size="small" to size="sm" - Update icon prop to startContent for Hero UI API - Update onClick to onPress event handler - Maintain existing styled-components with StyledButton wrapper 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate MessageMcpTool Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update two Button components with Hero UI API: - size="small" to size="sm" - onClick to onPress - variant="filled" to variant="solid" - Move icons to startContent prop - Maintain Dropdown.Button as antd component (not migrated) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate SettingsTab Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update settings icon button with Hero UI API: - type="text" to variant="light" - size="small" to size="sm" - icon prop to isIconOnly with child content - onClick to onPress event handler 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate AssistantTagsPopup Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update delete tag button with Hero UI API: - type="text" to variant="light" - danger prop to color="danger" - icon prop to isIconOnly with child content - onClick to onPress event handler 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate UpdateAppButton from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update styled Button component with Hero UI API: - onClick to onPress event handler - icon prop to startContent - color="orange" to color="warning" (closest equivalent) - variant="outlined" to variant="bordered" - size="small" to size="sm" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(NewTopicButton): replace styled-components with cn utility Simplify component styling by removing styled-components in favor of the cn utility * refactor: organize imports and remove unused event handlers remove duplicate Button imports and clean up stopPropagation handlers * feat: migrate KnowledgeContent Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update settings icon Button with Hero UI API: - type="text" to variant="light" - size="small" to size="sm" - icon prop to isIconOnly with child content - onClick to onPress event handler - Update ResponsiveButton styled component selector: - .ant-btn-icon + span to [data-slot="icon"] + [data-slot="label"] 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate KnowledgeDirectories Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update three Button components with Hero UI API: - Refresh button: type="text" to variant="light", icon to isIconOnly, onClick to onPress - Delete button: type="text" danger to variant="light" color="danger", icon to isIconOnly, onClick to onPress - Add directory button: type="primary" to variant="solid" color="primary", icon to startContent, disabled to isDisabled - Remove stopPropagation from add directory button as not needed with onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate KnowledgeFiles Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update three Button components with Hero UI API: - Add file button: type="primary" to variant="solid" color="primary", icon to startContent, disabled to isDisabled - Refresh button: type="text" to variant="light", icon to isIconOnly, onClick to onPress - Delete button: type="text" danger to variant="light" color="danger", icon to isIconOnly, onClick to onPress - Remove stopPropagation from add file button as not needed with onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate KnowledgeNotes Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update three Button components with Hero UI API: - Add note button: type="primary" to variant="solid" color="primary", icon to startContent, disabled to isDisabled - Edit button: type="text" to variant="light", icon to isIconOnly, onClick to onPress - Delete button: type="text" danger to variant="light" color="danger", icon to isIconOnly, onClick to onPress - Remove stopPropagation from add note button as not needed with onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate KnowledgeSitemaps Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update three Button components with Hero UI API: - Add sitemap button: type="primary" to variant="solid" color="primary", icon to startContent, disabled to isDisabled - Refresh button: type="text" to variant="light", icon to isIconOnly, onClick to onPress - Delete button: type="text" danger to variant="light" color="danger", icon to isIconOnly, onClick to onPress - Remove stopPropagation from add sitemap button as not needed with onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate KnowledgeUrls Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update three Button components with Hero UI API: - Add URL button: type="primary" to variant="solid" color="primary", icon to startContent, disabled to isDisabled - Refresh button: type="text" to variant="light", icon to isIconOnly, onClick to onPress - Delete button: type="text" danger to variant="light" color="danger", icon to isIconOnly, onClick to onPress - Remove stopPropagation from add URL button as not needed with onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate KnowledgeVideos Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update three Button components with Hero UI API: - Add video button: type="primary" to variant="solid" color="primary", icon to startContent, disabled to isDisabled - Refresh button: type="text" to variant="light", icon to isIconOnly, onClick to onPress - Delete button: type="text" danger to variant="light" color="danger", icon to isIconOnly, onClick to onPress - Remove stopPropagation from add video button as not needed with onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate MinAppsPage Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update two settings Button components with Hero UI API: - type="text" to variant="light" - icon prop to isIconOnly with child content - onClick to onPress event handler - Maintain className="nodrag" for draggable interface 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate MiniAppSettings Buttons from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update two Button components with Hero UI API: - Swap button: onClick to onPress event handler - Reset button: onClick to onPress event handler - Buttons use default Hero UI styling without additional props 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate NewAppButton from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update two Button components with Hero UI API: - Upload button: icon to startContent - Save button: type="primary" htmlType="submit" to variant="solid" color="primary" type="submit" - Maintain form submission functionality with type="submit" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: standardize button imports from @cherrystudio/ui * refactor(KnowledgeContent): replace icon prop with startContent in Button Improve consistency with component library by using startContent prop instead of children for icons * refactor(KnowledgeVideos): update button components to use startContent prop Use startContent prop for icons in buttons to improve consistency with the design system * refactor(MinAppsPage): improve button component structure by using startContent prop * feat: migrate AihubmixPage Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - size="small" to size="sm" - icon to startContent - onClick to onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate DmxapiPage Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - size="small" to size="sm" - icon to startContent - onClick to onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate NewApiPage Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - size="small" to size="sm" - icon to startContent - onClick to onPress - type="primary" to variant="solid" color="primary" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate SiliconPage Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - size="small" to size="sm" - icon to startContent - onClick to onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate TokenFluxPage Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - size="small" to size="sm" - icon to startContent - onClick to onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate ZhipuPage Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - type="text" to variant="light" - icon to startContent - onClick to onPress - disabled to isDisabled 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate Artboard Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - onClick to onPress for NavigationButton and CancelButton - type="link" to variant="light" - Maintain styled-components usage for NavigationButton and CancelButton 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate DynamicFormRender Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - icon to startContent - onClick to onPress - size="small" to size="sm" - danger to color="danger" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: convert Button inline styles to Tailwind CSS - Replace style={{borderTopLeftRadius: 0, borderBottomLeftRadius: 0, height: '32px'}} with className="rounded-l-none h-8" - Replace style={{flexShrink: 0, minWidth: 'auto', padding: '0 8px'}} with className="shrink-0 min-w-0 px-2" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate ImageUploader Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - size="small" to size="sm" - onClick to onPress 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(Artboard): replace inline styles with tailwind classes Use tailwind classes for consistent styling of navigation buttons instead of inline styles * feat: migrate AboutSettings Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - onClick to onPress for all Button components - loading to isLoading for CheckUpdateButton - disabled to isDisabled for CheckUpdateButton - Maintain CheckUpdateButton styled component 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate AssistantMemorySettings Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - type="text" to variant="light" + isIconOnly - icon to startContent - onClick to onPress - size="small" to size="sm" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate AssistantModelSettings Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - icon to startContent - onClick to onPress - variant="filled" to variant="solid" - danger + type="primary" to color="danger" variant="solid" - Add isIconOnly for icon-only buttons - Maintain ModelSelectButton styled component 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate AssistantPromptSettings Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - type="primary" to variant="solid" color="primary" - icon to startContent - onClick to onPress - Convert inline styles to Tailwind CSS: - style={{fontSize: 18, padding: '4px', minWidth: '28px', height: '28px'}} to className="text-lg p-1 min-w-7 h-7" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: consolidate Button imports from @cherrystudio/ui Move all Button imports from @cherrystudio/ui to be grouped with other imports from the same package for better consistency and maintainability * feat: migrate AssistantRegularPromptsSettings Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - type="text" to variant="light" - icon to startContent - onClick to onPress - Add isIconOnly for icon-only buttons - danger to color="danger" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: migrate DataSettings Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Update Button props with Hero UI API: - onClick to onPress for all buttons - icon to startContent for backup/restore buttons - danger to color="danger" for reset button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(NutstoreSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Update type/danger props to variant/color system - Convert loading to isLoading prop - Convert disabled to isDisabled prop - Update ghost prop to variant="ghost" - Add isIconOnly for folder icon button - Migrate startContent pattern for icons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(S3Settings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert icon props to startContent pattern - Convert loading to isLoading prop - Convert disabled to isDisabled prop 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(SiyuanSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(WebDavSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert icon props to startContent pattern - Convert loading to isLoading prop - Convert disabled to isDisabled prop 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(YuqueSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(DisplaySettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert icon props to startContent pattern - Convert variant="text" to variant="light" - Add isIconOnly for icon-only buttons - Replace inline styles with Tailwind CSS classes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(PreprocessProviderSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Convert type="text" to variant="light" - Convert size="small" to size="sm" - Convert icon to startContent pattern - Add isIconOnly for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(NotionSettings): replace antd Button with cherrystudio Button and update prop Update the Button import to use cherrystudio's component instead of antd's * refactor(settings): migrate Button props to use startContent and isDisabled Update Button components in LocalBackupSettings to use startContent instead of icon and isDisabled instead of disabled for consistency with the updated UI library * refactor(JoplinSettings): replace Button import and update onPress prop Use Button component from @cherrystudio/ui instead of antd Update onClick to onPress for consistency with component API * refactor(MarkdownExportSettings): replace antd Button with cherrystudio Button in markdown export Update the Button component import and props to use the cherrystudio UI library version instead of antd for consistency * refactor: organize imports in settings components Move Button import from cherrystudio/ui to be grouped with other imports from the same package for better consistency and readability * refactor(AddMcpServerModal): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert icon prop to startContent pattern 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(BuiltinMCPServerList): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Convert type="text" to variant="light" - Convert size="small" to size="sm" - Convert icon to startContent pattern - Convert disabled to isDisabled prop - Add isIconOnly for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(InstallNpxUv): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert type="primary" to variant="solid" color="primary" - Convert type="link" to variant="light" - Convert shape="circle" to radius="full" - Convert size="small" to size="sm" - Convert loading/disabled to isLoading/isDisabled - Convert icon to startContent pattern - Add isIconOnly for icon-only button - Convert green color to success color 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(McpServerCard): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers (removing e.stopPropagation) - Convert type="text" to variant="light" - Convert size="small" to size="sm" - Convert shape="circle" to radius="full" - Convert danger to color="danger" - Convert icon to startContent pattern - Add isIconOnly for icon-only buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(MCPSettings): reorder Button imports for consistency Move Button imports to be grouped with other UI component imports for better readability and maintainability * refactor(McpServersList): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert type="default" to variant="solid" - Convert shape="round" to radius="full" - Convert icon to startContent pattern 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(McpServerCard): remove unused event parameter from click handlers The event parameter was not being used in handleOpenUrl and onClickDetails handlers, so it was removed to simplify the code. * refactor(McpServerCard): remove data-no-dnd attribute from Button * refactor(McpSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert danger to color="danger" - Convert type="text" to variant="light" - Convert type="primary" to variant="solid" color="primary" - Convert shape="round" to radius="full" - Convert loading/disabled to isLoading/isDisabled - Convert icon to startContent pattern - Add isIconOnly for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(McpSettingsNavbar): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Convert type="text" to variant="light" - Convert size="small" to size="sm" - Convert icon to startContent pattern - Replace inline styles with Tailwind CSS classes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(NpxSearch): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Convert type="text" to variant="light" - Convert size="small" to size="sm" - Convert icon to startContent pattern - Add isIconOnly for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(SyncServersPopup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert type="default" to variant="solid" - Convert type="primary" to variant="solid" color="primary" - Convert loading/disabled to isLoading/isDisabled 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(MCPSettings/index): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert type="default" to variant="solid" - Convert shape="circle" to radius="full" - Convert icon to startContent pattern - Add isIconOnly for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(MemorySettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Convert type="text" to variant="light" - Convert type="primary" to variant="solid" color="primary" - Convert size="large" to size="lg" - Convert size="small" to size="sm" - Convert loading/disabled to isLoading/isDisabled - Convert danger to color="danger" - Convert icon to startContent pattern - Add isIconOnly for icon-only buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(UserSelector): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Convert type="default" to variant="solid" - Convert icon to startContent pattern - Add isIconOnly for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(DefaultAssistantSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Convert type="text" to variant="light" - Convert icon to startContent pattern - Add isIconOnly for icon-only button - Replace inline styles with Tailwind CSS classes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(QuickModelPopup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Change icon prop to startContent - Update type="text" to variant="light" - Add isIconOnly prop for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(NotesSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for all buttons - Change type="default" to variant="solid" - Change type="primary" to color="primary" - Update loading to isLoading prop - Update disabled to isDisabled prop - Change icon prop to startContent - Replace inline style with Tailwind CSS class (ml-2) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(AnthropicSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Change type="primary" to color="primary" - Update loading to isLoading prop 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ModelEditContent): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for all buttons - Change size="small" to size="sm" - Update icon prop to startContent for save and reset buttons - Change iconPosition="end" to endContent for more settings toggle - Update type="text" to variant="light" and add isIconOnly for reset button - Change type="primary" to color="primary" - Replace htmlType="submit" with type="submit" - Update variant="filled" to variant="solid" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ModelTypeSelector): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Change size="small" to size="sm" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(GithubCopilotSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for all buttons - Change type="primary" to color="primary" - Change type="primary" danger to color="danger" - Update size="small" to size="sm" - Update loading to isLoading prop - Update disabled to isDisabled prop - Change icon prop to startContent for copy button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(AddModelPopup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Change type="primary" to color="primary" - Replace htmlType="submit" with type="submit" - Change size="middle" to size="md" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ModelList): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for all buttons - Change type="text" to variant="light" and add isIconOnly for icon button - Change type="primary" to color="primary" - Change type="default" to variant="solid" - Update disabled to isDisabled prop - Change icon prop to startContent for all buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ModelListGroup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Change type="text" to variant="light" - Update disabled to isDisabled prop - Change icon prop to startContent - Remove e.stopPropagation() as no longer needed - Add isIconOnly prop for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ModelListItem): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for both buttons - Change type="text" to variant="light" - Update disabled to isDisabled prop - Change icon prop to startContent for both buttons - Add isIconOnly prop for icon-only buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(NewApiAddModelPopup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Change type="primary" to color="primary" - Replace htmlType="submit" with type="submit" - Change size="middle" to size="md" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(NewApiBatchAddModelPopup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Change type="primary" to color="primary" - Replace htmlType="submit" with type="submit" - Change size="middle" to size="md" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ProviderList): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Update disabled to isDisabled prop - Change icon prop to startContent - Keep existing style attributes for custom styling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ProviderOAuth): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for both buttons - Change shape="round" to radius="full" - Change icon prop to startContent for both buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(UrlSchemaInfoPopup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Change type="link" to variant="light" - Change size="small" to size="sm" - Change icon prop to startContent - Add isIconOnly prop for icon-only button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(QuickAssistantSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for both styled buttons - Change type="primary" to color="primary" - Change type="default" to color="default" - Update styled component to use new Button from @cherrystudio/ui 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(QuickPhraseSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for all buttons - Change type="text" to variant="light" - Change icon prop to startContent for all buttons - Change danger prop to color="danger" - Add isIconOnly prop for all icon-only buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(SelectionAssistantSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for both buttons - Change type="link" to variant="light" - Change icon prop to startContent - Keep existing style attributes for custom styling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ActionsListItem): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for all buttons - Change type="link" to variant="light" - Change size="small" to size="sm" - Change danger prop to color="danger" - Add isIconOnly prop for all icon-only buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(MacProcessTrustHintModal): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for both buttons - Change type="link" to variant="light" - Change type="primary" to color="primary" - Keep existing style attributes for custom styling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(SelectionActionSearchModal): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler - Change type="link" to variant="light" - Change size="small" to size="sm" - Keep existing style attributes for custom styling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(SelectionFilterListModal): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handler for both modal buttons - Change type="primary" to color="primary" - Keep existing key attributes for modal footer 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(SettingsActionsListHeader): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers - Update icon prop to startContent with Plus icon - Change disabled to isDisabled - Add color="primary" for primary button style - Update styled ResetButton to use variant="light" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ShortcutSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for all buttons - Update icon prop to startContent for icon buttons - Change disabled to isDisabled - Convert size="small" to size="sm" - Replace shape="circle" with isIconOnly for circular buttons - Migrate reset undo button, clear button, and reset all button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(ApiServerSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for all buttons - Update icon prop to startContent for documentation and copy buttons - Change type="primary" to color="primary" - Convert type="link" to variant="light" for regenerate button - Change disabled to isDisabled for input button and regenerate button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(CustomLanguageModal): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for modal footer buttons - Change type="primary" to color="primary" for save button - Convert icon prop to startContent with isIconOnly for emoji button - Migrate cancel, save, and emoji picker buttons to Hero UI API 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(CustomLanguageSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for all buttons - Update icon prop to startContent for edit, delete, and add buttons - Change type="primary" to color="primary" for add button - Convert danger prop to color="danger" for delete button - Migrate table action buttons and primary add button to Hero UI API 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(AddSubscribePopup): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert type="primary" to color="primary" for submit button - Change htmlType="submit" to type="submit" following Hero UI API - Migrate form submit button from antd to Hero UI 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(BlacklistSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for all buttons - Change type="primary" to color="primary" for subscribe buttons - Convert ghost prop to variant="ghost" - Change disabled to isDisabled for all button states - Migrate save, add subscribe, update subscribe, and delete buttons 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(WebSearchProviderSetting): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for API key list and check buttons - Change type="text" to variant="light" for API key list button - Convert icon prop to startContent with isIconOnly for list button - Update size="small" to size="sm" - Change ghost prop to variant="ghost" and type to color for check button - Convert disabled to isDisabled for API checking state 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(TranslateSettings): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress for more settings button - Simple migration for modal footer button 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(MigrateApp): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for all migration buttons - Change type="primary" to color="primary" for primary buttons - Convert disabled to isDisabled for migration in progress button - Change size="small" to size="sm" for debug button - Convert type="dashed" to variant="bordered" for styled buttons - Migrate all buttons in migration workflow stages 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(SelectionActionApp): migrate Button from antd to @cherrystudio/ui - Replace antd Button import with @cherrystudio/ui Button - Convert onClick to onPress handlers for all window control buttons - Change type="text" to variant="light" for all title bar buttons - Update icon prop to startContent for pin, opacity, minimize, and close buttons - Add isIconOnly prop for all icon-only buttons in the title bar - Migrate styled WinButton component to use Hero UI Button as base 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * style(ActionIconButton): remove fixed dimensions and add size prop Simplify button styling by removing fixed height/width and using size="sm" prop instead * refactor(AssistantPromptSettings): migrate from antd Popover to hero-ui components Replace antd Popover with hero-ui Popover and Tooltip components for better consistency Rename EmojiButtonWrapper to EmojiDeleteButtonWrapper for clarity * style(AssistantModelSettings): add size prop to delete button in model settings * style(settings): standardize button sizes and replace Space.Compact with Flex Consistently apply 'sm' size to buttons across settings components and replace deprecated Space.Compact with Flex component for better layout consistency * refactor(ApiServerSettings): replace custom buttons with standard Button component remove custom styled InputButton and RegenerateButton components in favor of using the standard Button component with appropriate props * style(ProviderSetting): make settings button icon-only for consistency * style(ui): update icon styling and button props remove global lucide icon color override update button components to use consistent props * style(ProviderList): adjust button size to match design * feat(theme): add foreground color calculation for primary theme Calculate and set foreground color based on primary theme color to ensure proper contrast * style(KnowledgeFiles): make button size consistent with other buttons * test: update test snapshots for button components Update test snapshots to reflect changes in button styling and accessibility attributes. The changes include updated class names, ripple effects, and focus states. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com> Co-authored-by: MyPrototypeWhat <daoquqiexing@gmail.com>
This commit is contained in:
+1
-1
@@ -145,7 +145,7 @@ export default defineConfig([
|
||||
paths: [
|
||||
{
|
||||
name: 'antd',
|
||||
importNames: ['Flex', 'Switch', 'message',],
|
||||
importNames: ['Flex', 'Switch', 'message', 'Button'],
|
||||
message:
|
||||
'❌ Do not import this component from antd. Use our custom components instead: import { ... } from "@cherrystudio/ui"'
|
||||
},
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { ButtonProps as HeroUIButtonProps } from '@heroui/react'
|
||||
import { Button as HeroUIButton } from '@heroui/react'
|
||||
|
||||
export interface ButtonProps extends HeroUIButtonProps {}
|
||||
|
||||
const Button = ({ ...props }: ButtonProps) => {
|
||||
return <HeroUIButton {...props} />
|
||||
}
|
||||
|
||||
Button.displayName = 'Button'
|
||||
|
||||
export default Button
|
||||
@@ -1,4 +1,5 @@
|
||||
// Base Components
|
||||
export { default as Button, type ButtonProps } from './base/Button'
|
||||
export { default as CopyButton } from './base/CopyButton'
|
||||
export { default as CustomCollapse } from './base/CustomCollapse'
|
||||
export { default as CustomTag } from './base/CustomTag'
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
// Original path: src/renderer/src/components/Preview/ImageToolButton.tsx
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Tooltip } from 'antd'
|
||||
import { memo } from 'react'
|
||||
|
||||
interface ImageToolButtonProps {
|
||||
tooltip: string
|
||||
icon: React.ReactNode
|
||||
onClick: () => void
|
||||
onPress: () => void
|
||||
}
|
||||
|
||||
const ImageToolButton = ({ tooltip, icon, onClick }: ImageToolButtonProps) => {
|
||||
const ImageToolButton = ({ tooltip, icon, onPress }: ImageToolButtonProps) => {
|
||||
return (
|
||||
<Tooltip title={tooltip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Button shape="circle" icon={icon} onClick={onClick} role="button" aria-label={tooltip} />
|
||||
<Button radius="full" isIconOnly onPress={onPress} aria-label={tooltip}>
|
||||
{icon}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import { Button } from '../../../src/components'
|
||||
|
||||
const meta: Meta<typeof Button> = {
|
||||
title: 'Components/Base/Button',
|
||||
component: Button,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: ['solid', 'bordered', 'light', 'flat', 'faded', 'shadow', 'ghost']
|
||||
},
|
||||
color: {
|
||||
control: { type: 'select' },
|
||||
options: ['default', 'primary', 'secondary', 'success', 'warning', 'danger']
|
||||
},
|
||||
size: {
|
||||
control: { type: 'select' },
|
||||
options: ['sm', 'md', 'lg']
|
||||
},
|
||||
radius: {
|
||||
control: { type: 'select' },
|
||||
options: ['none', 'sm', 'md', 'lg', 'full']
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' }
|
||||
},
|
||||
isLoading: {
|
||||
control: { type: 'boolean' }
|
||||
},
|
||||
fullWidth: {
|
||||
control: { type: 'boolean' }
|
||||
},
|
||||
isIconOnly: {
|
||||
control: { type: 'boolean' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
// 基础按钮
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: 'Button'
|
||||
}
|
||||
}
|
||||
|
||||
// 不同变体
|
||||
export const Variants: Story = {
|
||||
render: () => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button variant="solid">Solid</Button>
|
||||
<Button variant="bordered">Bordered</Button>
|
||||
<Button variant="light">Light</Button>
|
||||
<Button variant="flat">Flat</Button>
|
||||
<Button variant="faded">Faded</Button>
|
||||
<Button variant="shadow">Shadow</Button>
|
||||
<Button variant="ghost">Ghost</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 不同颜色
|
||||
export const Colors: Story = {
|
||||
render: () => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button color="default">Default</Button>
|
||||
<Button color="primary">Primary</Button>
|
||||
<Button color="secondary">Secondary</Button>
|
||||
<Button color="success">Success</Button>
|
||||
<Button color="warning">Warning</Button>
|
||||
<Button color="danger">Danger</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 不同尺寸
|
||||
export const Sizes: Story = {
|
||||
render: () => (
|
||||
<div className="flex gap-2 items-center">
|
||||
<Button size="sm">Small</Button>
|
||||
<Button size="md">Medium</Button>
|
||||
<Button size="lg">Large</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 不同圆角
|
||||
export const Radius: Story = {
|
||||
render: () => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button radius="none">None</Button>
|
||||
<Button radius="sm">Small</Button>
|
||||
<Button radius="md">Medium</Button>
|
||||
<Button radius="lg">Large</Button>
|
||||
<Button radius="full">Full</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 状态
|
||||
export const States: Story = {
|
||||
render: () => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button>Normal</Button>
|
||||
<Button isDisabled>Disabled</Button>
|
||||
<Button isLoading>Loading</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 带图标
|
||||
export const WithIcons: Story = {
|
||||
render: () => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button startContent={<span>📧</span>}>Email</Button>
|
||||
<Button endContent={<span>→</span>}>Next</Button>
|
||||
<Button isIconOnly>🔍</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 全宽按钮
|
||||
export const FullWidth: Story = {
|
||||
render: () => (
|
||||
<div className="w-96">
|
||||
<Button fullWidth color="primary">
|
||||
Full Width Button
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 交互示例
|
||||
export const Interactive: Story = {
|
||||
render: () => (
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button onPress={() => alert('Button pressed!')}>Click Me</Button>
|
||||
<Button onPress={() => console.log('Primary action')} color="primary" variant="solid">
|
||||
Primary Action
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -170,10 +170,6 @@ ul {
|
||||
display: flow-root;
|
||||
}
|
||||
|
||||
.lucide:not(.lucide-custom) {
|
||||
color: var(--color-icon);
|
||||
}
|
||||
|
||||
::highlight(search-matches) {
|
||||
background-color: var(--color-background-highlight);
|
||||
color: var(--color-highlight);
|
||||
|
||||
@@ -1,31 +1,34 @@
|
||||
import { cn } from '@cherrystudio/ui'
|
||||
import type { ButtonProps } from 'antd'
|
||||
import { Button } from 'antd'
|
||||
import { Button, type ButtonProps } from '@cherrystudio/ui'
|
||||
import React, { memo } from 'react'
|
||||
|
||||
interface ActionIconButtonProps extends ButtonProps {
|
||||
children: React.ReactNode
|
||||
interface ActionIconButtonProps extends Omit<ButtonProps, 'ref'> {
|
||||
icon: React.ReactNode
|
||||
active?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple action button rendered as an icon
|
||||
*/
|
||||
const ActionIconButton: React.FC<ActionIconButtonProps> = ({ children, active = false, className, ...props }) => {
|
||||
const ActionIconButton: React.FC<ActionIconButtonProps> = ({ icon, active = false, className, ...props }) => {
|
||||
return (
|
||||
<Button
|
||||
type="text"
|
||||
shape="circle"
|
||||
size="sm"
|
||||
variant="light"
|
||||
radius="full"
|
||||
isIconOnly
|
||||
startContent={icon}
|
||||
className={cn(
|
||||
'flex h-[30px] w-[30px] cursor-pointer flex-row items-center justify-center border-none p-0 text-base transition-all duration-300 ease-in-out [&_.anticon]:text-icon [&_.icon-a-addchat]:mb-[-2px] [&_.icon-a-addchat]:text-lg [&_.icon]:text-icon [&_.iconfont]:text-icon [&_.lucide]:text-icon',
|
||||
'flex cursor-pointer flex-row items-center justify-center border-none p-0 text-base transition-all duration-300 ease-in-out [&_.anticon]:text-icon [&_.icon-a-addchat]:mb-[-2px] [&_.icon-a-addchat]:text-lg [&_.icon]:text-icon [&_.iconfont]:text-icon [&_.lucide]:text-icon',
|
||||
active &&
|
||||
'[&_.anticon]:text-primary! [&_.icon]:text-primary! [&_.iconfont]:text-primary! [&_.lucide]:text-primary!',
|
||||
className
|
||||
)}
|
||||
{...props}>
|
||||
{children}
|
||||
</Button>
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
ActionIconButton.displayName = 'ActionIconButton'
|
||||
|
||||
export default memo(ActionIconButton)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { CodeOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { extractHtmlTitle, getFileNameFromHtmlTitle } from '@renderer/utils/formats'
|
||||
import type { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Button } from 'antd'
|
||||
import { Code, DownloadIcon, Globe, LinkIcon, Sparkles } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
@@ -89,20 +89,32 @@ const HtmlArtifactsCard: FC<Props> = ({ html, onSave, isStreaming = false }) =>
|
||||
</TerminalContent>
|
||||
</TerminalPreview>
|
||||
<ButtonContainer>
|
||||
<Button icon={<CodeOutlined />} onClick={() => setIsPopupOpen(true)} type="primary">
|
||||
<Button startContent={<CodeOutlined />} onPress={() => setIsPopupOpen(true)} color="primary">
|
||||
{t('chat.artifacts.button.preview')}
|
||||
</Button>
|
||||
</ButtonContainer>
|
||||
</>
|
||||
) : (
|
||||
<ButtonContainer>
|
||||
<Button icon={<CodeOutlined />} onClick={() => setIsPopupOpen(true)} type="text" disabled={!hasContent}>
|
||||
<Button
|
||||
startContent={<CodeOutlined />}
|
||||
onPress={() => setIsPopupOpen(true)}
|
||||
variant="light"
|
||||
isDisabled={!hasContent}>
|
||||
{t('chat.artifacts.button.preview')}
|
||||
</Button>
|
||||
<Button icon={<LinkIcon size={14} />} onClick={handleOpenExternal} type="text" disabled={!hasContent}>
|
||||
<Button
|
||||
startContent={<LinkIcon size={14} />}
|
||||
onPress={handleOpenExternal}
|
||||
variant="light"
|
||||
isDisabled={!hasContent}>
|
||||
{t('chat.artifacts.button.openExternal')}
|
||||
</Button>
|
||||
<Button icon={<DownloadIcon size={14} />} onClick={handleDownload} type="text" disabled={!hasContent}>
|
||||
<Button
|
||||
startContent={<DownloadIcon size={14} />}
|
||||
onPress={handleDownload}
|
||||
variant="light"
|
||||
isDisabled={!hasContent}>
|
||||
{t('code_block.download.label')}
|
||||
</Button>
|
||||
</ButtonContainer>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CodeEditor, type CodeEditorHandles } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { CopyIcon, FilePngIcon } from '@renderer/components/Icons'
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
@@ -7,7 +8,7 @@ import { useTemporaryValue } from '@renderer/hooks/useTemporaryValue'
|
||||
import { classNames } from '@renderer/utils'
|
||||
import { extractHtmlTitle, getFileNameFromHtmlTitle } from '@renderer/utils/formats'
|
||||
import { captureScrollableIframeAsBlob, captureScrollableIframeAsDataURL } from '@renderer/utils/image'
|
||||
import { Button, Dropdown, Modal, Splitter, Tooltip, Typography } from 'antd'
|
||||
import { Dropdown, Modal, Splitter, Tooltip, Typography } from 'antd'
|
||||
import { Camera, Check, Code, Eye, Maximize2, Minimize2, SaveIcon, SquareSplitHorizontal, X } from 'lucide-react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -83,24 +84,24 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
<HeaderCenter>
|
||||
<ViewControls onDoubleClick={(e) => e.stopPropagation()}>
|
||||
<ViewButton
|
||||
size="small"
|
||||
type={viewMode === 'split' ? 'primary' : 'default'}
|
||||
icon={<SquareSplitHorizontal size={14} />}
|
||||
onClick={() => setViewMode('split')}>
|
||||
size="sm"
|
||||
color={viewMode === 'split' ? 'primary' : 'default'}
|
||||
startContent={<SquareSplitHorizontal size={14} />}
|
||||
onPress={() => setViewMode('split')}>
|
||||
{t('html_artifacts.split')}
|
||||
</ViewButton>
|
||||
<ViewButton
|
||||
size="small"
|
||||
type={viewMode === 'code' ? 'primary' : 'default'}
|
||||
icon={<Code size={14} />}
|
||||
onClick={() => setViewMode('code')}>
|
||||
size="sm"
|
||||
color={viewMode === 'code' ? 'primary' : 'default'}
|
||||
startContent={<Code size={14} />}
|
||||
onPress={() => setViewMode('code')}>
|
||||
{t('html_artifacts.code')}
|
||||
</ViewButton>
|
||||
<ViewButton
|
||||
size="small"
|
||||
type={viewMode === 'preview' ? 'primary' : 'default'}
|
||||
icon={<Eye size={14} />}
|
||||
onClick={() => setViewMode('preview')}>
|
||||
size="sm"
|
||||
color={viewMode === 'preview' ? 'primary' : 'default'}
|
||||
startContent={<Eye size={14} />}
|
||||
onPress={() => setViewMode('preview')}>
|
||||
{t('html_artifacts.preview')}
|
||||
</ViewButton>
|
||||
</ViewControls>
|
||||
@@ -126,16 +127,17 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
]
|
||||
}}>
|
||||
<Tooltip title={t('html_artifacts.capture.label')} mouseLeaveDelay={0}>
|
||||
<Button type="text" icon={<Camera size={16} />} className="nodrag" />
|
||||
<Button variant="light" startContent={<Camera size={16} />} isIconOnly className="nodrag" />
|
||||
</Tooltip>
|
||||
</Dropdown>
|
||||
<Button
|
||||
onClick={() => setIsFullscreen(!isFullscreen)}
|
||||
type="text"
|
||||
icon={isFullscreen ? <Minimize2 size={16} /> : <Maximize2 size={16} />}
|
||||
onPress={() => setIsFullscreen(!isFullscreen)}
|
||||
variant="light"
|
||||
startContent={isFullscreen ? <Minimize2 size={16} /> : <Maximize2 size={16} />}
|
||||
isIconOnly
|
||||
className="nodrag"
|
||||
/>
|
||||
<Button onClick={onClose} type="text" icon={<X size={16} />} className="nodrag" />
|
||||
<Button onPress={onClose} variant="light" startContent={<X size={16} />} isIconOnly className="nodrag" />
|
||||
</HeaderRight>
|
||||
</ModalHeader>
|
||||
)
|
||||
@@ -163,18 +165,13 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
/>
|
||||
<ToolbarWrapper>
|
||||
<Tooltip title={t('code_block.edit.save.label')} mouseLeaveDelay={0}>
|
||||
<ToolbarButton
|
||||
shape="circle"
|
||||
size="large"
|
||||
icon={
|
||||
saved ? (
|
||||
<Check size={16} color="var(--color-status-success)" />
|
||||
) : (
|
||||
<SaveIcon size={16} className="custom-lucide" />
|
||||
)
|
||||
}
|
||||
onClick={handleSave}
|
||||
/>
|
||||
<ToolbarButton radius="full" size="lg" isIconOnly onPress={handleSave}>
|
||||
{saved ? (
|
||||
<Check size={16} color="var(--color-status-success)" />
|
||||
) : (
|
||||
<SaveIcon size={16} className="custom-lucide" />
|
||||
)}
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
</ToolbarWrapper>
|
||||
</CodeSection>
|
||||
|
||||
@@ -364,23 +364,33 @@ export const ContentSearch = React.forwardRef<ContentSearchRef, Props>(
|
||||
<ToolBar>
|
||||
{showUserToggle && (
|
||||
<Tooltip title={t('button.includes_user_questions')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<ActionIconButton onClick={userOutlinedButtonOnClick}>
|
||||
<User size={18} style={{ color: includeUser ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={userOutlinedButtonOnClick}
|
||||
isIconOnly
|
||||
icon={
|
||||
<User size={18} style={{ color: includeUser ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('button.case_sensitive')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<ActionIconButton onClick={caseSensitiveButtonOnClick}>
|
||||
<CaseSensitive
|
||||
size={18}
|
||||
style={{ color: isCaseSensitive ? 'var(--color-link)' : 'var(--color-icon)' }}
|
||||
/>
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={caseSensitiveButtonOnClick}
|
||||
icon={
|
||||
<CaseSensitive
|
||||
size={18}
|
||||
style={{ color: isCaseSensitive ? 'var(--color-link)' : 'var(--color-icon)' }}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('button.whole_word')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<ActionIconButton onClick={wholeWordButtonOnClick}>
|
||||
<WholeWord size={18} style={{ color: isWholeWord ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={wholeWordButtonOnClick}
|
||||
icon={
|
||||
<WholeWord size={18} style={{ color: isWholeWord ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ToolBar>
|
||||
</InputWrapper>
|
||||
@@ -397,15 +407,17 @@ export const ContentSearch = React.forwardRef<ContentSearchRef, Props>(
|
||||
)}
|
||||
</SearchResults>
|
||||
<ToolBar>
|
||||
<ActionIconButton onClick={prevButtonOnClick} disabled={allRanges.length === 0}>
|
||||
<ChevronUp size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onClick={nextButtonOnClick} disabled={allRanges.length === 0}>
|
||||
<ChevronDown size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onClick={closeButtonOnClick}>
|
||||
<X size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={prevButtonOnClick}
|
||||
isDisabled={allRanges.length === 0}
|
||||
icon={<ChevronUp size={18} />}
|
||||
/>
|
||||
<ActionIconButton
|
||||
onPress={nextButtonOnClick}
|
||||
isDisabled={allRanges.length === 0}
|
||||
icon={<ChevronDown size={18} />}
|
||||
/>
|
||||
<ActionIconButton onPress={closeButtonOnClick} icon={<X size={18} />} />
|
||||
</ToolBar>
|
||||
</SearchBarContainer>
|
||||
</NarrowLayout>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from 'antd'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@@ -22,7 +22,7 @@ const ExpandableText = ({
|
||||
|
||||
const button = useMemo(() => {
|
||||
return (
|
||||
<Button type="link" onClick={toggleExpand} style={{ alignSelf: 'flex-end' }}>
|
||||
<Button variant="light" onPress={toggleExpand} className="self-end">
|
||||
{isExpanded ? t('common.collapse') : t('common.expand')}
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import AiProvider from '@renderer/aiCore'
|
||||
import { RefreshIcon } from '@renderer/components/Icons'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
import type { Model } from '@renderer/types'
|
||||
import { getErrorMessage } from '@renderer/utils'
|
||||
import { Button, InputNumber, Space, Tooltip } from 'antd'
|
||||
import { InputNumber, Space, Tooltip } from 'antd'
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -77,9 +78,11 @@ const InputEmbeddingDimension = ({
|
||||
<Button
|
||||
role="button"
|
||||
aria-label="Get embedding dimension"
|
||||
disabled={disabled || loading}
|
||||
onClick={handleFetchDimension}
|
||||
icon={<RefreshIcon size={16} className={loading ? 'animation-rotate' : ''} />}
|
||||
isDisabled={disabled || loading}
|
||||
onPress={handleFetchDimension}
|
||||
size="sm"
|
||||
startContent={<RefreshIcon size={16} className={loading ? 'animation-rotate' : ''} />}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
</Space.Compact>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { DeleteOutlined, ExclamationCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button, Flex } from '@cherrystudio/ui'
|
||||
import { restoreFromLocal } from '@renderer/services/BackupService'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Button, Modal, Table, Tooltip } from 'antd'
|
||||
import { Modal, Table, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -191,18 +192,25 @@ export function LocalBackupManager({ visible, onClose, localBackupDir, restoreMe
|
||||
key: 'action',
|
||||
width: 160,
|
||||
render: (_: any, record: BackupFile) => (
|
||||
<>
|
||||
<Button type="link" onClick={() => handleRestore(record.fileName)} disabled={restoring || deleting}>
|
||||
<Flex>
|
||||
<Button
|
||||
className="inline-flex"
|
||||
size="sm"
|
||||
variant="light"
|
||||
onPress={() => handleRestore(record.fileName)}
|
||||
isDisabled={restoring || deleting}>
|
||||
{t('settings.data.local.backup.manager.restore.text')}
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => handleDeleteSingle(record.fileName)}
|
||||
disabled={deleting || restoring}>
|
||||
className="inline-flex"
|
||||
size="sm"
|
||||
variant="light"
|
||||
color="danger"
|
||||
onPress={() => handleDeleteSingle(record.fileName)}
|
||||
isDisabled={deleting || restoring}>
|
||||
{t('settings.data.local.backup.manager.delete.text')}
|
||||
</Button>
|
||||
</>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
]
|
||||
@@ -222,20 +230,21 @@ export function LocalBackupManager({ visible, onClose, localBackupDir, restoreMe
|
||||
width={800}
|
||||
centered
|
||||
transitionName="animation-move-down"
|
||||
classNames={{ footer: 'flex justify-end gap-1' }}
|
||||
footer={[
|
||||
<Button key="refresh" icon={<ReloadOutlined />} onClick={fetchBackupFiles} disabled={loading}>
|
||||
<Button key="refresh" startContent={<ReloadOutlined />} onPress={fetchBackupFiles} isDisabled={loading}>
|
||||
{t('settings.data.local.backup.manager.refresh')}
|
||||
</Button>,
|
||||
<Button
|
||||
key="delete"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={handleDeleteSelected}
|
||||
disabled={selectedRowKeys.length === 0 || deleting}
|
||||
loading={deleting}>
|
||||
color="danger"
|
||||
startContent={<DeleteOutlined />}
|
||||
onPress={handleDeleteSelected}
|
||||
isDisabled={selectedRowKeys.length === 0 || deleting}
|
||||
isLoading={deleting}>
|
||||
{t('settings.data.local.backup.manager.delete.selected')} ({selectedRowKeys.length})
|
||||
</Button>,
|
||||
<Button key="close" onClick={onClose}>
|
||||
<Button key="close" onPress={onClose}>
|
||||
{t('common.close')}
|
||||
</Button>
|
||||
]}>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { backupToLocal } from '@renderer/services/BackupService'
|
||||
import { Button, Input, Modal } from 'antd'
|
||||
import { Input, Modal } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -32,11 +33,12 @@ export function LocalBackupModal({
|
||||
open={isModalVisible}
|
||||
onOk={handleBackup}
|
||||
onCancel={handleCancel}
|
||||
classNames={{ footer: 'flex justify-end gap-1' }}
|
||||
footer={[
|
||||
<Button key="back" onClick={handleCancel}>
|
||||
<Button key="back" onPress={handleCancel}>
|
||||
{t('common.cancel')}
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" loading={backuping} onClick={handleBackup}>
|
||||
<Button key="submit" color="primary" isLoading={backuping} onPress={handleBackup}>
|
||||
{t('common.confirm')}
|
||||
</Button>
|
||||
]}>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
PushpinOutlined,
|
||||
ReloadOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import WindowControls from '@renderer/components/WindowControls'
|
||||
@@ -24,7 +25,7 @@ import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import type { MinAppType } from '@renderer/types'
|
||||
import { delay } from '@renderer/utils'
|
||||
import { clearWebviewState, getWebviewLoaded, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
||||
import { Alert, Avatar, Button, Drawer, Tooltip } from 'antd'
|
||||
import { Alert, Avatar, Drawer, Tooltip } from 'antd'
|
||||
import type { WebviewTag } from 'electron'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -129,7 +130,7 @@ const GoogleLoginTip = ({
|
||||
banner
|
||||
onClose={handleClose}
|
||||
action={
|
||||
<Button type="primary" size="small" onClick={openGoogleMinApp}>
|
||||
<Button color="primary" size="sm" onPress={openGoogleMinApp}>
|
||||
{t('common.open')} Google
|
||||
</Button>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import type { Model } from '@renderer/types'
|
||||
import type { TooltipProps } from 'antd'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
import ModelAvatar from './Avatar/ModelAvatar'
|
||||
@@ -23,7 +24,15 @@ const ModelSelectButton = ({ model, onSelectModel, modelFilter, noTooltip, toolt
|
||||
}, [model, modelFilter, onSelectModel])
|
||||
|
||||
const button = useMemo(() => {
|
||||
return <Button icon={<ModelAvatar model={model} size={22} />} type="text" shape="circle" onClick={onClick} />
|
||||
return (
|
||||
<Button
|
||||
startContent={<ModelAvatar model={model} size={22} />}
|
||||
variant="light"
|
||||
radius="full"
|
||||
isIconOnly
|
||||
onPress={onClick}
|
||||
/>
|
||||
)
|
||||
}, [model, onClick])
|
||||
|
||||
if (noTooltip) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { FolderIcon as NutstoreFolderIcon } from '@renderer/components/Icons/NutstoreIcons'
|
||||
import { Button, Input } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@@ -35,10 +36,10 @@ function NewFolder(props: NewFolderProps) {
|
||||
<NewFolderContainer>
|
||||
<FolderIcon className={props.className}></FolderIcon>
|
||||
<Input type="text" style={{ flex: 1 }} autoFocus value={name} onChange={(e) => setName(e.target.value)} />
|
||||
<Button type="primary" size="small" onClick={() => onConfirm(name)}>
|
||||
<Button color="primary" size="sm" onPress={() => onConfirm(name)}>
|
||||
{t('settings.data.nutstore.new_folder.button.confirm')}
|
||||
</Button>
|
||||
<Button type="default" size="small" onClick={() => onCancel()}>
|
||||
<Button size="sm" onPress={() => onCancel()}>
|
||||
{t('settings.data.nutstore.new_folder.button.cancel')}
|
||||
</Button>
|
||||
</NewFolderContainer>
|
||||
@@ -234,16 +235,14 @@ export function NustorePathSelectorFooter(props: FooterProps) {
|
||||
return (
|
||||
<FooterContainer className="justify-between">
|
||||
<RowFlex className="items-center gap-2">
|
||||
<Button onClick={props.returnPrev}>{t('settings.data.nutstore.pathSelector.return')}</Button>
|
||||
<Button size="small" type="link" onClick={props.mkdir}>
|
||||
<Button onPress={props.returnPrev}>{t('settings.data.nutstore.pathSelector.return')}</Button>
|
||||
<Button size="sm" variant="light" onPress={props.mkdir}>
|
||||
{t('settings.data.nutstore.new_folder.button.label')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
<RowFlex className="items-center gap-2">
|
||||
<Button type="default" onClick={props.cancel}>
|
||||
{t('settings.data.nutstore.new_folder.button.cancel')}
|
||||
</Button>
|
||||
<Button type="primary" onClick={props.confirm}>
|
||||
<Button onPress={props.cancel}>{t('settings.data.nutstore.new_folder.button.cancel')}</Button>
|
||||
<Button color="primary" onPress={props.confirm}>
|
||||
{t('backup.confirm.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button, type ButtonProps } from '@cherrystudio/ui'
|
||||
import { getProviderLabel } from '@renderer/i18n/label'
|
||||
import type { Provider } from '@renderer/types'
|
||||
import {
|
||||
@@ -8,8 +9,6 @@ import {
|
||||
oauthWithSiliconFlow,
|
||||
oauthWithTokenFlux
|
||||
} from '@renderer/utils/oauth'
|
||||
import type { ButtonProps } from 'antd'
|
||||
import { Button } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -55,7 +54,7 @@ const OAuthButton: FC<Props> = ({ provider, onSuccess, ...buttonProps }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Button type="primary" onClick={onAuth} shape="round" {...buttonProps}>
|
||||
<Button color="primary" onPress={onAuth} radius="full" {...buttonProps}>
|
||||
{t('settings.provider.oauth.button', { provider: getProviderLabel(provider.id) })}
|
||||
</Button>
|
||||
)
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { type HealthResult, HealthStatusIndicator } from '@renderer/components/HealthStatusIndicator'
|
||||
import { EditIcon } from '@renderer/components/Icons'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import type { ApiKeyWithStatus } from '@renderer/types/healthCheck'
|
||||
import { maskApiKey } from '@renderer/utils/api'
|
||||
import type { InputRef } from 'antd'
|
||||
import { Button, Input, List, Popconfirm, Tooltip, Typography } from 'antd'
|
||||
import { Input, List, Popconfirm, Tooltip, Typography } from 'antd'
|
||||
import { Check, Minus, X } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useEffect, useRef, useState } from 'react'
|
||||
@@ -93,79 +94,96 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
|
||||
return (
|
||||
<List.Item>
|
||||
{isEditing ? (
|
||||
<ItemInnerContainer style={{ gap: '10px' }}>
|
||||
<Input.Password
|
||||
ref={inputRef}
|
||||
value={editValue}
|
||||
onChange={(e) => setEditValue(e.target.value)}
|
||||
onPressEnter={handleSave}
|
||||
placeholder={t('settings.provider.api.key.new_key.placeholder')}
|
||||
style={{ flex: 1, fontSize: '14px', marginLeft: '-10px' }}
|
||||
spellCheck={false}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Flex className="items-center gap-0">
|
||||
<Tooltip title={t('common.save')}>
|
||||
<Button
|
||||
type={hasUnsavedChanges ? 'primary' : 'text'}
|
||||
icon={<Check size={16} />}
|
||||
onClick={handleSave}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.cancel')}>
|
||||
<Button type="text" icon={<X size={16} />} onClick={handleCancelEdit} disabled={disabled} />
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
</ItemInnerContainer>
|
||||
) : (
|
||||
<ItemInnerContainer style={{ gap: '10px' }}>
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography.Text style={{ color: 'white' }} copyable={{ text: keyStatus.key }}>
|
||||
{keyStatus.key}
|
||||
</Typography.Text>
|
||||
}
|
||||
mouseEnterDelay={0.5}
|
||||
placement="top"
|
||||
// 确保不留下明文
|
||||
destroyOnHidden>
|
||||
<span style={{ cursor: 'help' }}>{maskApiKey(keyStatus.key)}</span>
|
||||
</Tooltip>
|
||||
|
||||
<Flex className="items-center gap-2.5">
|
||||
<HealthStatusIndicator results={healthResults} loading={false} />
|
||||
|
||||
<ItemInnerContainer className="gap-2 px-3">
|
||||
{isEditing ? (
|
||||
<>
|
||||
<Input.Password
|
||||
ref={inputRef}
|
||||
value={editValue}
|
||||
onChange={(e) => setEditValue(e.target.value)}
|
||||
onPressEnter={handleSave}
|
||||
placeholder={t('settings.provider.api.key.new_key.placeholder')}
|
||||
style={{ flex: 1, fontSize: '14px' }}
|
||||
spellCheck={false}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Flex className="items-center gap-0">
|
||||
{showHealthCheck && (
|
||||
<Tooltip title={t('settings.provider.check')} mouseLeaveDelay={0}>
|
||||
<Tooltip title={t('common.save')}>
|
||||
<Button
|
||||
color={hasUnsavedChanges ? 'primary' : 'default'}
|
||||
variant={hasUnsavedChanges ? 'solid' : 'light'}
|
||||
startContent={<Check size={16} />}
|
||||
onPress={handleSave}
|
||||
isDisabled={disabled}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.cancel')}>
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<X size={16} />}
|
||||
onPress={handleCancelEdit}
|
||||
isDisabled={disabled}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography.Text style={{ color: 'white' }} copyable={{ text: keyStatus.key }}>
|
||||
{keyStatus.key}
|
||||
</Typography.Text>
|
||||
}
|
||||
mouseEnterDelay={0.5}
|
||||
placement="top"
|
||||
// 确保不留下明文
|
||||
destroyOnHidden>
|
||||
<span style={{ cursor: 'help' }}>{maskApiKey(keyStatus.key)}</span>
|
||||
</Tooltip>
|
||||
|
||||
<Flex className="items-center gap-2.5">
|
||||
<HealthStatusIndicator results={healthResults} loading={false} />
|
||||
|
||||
<Flex className="items-center gap-0">
|
||||
{showHealthCheck && (
|
||||
<Tooltip title={t('settings.provider.check')} mouseLeaveDelay={0}>
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<StreamlineGoodHealthAndWellBeing size={18} isActive={keyStatus.checking} />}
|
||||
onPress={onCheck}
|
||||
isDisabled={disabled}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('common.edit')} mouseLeaveDelay={0}>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<StreamlineGoodHealthAndWellBeing size={18} isActive={keyStatus.checking} />}
|
||||
onClick={onCheck}
|
||||
disabled={disabled}
|
||||
variant="light"
|
||||
startContent={<EditIcon size={16} />}
|
||||
onPress={handleEdit}
|
||||
isDisabled={disabled}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('common.edit')} mouseLeaveDelay={0}>
|
||||
<Button type="text" icon={<EditIcon size={16} />} onClick={handleEdit} disabled={disabled} />
|
||||
</Tooltip>
|
||||
<Popconfirm
|
||||
title={t('common.delete_confirm')}
|
||||
onConfirm={onRemove}
|
||||
disabled={disabled}
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ danger: true }}>
|
||||
<Tooltip title={t('common.delete')} mouseLeaveDelay={0}>
|
||||
<Button type="text" icon={<Minus size={16} />} disabled={disabled} />
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
<Popconfirm
|
||||
title={t('common.delete_confirm')}
|
||||
onConfirm={onRemove}
|
||||
disabled={disabled}
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ color: 'danger' }}>
|
||||
<Tooltip title={t('common.delete')} mouseLeaveDelay={0}>
|
||||
<Button variant="light" startContent={<Minus size={16} />} isDisabled={disabled} isIconOnly />
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ItemInnerContainer>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ItemInnerContainer>
|
||||
</List.Item>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
@@ -10,7 +11,7 @@ import { isProviderSupportAuth } from '@renderer/services/ProviderService'
|
||||
import type { PreprocessProviderId, WebSearchProviderId } from '@renderer/types'
|
||||
import type { ApiKeyWithStatus } from '@renderer/types/healthCheck'
|
||||
import { HealthStatus } from '@renderer/types/healthCheck'
|
||||
import { Button, Card, List, Popconfirm, Space, Tooltip, Typography } from 'antd'
|
||||
import { Card, List, Popconfirm, Space, Tooltip, Typography } from 'antd'
|
||||
import { Plus } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
@@ -141,13 +142,14 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
onConfirm={removeInvalidKeys}
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ danger: true }}>
|
||||
okButtonProps={{ color: 'danger' }}>
|
||||
<Tooltip title={t('settings.provider.remove_invalid_keys')} placement="top" mouseLeaveDelay={0}>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
disabled={isChecking || !!pendingNewKey}
|
||||
danger
|
||||
variant="light"
|
||||
startContent={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
isDisabled={isChecking || !!pendingNewKey}
|
||||
color="danger"
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
@@ -155,10 +157,11 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
{/* 批量检查 */}
|
||||
<Tooltip title={t('settings.provider.check_all_keys')} placement="top" mouseLeaveDelay={0}>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<StreamlineGoodHealthAndWellBeing size={'1.2em'} />}
|
||||
onClick={checkAllKeysConnectivity}
|
||||
disabled={isChecking || !!pendingNewKey}
|
||||
variant="light"
|
||||
startContent={<StreamlineGoodHealthAndWellBeing size={'1.2em'} />}
|
||||
onPress={checkAllKeysConnectivity}
|
||||
isDisabled={isChecking || !!pendingNewKey}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
@@ -167,11 +170,11 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
{/* 添加新 key */}
|
||||
<Button
|
||||
key="add"
|
||||
type="primary"
|
||||
onClick={handleAddNew}
|
||||
icon={<Plus size={16} />}
|
||||
color="primary"
|
||||
onPress={handleAddNew}
|
||||
startContent={<Plus size={16} />}
|
||||
autoFocus={shouldAutoFocus()}
|
||||
disabled={isChecking || !!pendingNewKey}>
|
||||
isDisabled={isChecking || !!pendingNewKey}>
|
||||
{t('common.add')}
|
||||
</Button>
|
||||
</Space>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { CopyIcon, DeleteIcon } from '@renderer/components/Icons'
|
||||
import { useChatContext } from '@renderer/hooks/useChatContext'
|
||||
import type { Topic } from '@renderer/types'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Save, X } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -37,37 +38,37 @@ const MultiSelectActionPopup: FC<Props> = ({ topic }) => {
|
||||
<ActionButtons>
|
||||
<Tooltip title={t('common.save')}>
|
||||
<Button
|
||||
shape="circle"
|
||||
color="default"
|
||||
variant="text"
|
||||
icon={<Save size={16} />}
|
||||
disabled={isActionDisabled}
|
||||
onClick={() => handleAction('save')}
|
||||
radius="full"
|
||||
variant="light"
|
||||
startContent={<Save size={16} />}
|
||||
isDisabled={isActionDisabled}
|
||||
onPress={() => handleAction('save')}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.copy')}>
|
||||
<Button
|
||||
shape="circle"
|
||||
color="default"
|
||||
variant="text"
|
||||
icon={<CopyIcon size={16} />}
|
||||
disabled={isActionDisabled}
|
||||
onClick={() => handleAction('copy')}
|
||||
radius="full"
|
||||
variant="light"
|
||||
startContent={<CopyIcon size={16} />}
|
||||
isDisabled={isActionDisabled}
|
||||
onPress={() => handleAction('copy')}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.delete')}>
|
||||
<Button
|
||||
shape="circle"
|
||||
radius="full"
|
||||
color="danger"
|
||||
variant="text"
|
||||
danger
|
||||
icon={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
onClick={() => handleAction('delete')}
|
||||
variant="light"
|
||||
startContent={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
onPress={() => handleAction('delete')}
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
</ActionButtons>
|
||||
<Tooltip title={t('chat.navigation.close')}>
|
||||
<Button shape="circle" color="default" variant="text" icon={<X size={16} />} onClick={handleClose} />
|
||||
<Button radius="full" variant="light" startContent={<X size={16} />} onPress={handleClose} isIconOnly />
|
||||
</Tooltip>
|
||||
</ActionBar>
|
||||
</Container>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { runAsyncFunction } from '@renderer/utils'
|
||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Button, Modal } from 'antd'
|
||||
import { Modal } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@@ -92,11 +93,11 @@ const PopupContainer: React.FC<Props> = ({ title, showDeclineButton = true, reso
|
||||
width={900}
|
||||
footer={[
|
||||
showDeclineButton && (
|
||||
<Button key="decline" onClick={handleDecline}>
|
||||
<Button key="decline" onPress={handleDecline}>
|
||||
{i18n.language.startsWith('zh') ? '拒绝' : 'Decline'}
|
||||
</Button>
|
||||
),
|
||||
<Button key="accept" type="primary" onClick={handleAccept}>
|
||||
<Button key="accept" variant="solid" color="primary" onPress={handleAccept}>
|
||||
{i18n.language.startsWith('zh') ? '同意并继续' : 'Accept and Continue'}
|
||||
</Button>
|
||||
].filter(Boolean)}>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Tooltip } from 'antd'
|
||||
import { memo } from 'react'
|
||||
|
||||
interface ImageToolButtonProps {
|
||||
tooltip: string
|
||||
icon: React.ReactNode
|
||||
onClick: () => void
|
||||
onPress: () => void
|
||||
}
|
||||
|
||||
const ImageToolButton = ({ tooltip, icon, onClick }: ImageToolButtonProps) => {
|
||||
const ImageToolButton = ({ tooltip, icon, onPress }: ImageToolButtonProps) => {
|
||||
return (
|
||||
<Tooltip title={tooltip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Button shape="circle" icon={icon} onClick={onClick} role="button" aria-label={tooltip} />
|
||||
<Button radius="full" startContent={icon} onPress={onPress} isIconOnly aria-label={tooltip} />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ const ImageToolbar = ({ pan, zoom, dialog, className }: ImageToolbarProps) => {
|
||||
<ImageToolButton
|
||||
tooltip={t('preview.pan_up')}
|
||||
icon={<ChevronUp size={'1rem'} />}
|
||||
onClick={() => pan(0, -panDistance)}
|
||||
onPress={() => pan(0, -panDistance)}
|
||||
/>
|
||||
<ImageToolButton tooltip={t('preview.dialog')} icon={<Scan size={'1rem'} />} onClick={dialog} />
|
||||
<ImageToolButton tooltip={t('preview.dialog')} icon={<Scan size={'1rem'} />} onPress={dialog} />
|
||||
</ActionButtonRow>
|
||||
|
||||
{/* Left, Reset, Right */}
|
||||
@@ -46,13 +46,13 @@ const ImageToolbar = ({ pan, zoom, dialog, className }: ImageToolbarProps) => {
|
||||
<ImageToolButton
|
||||
tooltip={t('preview.pan_left')}
|
||||
icon={<ChevronLeft size={'1rem'} />}
|
||||
onClick={() => pan(-panDistance, 0)}
|
||||
onPress={() => pan(-panDistance, 0)}
|
||||
/>
|
||||
<ImageToolButton tooltip={t('preview.reset')} icon={<ResetIcon size={'1rem'} />} onClick={handleReset} />
|
||||
<ImageToolButton tooltip={t('preview.reset')} icon={<ResetIcon size={'1rem'} />} onPress={handleReset} />
|
||||
<ImageToolButton
|
||||
tooltip={t('preview.pan_right')}
|
||||
icon={<ChevronRight size={'1rem'} />}
|
||||
onClick={() => pan(panDistance, 0)}
|
||||
onPress={() => pan(panDistance, 0)}
|
||||
/>
|
||||
</ActionButtonRow>
|
||||
|
||||
@@ -61,17 +61,17 @@ const ImageToolbar = ({ pan, zoom, dialog, className }: ImageToolbarProps) => {
|
||||
<ImageToolButton
|
||||
tooltip={t('preview.zoom_out')}
|
||||
icon={<ZoomOut size={'1rem'} />}
|
||||
onClick={() => zoom(-zoomDelta)}
|
||||
onPress={() => zoom(-zoomDelta)}
|
||||
/>
|
||||
<ImageToolButton
|
||||
tooltip={t('preview.pan_down')}
|
||||
icon={<ChevronDown size={'1rem'} />}
|
||||
onClick={() => pan(0, panDistance)}
|
||||
onPress={() => pan(0, panDistance)}
|
||||
/>
|
||||
<ImageToolButton
|
||||
tooltip={t('preview.zoom_in')}
|
||||
icon={<ZoomIn size={'1rem'} />}
|
||||
onClick={() => zoom(zoomDelta)}
|
||||
onPress={() => zoom(zoomDelta)}
|
||||
/>
|
||||
</ActionButtonRow>
|
||||
</ToolbarWrapper>
|
||||
|
||||
@@ -21,7 +21,7 @@ describe('ImageToolButton', () => {
|
||||
const defaultProps = {
|
||||
tooltip: 'Test tooltip',
|
||||
icon: <span data-testid="test-icon">Icon</span>,
|
||||
onClick: vi.fn()
|
||||
onPress: vi.fn()
|
||||
}
|
||||
|
||||
it('should match snapshot', () => {
|
||||
|
||||
@@ -12,8 +12,8 @@ vi.mock('react-i18next', () => ({
|
||||
|
||||
// Mock ImageToolButton
|
||||
vi.mock('../ImageToolButton', () => ({
|
||||
default: vi.fn(({ tooltip, onClick, icon }) => (
|
||||
<button type="button" onClick={onClick} role="button" aria-label={tooltip}>
|
||||
default: vi.fn(({ tooltip, onPress, icon }) => (
|
||||
<button type="button" onClick={onPress} role="button" aria-label={tooltip}>
|
||||
{icon}
|
||||
</button>
|
||||
))
|
||||
|
||||
+12
-5
@@ -7,12 +7,19 @@ exports[`ImageToolButton > should match snapshot 1`] = `
|
||||
>
|
||||
<button
|
||||
aria-label="Test tooltip"
|
||||
data-testid="custom-button"
|
||||
icon="[object Object]"
|
||||
role="button"
|
||||
shape="circle"
|
||||
class="z-0 group relative inline-flex items-center justify-center box-border appearance-none select-none whitespace-nowrap font-normal subpixel-antialiased overflow-hidden tap-highlight-transparent transform-gpu data-[pressed=true]:scale-[0.97] cursor-pointer outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-small gap-2 rounded-full px-0 !gap-0 transition-transform-colors-opacity motion-reduce:transition-none bg-default text-default-foreground min-w-10 w-10 h-10 data-[hover=true]:opacity-hover"
|
||||
data-react-aria-pressable="true"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
/>
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
data-testid="test-icon"
|
||||
focusable="false"
|
||||
>
|
||||
Icon
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { InboxOutlined, LinkOutlined, LoadingOutlined, UploadOutlined } from '@ant-design/icons'
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button, Input, Modal, Spin, Tabs, Upload } from 'antd'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Input, Modal, Spin, Tabs, Upload } from 'antd'
|
||||
|
||||
const { Dragger } = Upload
|
||||
import type { RcFile } from 'antd/es/upload'
|
||||
@@ -174,17 +175,10 @@ export const ImageUploader: React.FC<ImageUploaderProps> = ({ onImageSelect, vis
|
||||
prefix={<LinkOutlined style={{ color: '#999' }} />}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<Button
|
||||
onClick={() => setUrlInput('')}
|
||||
style={{
|
||||
border: '1px solid #dadce0',
|
||||
borderRadius: '4px',
|
||||
color: '#3c4043',
|
||||
background: '#ffffff'
|
||||
}}>
|
||||
<Button onPress={() => setUrlInput('')} className="border border-gray-300 bg-white text-gray-700">
|
||||
{t('common.clear')}
|
||||
</Button>
|
||||
<Button type="primary" onClick={handleUrlSubmit} disabled={!urlInput.trim()}>
|
||||
<Button color="primary" onPress={handleUrlSubmit} isDisabled={!urlInput.trim()}>
|
||||
{t('richEditor.imageUploader.embedImage')}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { Button, Input } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -146,16 +147,16 @@ const LinkEditor: React.FC<LinkEditorProps> = ({
|
||||
<Flex className="items-center justify-between">
|
||||
<div>
|
||||
{showRemove && (
|
||||
<Button size="small" danger type="text" onClick={onRemove} style={{ padding: '0 8px' }}>
|
||||
<Button size="sm" color="danger" variant="light" onPress={onRemove} className="px-2">
|
||||
{t('richEditor.link.remove')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<Flex className="gap-1.5">
|
||||
<Button size="small" onClick={onCancel}>
|
||||
<Button size="sm" onPress={onCancel}>
|
||||
{t('common.cancel')}
|
||||
</Button>
|
||||
<Button type="primary" size="small" onClick={handleSave} disabled={!href.trim() || !text.trim()}>
|
||||
<Button color="primary" size="sm" onPress={handleSave} isDisabled={!href.trim() || !text.trim()}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { Button, Input } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -148,10 +149,10 @@ const MathInputDialog: React.FC<MathInputDialogProps> = ({
|
||||
style={{ marginBottom: 12, fontFamily: 'monospace' }}
|
||||
/>
|
||||
<Flex className="justify-end gap-2">
|
||||
<Button size="small" onClick={onCancel}>
|
||||
<Button size="sm" onPress={onCancel}>
|
||||
{t('common.cancel')}
|
||||
</Button>
|
||||
<Button type="primary" size="small" onClick={handleSubmit}>
|
||||
<Button color="primary" size="sm" onPress={handleSubmit}>
|
||||
{t('common.confirm')}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
+7
-5
@@ -1,7 +1,8 @@
|
||||
import { CopyOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { DEFAULT_LANGUAGES, getHighlighter, getShiki } from '@renderer/utils/shiki'
|
||||
import { NodeViewContent, NodeViewWrapper, type ReactNodeViewProps, ReactNodeViewRenderer } from '@tiptap/react'
|
||||
import { Button, Select, Tooltip } from 'antd'
|
||||
import { Select, Tooltip } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
@@ -67,11 +68,12 @@ const CodeBlockNodeView: FC<ReactNodeViewProps> = (props) => {
|
||||
/>
|
||||
<Tooltip title="Copy">
|
||||
<Button
|
||||
size="small"
|
||||
type="text"
|
||||
icon={<CopyOutlined />}
|
||||
size="sm"
|
||||
variant="light"
|
||||
startContent={<CopyOutlined />}
|
||||
isIconOnly
|
||||
className="code-block-copy-btn"
|
||||
onClick={handleCopy}
|
||||
onPress={handleCopy}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { DeleteOutlined, ExclamationCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { restoreFromS3 } from '@renderer/services/BackupService'
|
||||
import type { S3Config } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Button, Modal, Table, Tooltip } from 'antd'
|
||||
import { Modal, Table, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -231,14 +232,14 @@ export function S3BackupManager({ visible, onClose, s3Config, restoreMethod }: S
|
||||
width: 160,
|
||||
render: (_: any, record: BackupFile) => (
|
||||
<>
|
||||
<Button type="link" onClick={() => handleRestore(record.fileName)} disabled={restoring || deleting}>
|
||||
<Button variant="light" onPress={() => handleRestore(record.fileName)} isDisabled={restoring || deleting}>
|
||||
{t('settings.data.s3.manager.restore')}
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => handleDeleteSingle(record.fileName)}
|
||||
disabled={deleting || restoring}>
|
||||
variant="light"
|
||||
color="danger"
|
||||
onPress={() => handleDeleteSingle(record.fileName)}
|
||||
isDisabled={deleting || restoring}>
|
||||
{t('settings.data.s3.manager.delete.label')}
|
||||
</Button>
|
||||
</>
|
||||
@@ -262,19 +263,19 @@ export function S3BackupManager({ visible, onClose, s3Config, restoreMethod }: S
|
||||
centered
|
||||
transitionName="animation-move-down"
|
||||
footer={[
|
||||
<Button key="refresh" icon={<ReloadOutlined />} onClick={fetchBackupFiles} disabled={loading}>
|
||||
<Button key="refresh" startContent={<ReloadOutlined />} onPress={fetchBackupFiles} isDisabled={loading}>
|
||||
{t('settings.data.s3.manager.refresh')}
|
||||
</Button>,
|
||||
<Button
|
||||
key="delete"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={handleDeleteSelected}
|
||||
disabled={selectedRowKeys.length === 0 || deleting}
|
||||
loading={deleting}>
|
||||
color="danger"
|
||||
startContent={<DeleteOutlined />}
|
||||
onPress={handleDeleteSelected}
|
||||
isDisabled={selectedRowKeys.length === 0 || deleting}
|
||||
isLoading={deleting}>
|
||||
{t('settings.data.s3.manager.delete.selected', { count: selectedRowKeys.length })}
|
||||
</Button>,
|
||||
<Button key="close" onClick={onClose}>
|
||||
<Button key="close" onPress={onClose}>
|
||||
{t('settings.data.s3.manager.close')}
|
||||
</Button>
|
||||
]}>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import useTranslate from '@renderer/hooks/useTranslate'
|
||||
import { translateText } from '@renderer/services/TranslateService'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Languages } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
interface Props {
|
||||
text?: string
|
||||
@@ -70,47 +70,18 @@ const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoa
|
||||
title={t('chat.input.translate', { target_language: getLanguageByLangcode(targetLanguage).label() })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton onClick={handleTranslate} disabled={disabled || isTranslating} style={style} type="text">
|
||||
<Button
|
||||
onPress={handleTranslate}
|
||||
isDisabled={disabled || isTranslating}
|
||||
style={style}
|
||||
variant="light"
|
||||
isIconOnly
|
||||
size="sm"
|
||||
radius="full">
|
||||
{isTranslating ? <LoadingOutlined spin /> : <Languages size={18} />}
|
||||
</ToolbarButton>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
const ToolbarButton = styled(Button)`
|
||||
min-width: 30px;
|
||||
height: 30px;
|
||||
font-size: 16px;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
color: var(--color-icon);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
&.anticon,
|
||||
&.iconfont {
|
||||
transition: all 0.3s ease;
|
||||
color: var(--color-icon);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-background-soft);
|
||||
.anticon,
|
||||
.iconfont {
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
background-color: var(--color-primary) !important;
|
||||
.anticon,
|
||||
.iconfont {
|
||||
color: var(--color-white-soft);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default TranslateButton
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { DeleteOutlined, ExclamationCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { restoreFromWebdav } from '@renderer/services/BackupService'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Button, Modal, Table, Tooltip } from 'antd'
|
||||
import { Modal, Table, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -238,14 +239,14 @@ export function WebdavBackupManager({
|
||||
width: 160,
|
||||
render: (_: any, record: BackupFile) => (
|
||||
<>
|
||||
<Button type="link" onClick={() => handleRestore(record.fileName)} disabled={restoring || deleting}>
|
||||
<Button variant="light" onPress={() => handleRestore(record.fileName)} isDisabled={restoring || deleting}>
|
||||
{t('settings.data.webdav.backup.manager.restore.text')}
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => handleDeleteSingle(record.fileName)}
|
||||
disabled={deleting || restoring}>
|
||||
variant="light"
|
||||
color="danger"
|
||||
onPress={() => handleDeleteSingle(record.fileName)}
|
||||
isDisabled={deleting || restoring}>
|
||||
{t('settings.data.webdav.backup.manager.delete.text')}
|
||||
</Button>
|
||||
</>
|
||||
@@ -269,19 +270,19 @@ export function WebdavBackupManager({
|
||||
centered
|
||||
transitionName="animation-move-down"
|
||||
footer={[
|
||||
<Button key="refresh" icon={<ReloadOutlined />} onClick={fetchBackupFiles} disabled={loading}>
|
||||
<Button key="refresh" startContent={<ReloadOutlined />} onPress={fetchBackupFiles} isDisabled={loading}>
|
||||
{t('settings.data.webdav.backup.manager.refresh')}
|
||||
</Button>,
|
||||
<Button
|
||||
key="delete"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={handleDeleteSelected}
|
||||
disabled={selectedRowKeys.length === 0 || deleting}
|
||||
loading={deleting}>
|
||||
color="danger"
|
||||
startContent={<DeleteOutlined />}
|
||||
onPress={handleDeleteSelected}
|
||||
isDisabled={selectedRowKeys.length === 0 || deleting}
|
||||
isLoading={deleting}>
|
||||
{t('settings.data.webdav.backup.manager.delete.selected')} ({selectedRowKeys.length})
|
||||
</Button>,
|
||||
<Button key="close" onClick={onClose}>
|
||||
<Button key="close" onPress={onClose}>
|
||||
{t('common.close')}
|
||||
</Button>
|
||||
]}>
|
||||
|
||||
+14
@@ -18,13 +18,18 @@ exports[`InputEmbeddingDimension > basic rendering > should match snapshot with
|
||||
>
|
||||
<button
|
||||
aria-label="Get embedding dimension"
|
||||
class="z-0 group relative inline-flex items-center justify-center box-border appearance-none select-none whitespace-nowrap font-normal subpixel-antialiased overflow-hidden tap-highlight-transparent transform-gpu data-[pressed=true]:scale-[0.97] cursor-pointer outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-tiny gap-2 rounded-small px-0 !gap-0 transition-transform-colors-opacity motion-reduce:transition-none bg-default text-default-foreground min-w-8 w-8 h-8 data-[hover=true]:opacity-hover"
|
||||
data-react-aria-pressable="true"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-label="refresh"
|
||||
class=""
|
||||
data-testid="refresh-icon"
|
||||
focusable="false"
|
||||
role="img"
|
||||
size="16"
|
||||
>
|
||||
@@ -53,19 +58,28 @@ exports[`InputEmbeddingDimension > basic rendering > should match snapshot with
|
||||
>
|
||||
<button
|
||||
aria-label="Get embedding dimension"
|
||||
class="z-0 group relative inline-flex items-center justify-center box-border appearance-none select-none whitespace-nowrap font-normal subpixel-antialiased overflow-hidden tap-highlight-transparent transform-gpu data-[pressed=true]:scale-[0.97] cursor-pointer outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-tiny gap-2 rounded-small opacity-disabled pointer-events-none px-0 !gap-0 transition-transform-colors-opacity motion-reduce:transition-none bg-default text-default-foreground min-w-8 w-8 h-8 data-[hover=true]:opacity-hover"
|
||||
data-disabled="true"
|
||||
data-react-aria-pressable="true"
|
||||
disabled=""
|
||||
role="button"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-label="refresh"
|
||||
class="animation-rotate"
|
||||
data-testid="refresh-icon"
|
||||
focusable="false"
|
||||
role="img"
|
||||
size="16"
|
||||
>
|
||||
RefreshIcon
|
||||
</svg>
|
||||
<span
|
||||
class="heroui-ripple"
|
||||
style="position: absolute; background-color: currentColor; border-radius: 100%; transform-origin: center; pointer-events: none; overflow: hidden; inset: 0; z-index: 0; top: 0px; left: 0px; width: 0px; height: 0px; transform: scale(0); opacity: 0.35;"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// import { setUserTheme, UserTheme } from '@renderer/store/settings'
|
||||
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { getForegroundColor } from '@renderer/utils'
|
||||
import Color from 'color'
|
||||
|
||||
export default function useUserTheme() {
|
||||
@@ -15,6 +16,7 @@ export default function useUserTheme() {
|
||||
document.body.style.setProperty('--color-primary', colorPrimary.toString())
|
||||
// overwrite hero UI primary color.
|
||||
document.body.style.setProperty('--primary', colorPrimary.toString())
|
||||
document.body.style.setProperty('--primary-foreground', getForegroundColor(colorPrimary.hex()))
|
||||
document.body.style.setProperty('--color-primary-soft', colorPrimary.alpha(0.6).toString())
|
||||
document.body.style.setProperty('--color-primary-mute', colorPrimary.alpha(0.3).toString())
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ImportOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import { ColFlex, Flex, RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import ListItem from '@renderer/components/ListItem'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
@@ -9,7 +10,7 @@ import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
|
||||
import type { Agent } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { Button, Empty, Input } from 'antd'
|
||||
import { Empty, Input } from 'antd'
|
||||
import { omit } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -267,17 +268,17 @@ const AgentsPage: FC = () => {
|
||||
) : (
|
||||
isTopNavbar && (
|
||||
<Button
|
||||
type="text"
|
||||
onClick={handleSearchIconClick}
|
||||
icon={<Search size={18} color="var(--color-icon)" />}>
|
||||
variant="light"
|
||||
onPress={handleSearchIconClick}
|
||||
startContent={<Search size={18} color="var(--color-icon)" />}>
|
||||
{t('common.search')}
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
<Button type="text" onClick={handleImportAgent} icon={<ImportOutlined />}>
|
||||
<Button variant="light" onPress={handleImportAgent} startContent={<ImportOutlined />}>
|
||||
{t('agents.import.title')}
|
||||
</Button>
|
||||
<Button type="text" onClick={handleAddAgent} icon={<PlusOutlined />}>
|
||||
<Button variant="light" onPress={handleAddAgent} startContent={<PlusOutlined />}>
|
||||
{t('agents.add.title')}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'emoji-picker-element'
|
||||
|
||||
import { CheckOutlined, LoadingOutlined, RollbackOutlined, ThunderboltOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import EmojiPicker from '@renderer/components/EmojiPicker'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
@@ -14,7 +15,7 @@ import type { Agent, KnowledgeBase } from '@renderer/types'
|
||||
import { getLeadingEmoji, uuid } from '@renderer/utils'
|
||||
import { AGENT_PROMPT } from '@shared/config/prompts'
|
||||
import type { FormInstance, SelectProps } from 'antd'
|
||||
import { Button, Form, Input, Modal, Popover, Select } from 'antd'
|
||||
import { Form, Input, Modal, Popover, Select } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -202,7 +203,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
}
|
||||
arrow
|
||||
trigger="click">
|
||||
<Button icon={emoji && <span style={{ fontSize: 20 }}>{emoji}</span>}>{t('common.select')}</Button>
|
||||
<Button startContent={emoji && <span style={{ fontSize: 20 }}>{emoji}</span>}>{t('common.select')}</Button>
|
||||
</Popover>
|
||||
</Form.Item>
|
||||
<Form.Item name="name" label={t('agents.add.name.label')} rules={[{ required: true }]}>
|
||||
@@ -218,15 +219,19 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
</Form.Item>
|
||||
<TokenCount>Tokens: {tokenCount}</TokenCount>
|
||||
<Button
|
||||
icon={loading ? <LoadingOutlined /> : <ThunderboltOutlined />}
|
||||
onClick={handleGenerateButtonClick}
|
||||
startContent={loading ? <LoadingOutlined /> : <ThunderboltOutlined />}
|
||||
isIconOnly
|
||||
size="sm"
|
||||
onPress={handleGenerateButtonClick}
|
||||
style={{ position: 'absolute', top: 8, right: 8 }}
|
||||
disabled={loading}
|
||||
isDisabled={loading}
|
||||
/>
|
||||
{showUndoButton && (
|
||||
<Button
|
||||
icon={<RollbackOutlined />}
|
||||
onClick={handleUndoButtonClick}
|
||||
startContent={<RollbackOutlined />}
|
||||
isIconOnly
|
||||
size="sm"
|
||||
onPress={handleUndoButtonClick}
|
||||
style={{ position: 'absolute', top: 8, right: 48 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
@@ -5,7 +6,7 @@ import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
|
||||
import type { Agent } from '@renderer/types'
|
||||
import { getLeadingEmoji } from '@renderer/utils'
|
||||
import { Button, Dropdown } from 'antd'
|
||||
import { Dropdown } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { ArrowDownAZ, Ellipsis, PlusIcon, SquareArrowOutUpRight } from 'lucide-react'
|
||||
import { type FC, memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
@@ -159,16 +160,9 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
}}
|
||||
trigger={['click']}
|
||||
placement="bottomRight">
|
||||
<MenuButton
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}}
|
||||
color="default"
|
||||
variant="filled"
|
||||
shape="circle"
|
||||
icon={<Ellipsis size={14} color="var(--color-text-3)" />}
|
||||
/>
|
||||
<MenuButton color="default" variant="light" radius="full" isIconOnly={true}>
|
||||
<Ellipsis size={14} color="var(--color-text-3)" />
|
||||
</MenuButton>
|
||||
</Dropdown>
|
||||
</AgentCardHeaderInfoAction>
|
||||
) : (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
@@ -6,7 +7,7 @@ import { getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import type { Agent } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { Button, Form, Input, Modal, Radio } from 'antd'
|
||||
import { Form, Input, Modal, Radio } from 'antd'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -100,8 +101,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
maskClosable={false}
|
||||
footer={
|
||||
<Flex className="justify-end gap-2">
|
||||
<Button onClick={onCancel}>{t('common.cancel')}</Button>
|
||||
<Button type="primary" onClick={() => form.submit()} loading={loading}>
|
||||
<Button onPress={onCancel}>{t('common.cancel')}</Button>
|
||||
<Button color="primary" onPress={() => form.submit()} isLoading={loading}>
|
||||
{t('agents.import.button')}
|
||||
</Button>
|
||||
</Flex>
|
||||
@@ -124,7 +125,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
|
||||
{importType === 'file' && (
|
||||
<Form.Item>
|
||||
<Button onClick={() => form.submit()}>{t('agents.import.select_file')}</Button>
|
||||
<Button onPress={() => form.submit()}>{t('agents.import.select_file')}</Button>
|
||||
</Form.Item>
|
||||
)}
|
||||
</Form>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import AiProvider from '@renderer/aiCore'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import ModelSelector from '@renderer/components/ModelSelector'
|
||||
@@ -16,7 +17,7 @@ import { setIsBunInstalled } from '@renderer/store/mcp'
|
||||
import type { EndpointType, Model } from '@renderer/types'
|
||||
import type { TerminalConfig } from '@shared/config/constant'
|
||||
import { codeTools, terminalApps } from '@shared/config/constant'
|
||||
import { Alert, Avatar, Button, Checkbox, Input, Popover, Select, Space, Tooltip } from 'antd'
|
||||
import { Alert, Avatar, Checkbox, Input, Popover, Select, Space, Tooltip } from 'antd'
|
||||
import { ArrowUpRight, Download, FolderOpen, HelpCircle, Terminal, X } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
@@ -321,12 +322,12 @@ const CodeToolsPage: FC = () => {
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<span>{t('code.bun_required_message')}</span>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
icon={<Download size={14} />}
|
||||
onClick={handleInstallBun}
|
||||
loading={isInstallingBun}
|
||||
disabled={isInstallingBun}>
|
||||
color="primary"
|
||||
size="sm"
|
||||
startContent={<Download size={14} />}
|
||||
onPress={handleInstallBun}
|
||||
isLoading={isInstallingBun}
|
||||
isDisabled={isInstallingBun}>
|
||||
{isInstallingBun ? t('code.installing_bun') : t('code.install_bun')}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -457,7 +458,11 @@ const CodeToolsPage: FC = () => {
|
||||
selectedTerminal !== terminalApps.powershell &&
|
||||
selectedTerminal !== terminalApps.windowsTerminal && (
|
||||
<Tooltip title={terminalCustomPaths[selectedTerminal] || t('code.set_custom_path')}>
|
||||
<Button icon={<FolderOpen size={16} />} onClick={() => handleSetCustomPath(selectedTerminal)} />
|
||||
<Button
|
||||
startContent={<FolderOpen size={16} />}
|
||||
isIconOnly
|
||||
onPress={() => handleSetCustomPath(selectedTerminal)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space.Compact>
|
||||
@@ -484,13 +489,13 @@ const CodeToolsPage: FC = () => {
|
||||
</SettingsPanel>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<Terminal size={16} />}
|
||||
size="large"
|
||||
onClick={handleLaunch}
|
||||
loading={isLaunching}
|
||||
disabled={!canLaunch || !isBunInstalled}
|
||||
block>
|
||||
color="primary"
|
||||
startContent={<Terminal size={16} />}
|
||||
size="lg"
|
||||
onPress={handleLaunch}
|
||||
isLoading={isLaunching}
|
||||
isDisabled={!canLaunch || !isBunInstalled}
|
||||
fullWidth={true}>
|
||||
{isLaunching ? t('code.launching') : t('code.launch.label')}
|
||||
</Button>
|
||||
</MainContent>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
@@ -12,7 +13,7 @@ import store from '@renderer/store'
|
||||
import type { FileMetadata } from '@renderer/types'
|
||||
import { FileTypes } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Button, Checkbox, Dropdown, Empty, Popconfirm } from 'antd'
|
||||
import { Checkbox, Dropdown, Empty, Popconfirm } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useLiveQuery } from 'dexie-react-hooks'
|
||||
import {
|
||||
@@ -114,7 +115,7 @@ const FilesPage: FC = () => {
|
||||
created_at_unix: dayjs(file.created_at).unix(),
|
||||
actions: (
|
||||
<Flex className="items-center gap-0 opacity-70">
|
||||
<Button type="text" icon={<EditIcon size={14} />} onClick={() => handleRename(file.id)} />
|
||||
<Button variant="light" startContent={<EditIcon size={14} />} onPress={() => handleRename(file.id)} />
|
||||
<Popconfirm
|
||||
title={t('files.delete.title')}
|
||||
description={t('files.delete.content')}
|
||||
@@ -123,7 +124,7 @@ const FilesPage: FC = () => {
|
||||
onConfirm={() => handleDelete(file.id, t)}
|
||||
placement="left"
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}>
|
||||
<Button type="text" danger icon={<DeleteIcon size={14} className="lucide-custom" />} />
|
||||
<Button variant="light" color="danger" startContent={<DeleteIcon size={14} className="lucide-custom" />} />
|
||||
</Popconfirm>
|
||||
{fileType !== 'image' && (
|
||||
<Checkbox
|
||||
@@ -168,7 +169,7 @@ const FilesPage: FC = () => {
|
||||
<SortButton
|
||||
key={field}
|
||||
active={sortField === field}
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
if (sortField === field) {
|
||||
setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc')
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { MessageEditingProvider } from '@renderer/context/MessageEditingContext'
|
||||
import { getTopicById } from '@renderer/hooks/useTopic'
|
||||
import { default as MessageItem } from '@renderer/pages/home/Messages/Message'
|
||||
@@ -7,7 +8,6 @@ import NavigationService from '@renderer/services/NavigationService'
|
||||
import type { Topic } from '@renderer/types'
|
||||
import type { Message } from '@renderer/types/newMessage'
|
||||
import { runAsyncFunction } from '@renderer/utils'
|
||||
import { Button } from 'antd'
|
||||
import { Forward } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -46,14 +46,14 @@ const SearchMessage: FC<Props> = ({ message, ...props }) => {
|
||||
<ContainerWrapper>
|
||||
<MessageItem message={message} topic={topic} hideMenuBar={true} />
|
||||
<Button
|
||||
type="text"
|
||||
size="middle"
|
||||
style={{ color: 'var(--color-text-3)', position: 'absolute', right: 16, top: 16 }}
|
||||
onClick={() => locateToMessage(navigate, message)}
|
||||
icon={<Forward size={16} />}
|
||||
variant="light"
|
||||
size="md"
|
||||
className="absolute top-4 right-4 text-[var(--color-text-3)]"
|
||||
onPress={() => locateToMessage(navigate, message)}
|
||||
startContent={<Forward size={16} />}
|
||||
/>
|
||||
<RowFlex className="mt-[10px] justify-center">
|
||||
<Button onClick={() => locateToMessage(navigate, message)} icon={<Forward size={16} />}>
|
||||
<Button onPress={() => locateToMessage(navigate, message)} startContent={<Forward size={16} />}>
|
||||
{t('history.locate.message')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MessageOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import SearchPopup from '@renderer/components/Popups/SearchPopup'
|
||||
import { MessageEditingProvider } from '@renderer/context/MessageEditingContext'
|
||||
@@ -13,7 +14,7 @@ import { locateToMessage } from '@renderer/services/MessagesService'
|
||||
import NavigationService from '@renderer/services/NavigationService'
|
||||
import type { Topic } from '@renderer/types'
|
||||
import { classNames, runAsyncFunction } from '@renderer/utils'
|
||||
import { Button, Divider, Empty } from 'antd'
|
||||
import { Divider, Empty } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { Forward } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -64,11 +65,11 @@ const TopicMessages: FC<Props> = ({ topic: _topic, ...props }) => {
|
||||
<MessageWrapper key={message.id} className={classNames([messageStyle, message.role])}>
|
||||
<MessageItem message={message} topic={topic} hideMenuBar={true} />
|
||||
<Button
|
||||
type="text"
|
||||
size="middle"
|
||||
style={{ color: 'var(--color-text-3)', position: 'absolute', right: 0, top: 5 }}
|
||||
onClick={() => locateToMessage(navigate, message)}
|
||||
icon={<Forward size={16} />}
|
||||
variant="light"
|
||||
size="md"
|
||||
className="absolute top-[5px] right-0 text-[var(--color-text-3)]"
|
||||
onPress={() => locateToMessage(navigate, message)}
|
||||
startContent={<Forward size={16} />}
|
||||
/>
|
||||
<Divider style={{ margin: '8px auto 15px' }} variant="dashed" />
|
||||
</MessageWrapper>
|
||||
@@ -76,7 +77,7 @@ const TopicMessages: FC<Props> = ({ topic: _topic, ...props }) => {
|
||||
{isEmpty && <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
|
||||
{!isEmpty && (
|
||||
<RowFlex className="justify-center">
|
||||
<Button onClick={() => onContinueChat(topic)} icon={<MessageOutlined />}>
|
||||
<Button onPress={() => onContinueChat(topic)} startContent={<MessageOutlined />}>
|
||||
{t('history.continue_chat')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { SearchOutlined } from '@ant-design/icons'
|
||||
import { ColFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import useScrollPosition from '@renderer/hooks/useScrollPosition'
|
||||
import { selectAllTopics } from '@renderer/store/assistants'
|
||||
import type { Topic } from '@renderer/types'
|
||||
import { Button, Divider, Empty, Segmented } from 'antd'
|
||||
import { Divider, Empty, Segmented } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { groupBy, isEmpty, orderBy } from 'lodash'
|
||||
import { useState } from 'react'
|
||||
@@ -40,7 +41,7 @@ const TopicsHistory: React.FC<Props> = ({ keywords, onClick, onSearch, ...props
|
||||
<ListContainer {...props}>
|
||||
<ColFlex className="items-center">
|
||||
<Empty description={t('history.search.topics.empty')} />
|
||||
<Button style={{ width: 200, marginTop: 20 }} type="primary" onClick={onSearch} icon={<SearchOutlined />}>
|
||||
<Button className="mt-5 w-[200px]" color="primary" onPress={onSearch} startContent={<SearchOutlined />}>
|
||||
{t('history.search.messages')}
|
||||
</Button>
|
||||
</ColFlex>
|
||||
@@ -75,7 +76,7 @@ const TopicsHistory: React.FC<Props> = ({ keywords, onClick, onSearch, ...props
|
||||
))}
|
||||
{keywords && (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', width: '100%' }}>
|
||||
<Button style={{ width: 200, marginTop: 20 }} type="primary" onClick={onSearch} icon={<SearchOutlined />}>
|
||||
<Button className="mt-5 w-[200px]" color="primary" onPress={onSearch} startContent={<SearchOutlined />}>
|
||||
{t('history.search.messages')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -148,9 +148,12 @@ const AttachmentButton: FC<Props> = ({ ref, couldAddImageFile, extensions, files
|
||||
title={couldAddImageFile ? t('chat.input.upload.image_or_document') : t('chat.input.upload.document')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton onClick={openFileSelectDialog} active={files.length > 0} disabled={disabled}>
|
||||
<Paperclip size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={openFileSelectDialog}
|
||||
active={files.length > 0}
|
||||
isDisabled={disabled}
|
||||
icon={<Paperclip size={18} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ const GenerateImageButton: FC<Props> = ({ model, assistant, onEnableGenerateImag
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton
|
||||
onClick={onEnableGenerateImage}
|
||||
onPress={onEnableGenerateImage}
|
||||
active={assistant.enableGenerateImage}
|
||||
disabled={!isGenerateImageModel(model)}>
|
||||
<Image size={18} />
|
||||
</ActionIconButton>
|
||||
isDisabled={!isGenerateImageModel(model)}
|
||||
icon={<Image size={18} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -912,9 +912,11 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
<SendMessageButton sendMessage={sendMessage} disabled={inputEmpty} />
|
||||
{loading && (
|
||||
<Tooltip placement="top" title={t('chat.input.pause')} mouseLeaveDelay={0} arrow>
|
||||
<ActionIconButton onClick={onPause} style={{ marginRight: -2 }}>
|
||||
<CirclePause size={20} color="var(--color-error)" />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onClick={onPause}
|
||||
className="mr-[-2px]"
|
||||
icon={<CirclePause size={20} color="var(--color-error)" />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ToolbarMenu>
|
||||
|
||||
@@ -359,9 +359,7 @@ const InputbarTools = ({
|
||||
title={t('chat.input.new_topic', { Command: newTopicShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton onClick={addNewTopic}>
|
||||
<MessageSquareDiff size={19} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={addNewTopic} icon={<MessageSquareDiff size={19} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
@@ -466,9 +464,7 @@ const InputbarTools = ({
|
||||
title={t('chat.input.clear.label', { Command: clearTopicShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton onClick={clearTopic}>
|
||||
<PaintbrushVertical size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={clearTopic} icon={<PaintbrushVertical size={18} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
@@ -481,9 +477,10 @@ const InputbarTools = ({
|
||||
title={isExpended ? t('chat.input.collapse') : t('chat.input.expand')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton onClick={onToggleExpended}>
|
||||
{isExpended ? <Minimize size={18} /> : <Maximize size={18} />}
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={onToggleExpended}
|
||||
icon={isExpended ? <Minimize size={18} /> : <Maximize size={18} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
@@ -662,14 +659,17 @@ const InputbarTools = ({
|
||||
placement="top"
|
||||
title={isCollapse ? t('chat.input.tools.expand') : t('chat.input.tools.collapse')}
|
||||
arrow>
|
||||
<ActionIconButton onClick={() => dispatch(setIsCollapsed(!isCollapse))}>
|
||||
<CircleChevronRight
|
||||
size={18}
|
||||
style={{
|
||||
transform: isCollapse ? 'scaleX(1)' : 'scaleX(-1)'
|
||||
}}
|
||||
/>
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={() => dispatch(setIsCollapsed(!isCollapse))}
|
||||
icon={
|
||||
<CircleChevronRight
|
||||
size={18}
|
||||
style={{
|
||||
transform: isCollapse ? 'scaleX(1)' : 'scaleX(-1)'
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ToolsContainer>
|
||||
|
||||
@@ -110,11 +110,11 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.knowledge_base')} mouseLeaveDelay={0} arrow>
|
||||
<ActionIconButton
|
||||
onClick={handleOpenQuickPanel}
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={selectedBases && selectedBases.length > 0}
|
||||
disabled={disabled}>
|
||||
<FileSearch size={18} />
|
||||
</ActionIconButton>
|
||||
isDisabled={disabled}
|
||||
icon={<FileSearch size={18} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -488,9 +488,11 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, assista
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('settings.mcp.title')} mouseLeaveDelay={0} arrow>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel} active={assistant.mcpServers && assistant.mcpServers.length > 0}>
|
||||
<Hammer size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={assistant.mcpServers && assistant.mcpServers.length > 0}
|
||||
icon={<Hammer size={18} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -304,9 +304,11 @@ const MentionModelsButton: FC<Props> = ({
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('agents.edit.model.select.title')} mouseLeaveDelay={0} arrow>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel} active={mentionedModels.length > 0}>
|
||||
<AtSign size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={mentionedModels.length > 0}
|
||||
icon={<AtSign size={18} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@ const NewContextButton: FC<Props> = ({ onNewContext }) => {
|
||||
title={t('chat.input.new.context', { Command: newContextShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton onClick={onNewContext}>
|
||||
<Eraser size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={onNewContext} icon={<Eraser size={18} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -157,9 +157,7 @@ const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, assistantId }:
|
||||
return (
|
||||
<>
|
||||
<Tooltip placement="top" title={t('settings.quickPhrase.title')} mouseLeaveDelay={0} arrow>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel}>
|
||||
<Zap size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={handleOpenQuickPanel} icon={<Zap size={18} />} />
|
||||
</Tooltip>
|
||||
|
||||
<Modal
|
||||
|
||||
@@ -140,9 +140,11 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistantId }): ReactElement =>
|
||||
}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel} active={currentReasoningEffort !== 'off'}>
|
||||
{ThinkingIcon(currentReasoningEffort)}
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={currentReasoningEffort !== 'off'}
|
||||
icon={ThinkingIcon(currentReasoningEffort)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -48,9 +48,7 @@ const UrlContextButton: FC<Props> = ({ assistantId }) => {
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.url_context')} arrow>
|
||||
<ActionIconButton onClick={handleToggle} active={assistant.enableUrlContext}>
|
||||
<Link size={18} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={handleToggle} active={assistant.enableUrlContext} icon={<Link size={18} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -212,9 +212,11 @@ const WebSearchButton: FC<Props> = ({ ref, assistantId }) => {
|
||||
title={enableWebSearch ? t('common.close') : t('chat.input.web_search.label')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ActionIconButton onClick={onClick} active={!!enableWebSearch}>
|
||||
<WebSearchIcon pid={assistant.webSearchProviderId} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton
|
||||
onPress={onClick}
|
||||
active={!!enableWebSearch}
|
||||
icon={<WebSearchIcon pid={assistant.webSearchProviderId} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@ import {
|
||||
VerticalAlignBottomOutlined,
|
||||
VerticalAlignTopOutlined
|
||||
} from '@ant-design/icons'
|
||||
// import { selectCurrentTopicId } from '@renderer/store/newMessage'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import type { RootState } from '@renderer/store'
|
||||
// import { selectCurrentTopicId } from '@renderer/store/newMessage'
|
||||
import { Button, Drawer, Tooltip } from 'antd'
|
||||
import { Drawer, Tooltip } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -338,54 +339,54 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
|
||||
<ButtonGroup>
|
||||
<Tooltip title={t('chat.navigation.close')} placement="left" mouseEnterDelay={0.5}>
|
||||
<NavigationButton
|
||||
type="text"
|
||||
icon={<CloseOutlined />}
|
||||
onClick={handleCloseChatNavigation}
|
||||
variant="light"
|
||||
startContent={<CloseOutlined />}
|
||||
onPress={handleCloseChatNavigation}
|
||||
aria-label={t('chat.navigation.close')}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.top')} placement="left" mouseEnterDelay={0.5}>
|
||||
<NavigationButton
|
||||
type="text"
|
||||
icon={<VerticalAlignTopOutlined />}
|
||||
onClick={handleScrollToTop}
|
||||
variant="light"
|
||||
startContent={<VerticalAlignTopOutlined />}
|
||||
onPress={handleScrollToTop}
|
||||
aria-label={t('chat.navigation.top')}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.prev')} placement="left" mouseEnterDelay={0.5}>
|
||||
<NavigationButton
|
||||
type="text"
|
||||
icon={<ArrowUpOutlined />}
|
||||
onClick={handlePrevMessage}
|
||||
variant="light"
|
||||
startContent={<ArrowUpOutlined />}
|
||||
onPress={handlePrevMessage}
|
||||
aria-label={t('chat.navigation.prev')}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.next')} placement="left" mouseEnterDelay={0.5}>
|
||||
<NavigationButton
|
||||
type="text"
|
||||
icon={<ArrowDownOutlined />}
|
||||
onClick={handleNextMessage}
|
||||
variant="light"
|
||||
startContent={<ArrowDownOutlined />}
|
||||
onPress={handleNextMessage}
|
||||
aria-label={t('chat.navigation.next')}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.bottom')} placement="left" mouseEnterDelay={0.5}>
|
||||
<NavigationButton
|
||||
type="text"
|
||||
icon={<VerticalAlignBottomOutlined />}
|
||||
onClick={handleScrollToBottom}
|
||||
variant="light"
|
||||
startContent={<VerticalAlignBottomOutlined />}
|
||||
onPress={handleScrollToBottom}
|
||||
aria-label={t('chat.navigation.bottom')}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.history')} placement="left" mouseEnterDelay={0.5}>
|
||||
<NavigationButton
|
||||
type="text"
|
||||
icon={<HistoryOutlined />}
|
||||
onClick={handleChatHistoryClick}
|
||||
variant="light"
|
||||
startContent={<HistoryOutlined />}
|
||||
onPress={handleChatHistoryClick}
|
||||
aria-label={t('chat.navigation.history')}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import ContextMenu from '@renderer/components/ContextMenu'
|
||||
import Favicon from '@renderer/components/Icons/FallbackFavicon'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
@@ -6,7 +7,7 @@ import type { Citation } from '@renderer/types'
|
||||
import { fetchWebContent } from '@renderer/utils/fetch'
|
||||
import { cleanMarkdownContent } from '@renderer/utils/formats'
|
||||
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'
|
||||
import { Button, Popover, Skeleton } from 'antd'
|
||||
import { Popover, Skeleton } from 'antd'
|
||||
import { Check, Copy, FileSearch } from 'lucide-react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -91,7 +92,7 @@ const CitationsList: React.FC<CitationsListProps> = ({ citations }) => {
|
||||
padding: '0 0 8px 0'
|
||||
}
|
||||
}}>
|
||||
<OpenButton type="text">
|
||||
<OpenButton variant="light">
|
||||
<PreviewIcons>
|
||||
{previewItems.map((c, i) => (
|
||||
<PreviewIcon key={i} style={{ zIndex: previewItems.length - i }}>
|
||||
|
||||
@@ -360,20 +360,14 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
<ActionBarMiddle />
|
||||
<ActionBarRight>
|
||||
<Tooltip title={t('common.cancel')}>
|
||||
<ActionIconButton onClick={onCancel}>
|
||||
<X size={16} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={onCancel} icon={<X size={16} />} />
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.save')}>
|
||||
<ActionIconButton onClick={handleSave}>
|
||||
<Save size={16} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={handleSave} icon={<Save size={16} />} />
|
||||
</Tooltip>
|
||||
{message.role === 'user' && (
|
||||
<Tooltip title={t('chat.resend')}>
|
||||
<ActionIconButton onClick={handleResend}>
|
||||
<Send size={16} />
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onPress={handleResend} icon={<Send size={16} />} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</ActionBarRight>
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ReloadOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
|
||||
import type { Topic } from '@renderer/types'
|
||||
@@ -14,7 +15,7 @@ import type { Message } from '@renderer/types/newMessage'
|
||||
import { AssistantMessageStatus } from '@renderer/types/newMessage'
|
||||
import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
||||
import type { MultiModelMessageStyle } from '@shared/data/preference/preferenceTypes'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -137,19 +138,19 @@ const MessageGroupMenuBar: FC<Props> = ({
|
||||
{hasFailedMessages && (
|
||||
<Tooltip title={t('message.group.retry_failed')} mouseEnterDelay={0.6}>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<ReloadOutlined />}
|
||||
onClick={handleRetryAll}
|
||||
style={{ marginRight: 4 }}
|
||||
variant="light"
|
||||
size="sm"
|
||||
startContent={<ReloadOutlined />}
|
||||
onPress={handleRetryAll}
|
||||
className="mr-1"
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<DeleteOutlined style={{ color: 'var(--color-error)' }} />}
|
||||
onClick={handleDeleteGroup}
|
||||
variant="light"
|
||||
size="sm"
|
||||
startContent={<DeleteOutlined style={{ color: 'var(--color-error)' }} />}
|
||||
onPress={handleDeleteGroup}
|
||||
/>
|
||||
</GroupMenuBar>
|
||||
)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { FormOutlined } from '@ant-design/icons'
|
||||
import { Button, cn } from '@cherrystudio/ui'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { EventEmitter } from '@renderer/services/EventService'
|
||||
import { EVENT_NAMES } from '@renderer/services/EventService'
|
||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Button as AntdButton } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const NewTopicButton: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -17,39 +16,29 @@ const NewTopicButton: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Button size="small" color="primary" icon={<FormOutlined />} onClick={addNewTopic} $theme={theme}>
|
||||
<div className="-mt-2.5 mb-2.5 flex min-h-auto items-center justify-center p-0">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="light"
|
||||
color="primary"
|
||||
radius="full"
|
||||
startContent={<FormOutlined />}
|
||||
onPress={addNewTopic}
|
||||
className={cn(
|
||||
'h-[34px]! px-3 text-xs opacity-80 transition-all duration-300',
|
||||
'hover:border-[var(--color-border-mute)] hover:text-[var(--color-text-1)]! hover:opacity-90',
|
||||
theme === ThemeMode.dark
|
||||
? 'bg-[var(--color-background-soft)] hover:bg-[var(--color-background-mute)]!'
|
||||
: undefined
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: theme === ThemeMode.dark ? '' : undefined,
|
||||
color: 'var(--color-text-2)'
|
||||
}}>
|
||||
{t('chat.topics.new')}
|
||||
</Button>
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
margin-top: -10px;
|
||||
padding: 0;
|
||||
min-height: auto;
|
||||
`
|
||||
|
||||
const Button = styled(AntdButton)<{ $theme: ThemeMode }>`
|
||||
border-radius: 20px;
|
||||
padding: 0 12px;
|
||||
height: 34px !important;
|
||||
font-size: 12px;
|
||||
opacity: 0.8;
|
||||
transition: all 0.3s ease;
|
||||
background-color: ${(props) => (props.$theme === ThemeMode.dark ? 'var(--color-background-soft)' : '')};
|
||||
color: var(--color-text-2);
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
background-color: ${(props) => (props.$theme === ThemeMode.dark ? 'var(--color-background-mute)' : '')} !important;
|
||||
color: var(--color-text-1) !important;
|
||||
border-color: var(--color-border-mute) !important;
|
||||
}
|
||||
`
|
||||
|
||||
export default NewTopicButton
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { CopyIcon, LoadingIcon } from '@renderer/components/Icons'
|
||||
@@ -11,7 +12,7 @@ import { isToolAutoApproved } from '@renderer/utils/mcp-tools'
|
||||
import { cancelToolAction, confirmToolAction } from '@renderer/utils/userConfirmation'
|
||||
import type { MCPProgressEvent } from '@shared/config/types'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { Button, Collapse, ConfigProvider, Dropdown, Modal, Progress, Tabs, Tooltip } from 'antd'
|
||||
import { Collapse, ConfigProvider, Dropdown, Modal, Progress, Tabs, Tooltip } from 'antd'
|
||||
import {
|
||||
Check,
|
||||
ChevronDown,
|
||||
@@ -400,26 +401,25 @@ const MessageMcpTool: FC<Props> = ({ block }) => {
|
||||
{isWaitingConfirmation && (
|
||||
<Button
|
||||
color="danger"
|
||||
variant="filled"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
variant="solid"
|
||||
size="sm"
|
||||
onPress={() => {
|
||||
handleCancelTool()
|
||||
}}>
|
||||
<CircleX size={15} className="lucide-custom" />
|
||||
}}
|
||||
startContent={<CircleX size={15} className="lucide-custom" />}>
|
||||
{t('common.cancel')}
|
||||
</Button>
|
||||
)}
|
||||
{isExecuting && toolResponse?.id ? (
|
||||
<Button
|
||||
size="small"
|
||||
size="sm"
|
||||
color="danger"
|
||||
variant="solid"
|
||||
className="abort-button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onPress={() => {
|
||||
handleAbortTool()
|
||||
}}>
|
||||
<PauseCircle size={14} className="lucide-custom" />
|
||||
}}
|
||||
startContent={<PauseCircle size={14} className="lucide-custom" />}>
|
||||
{t('chat.input.pause')}
|
||||
</Button>
|
||||
) : (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { RowFlex, Selector, Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useMultiplePreferences, usePreference } from '@data/hooks/usePreference'
|
||||
import EditableNumber from '@renderer/components/EditableNumber'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
@@ -20,7 +21,7 @@ import { modalConfirm } from '@renderer/utils'
|
||||
import { getSendMessageShortcutLabel } from '@renderer/utils/input'
|
||||
import type { SendMessageShortcut } from '@shared/data/preference/preferenceTypes'
|
||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Button, Col, InputNumber, Row, Slider } from 'antd'
|
||||
import { Col, InputNumber, Row, Slider } from 'antd'
|
||||
import { Settings2 } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
@@ -173,11 +174,12 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
extra={
|
||||
<RowFlex className="items-center gap-0.5">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<Settings2 size={16} />}
|
||||
onClick={() => AssistantSettingsPopup.show({ assistant, tab: 'model' })}
|
||||
/>
|
||||
variant="light"
|
||||
size="sm"
|
||||
isIconOnly
|
||||
onPress={() => AssistantSettingsPopup.show({ assistant, tab: 'model' })}>
|
||||
<Settings2 size={16} />
|
||||
</Button>
|
||||
</RowFlex>
|
||||
}>
|
||||
<SettingGroup style={{ marginTop: 5 }}>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Box } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useTags } from '@renderer/hooks/useTags'
|
||||
import { Button, Empty, Modal } from 'antd'
|
||||
import { Empty, Modal } from 'antd'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -93,14 +94,14 @@ const PopupContainer: React.FC<Props> = ({ title, resolve }) => {
|
||||
<TagItem ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
||||
<Box className="mr-2">{tag}</Box>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
danger
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
variant="light"
|
||||
color="danger"
|
||||
isIconOnly
|
||||
onPress={() => {
|
||||
onDelete(tag)
|
||||
}}
|
||||
/>
|
||||
}}>
|
||||
<DeleteIcon size={16} className="lucide-custom" />
|
||||
</Button>
|
||||
</TagItem>
|
||||
)}
|
||||
</Draggable>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import SelectModelPopup from '@renderer/components/Popups/SelectModelPopup'
|
||||
import { isLocalAi } from '@renderer/config/env'
|
||||
@@ -6,7 +7,7 @@ import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { Assistant, Model } from '@renderer/types'
|
||||
import { Button, Tag } from 'antd'
|
||||
import { Tag } from 'antd'
|
||||
import { ChevronsUpDown } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useRef } from 'react'
|
||||
@@ -25,8 +26,7 @@ const SelectModelButton: FC<Props> = ({ assistant }) => {
|
||||
|
||||
const modelFilter = (model: Model) => !isEmbeddingModel(model) && !isRerankModel(model)
|
||||
|
||||
const onSelectModel = async (event: React.MouseEvent<HTMLElement>) => {
|
||||
event.currentTarget.blur()
|
||||
const onSelectModel = async () => {
|
||||
const selectedModel = await SelectModelPopup.show({ model, filter: modelFilter })
|
||||
if (selectedModel) {
|
||||
// 避免更新数据造成关闭弹框的卡顿
|
||||
@@ -55,7 +55,11 @@ const SelectModelButton: FC<Props> = ({ assistant }) => {
|
||||
const providerName = getProviderName(model)
|
||||
|
||||
return (
|
||||
<DropdownButton size="small" type="text" onClick={onSelectModel}>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="light"
|
||||
onPress={onSelectModel}
|
||||
className="mt-0.5 rounded-2xl border border-transparent border-solid bg-transparent px-1 py-3 text-xs shadow-none">
|
||||
<ButtonContent>
|
||||
<ModelAvatar model={model} size={20} />
|
||||
<ModelName>
|
||||
@@ -64,21 +68,10 @@ const SelectModelButton: FC<Props> = ({ assistant }) => {
|
||||
</ButtonContent>
|
||||
<ChevronsUpDown size={14} color="var(--color-icon)" />
|
||||
{!provider && <Tag color="error">{t('models.invalid_model')}</Tag>}
|
||||
</DropdownButton>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
const DropdownButton = styled(Button)`
|
||||
font-size: 11px;
|
||||
border-radius: 15px;
|
||||
padding: 13px 5px;
|
||||
-webkit-app-region: none;
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
margin-top: 1px;
|
||||
`
|
||||
|
||||
const ButtonContent = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SyncOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { useAppUpdateState } from '@renderer/hooks/useAppUpdate'
|
||||
import { Button } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@@ -23,11 +23,11 @@ const UpdateAppButton: FC = () => {
|
||||
<Container>
|
||||
<UpdateButton
|
||||
className="nodrag"
|
||||
onClick={() => window.api.showUpdateDialog()}
|
||||
icon={<SyncOutlined />}
|
||||
color="orange"
|
||||
variant="outlined"
|
||||
size="small">
|
||||
onPress={() => window.api.showUpdateDialog()}
|
||||
startContent={<SyncOutlined />}
|
||||
color="warning"
|
||||
variant="bordered"
|
||||
size="sm">
|
||||
{t('button.update_available')}
|
||||
</UpdateButton>
|
||||
</Container>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { RedoOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||
import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import { NavbarIcon } from '@renderer/pages/home/ChatNavbar'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase } from '@renderer/types'
|
||||
import { Button, Empty, Tabs, Tag, Tooltip } from 'antd'
|
||||
import { Empty, Tabs, Tag, Tooltip } from 'antd'
|
||||
import { Book, Folder, Globe, Link, Notebook, Search, Settings, Video } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -145,10 +146,11 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<HeaderContainer>
|
||||
<ModelInfo>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<Settings size={18} color="var(--color-icon)" />}
|
||||
onClick={() => EditKnowledgeBasePopup.show({ base })}
|
||||
size="small"
|
||||
variant="light"
|
||||
startContent={<Settings size={18} color="var(--color-icon)" />}
|
||||
isIconOnly
|
||||
onPress={() => EditKnowledgeBasePopup.show({ base })}
|
||||
size="sm"
|
||||
/>
|
||||
<div className="model-row">
|
||||
<div className="label-column">
|
||||
@@ -339,7 +341,7 @@ export const FlexAlignCenter = styled.div`
|
||||
|
||||
export const ResponsiveButton = styled(Button)`
|
||||
@media (max-width: 1080px) {
|
||||
.ant-btn-icon + span {
|
||||
[data-slot="icon"] + [data-slot="label"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
@@ -6,7 +7,7 @@ import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -69,13 +70,11 @@ const KnowledgeDirectories: FC<KnowledgeContentProps> = ({ selectedBase, progres
|
||||
<ItemContainer>
|
||||
<ItemHeader>
|
||||
<ResponsiveButton
|
||||
type="primary"
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddDirectory()
|
||||
}}
|
||||
disabled={disabled}>
|
||||
variant="solid"
|
||||
color="primary"
|
||||
startContent={<PlusIcon size={16} />}
|
||||
onPress={handleAddDirectory}
|
||||
isDisabled={disabled}>
|
||||
{t('knowledge.add_directory')}
|
||||
</ResponsiveButton>
|
||||
</ItemHeader>
|
||||
@@ -103,7 +102,11 @@ const KnowledgeDirectories: FC<KnowledgeContentProps> = ({ selectedBase, progres
|
||||
extra: getDisplayTime(item),
|
||||
actions: (
|
||||
<FlexAlignCenter>
|
||||
{item.uniqueId && <Button type="text" icon={<RefreshIcon />} onClick={() => refreshItem(item)} />}
|
||||
{item.uniqueId && (
|
||||
<Button variant="light" isIconOnly onPress={() => refreshItem(item)}>
|
||||
<RefreshIcon />
|
||||
</Button>
|
||||
)}
|
||||
<StatusIconWrapper>
|
||||
<StatusIcon
|
||||
sourceId={item.id}
|
||||
@@ -113,12 +116,9 @@ const KnowledgeDirectories: FC<KnowledgeContentProps> = ({ selectedBase, progres
|
||||
type="directory"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
<Button variant="light" color="danger" isIconOnly onPress={() => removeItem(item)}>
|
||||
<DeleteIcon size={14} className="lucide-custom" />
|
||||
</Button>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { useFiles } from '@renderer/hooks/useFiles'
|
||||
@@ -10,7 +11,7 @@ import type { FileMetadata, FileTypes, KnowledgeBase, KnowledgeItem } from '@ren
|
||||
import { isKnowledgeFileItem } from '@renderer/types'
|
||||
import { formatFileSize, uuid } from '@renderer/utils'
|
||||
import { bookExts, documentExts, textExts, thirdPartyApplicationExts } from '@shared/config/constant'
|
||||
import { Button, Tooltip, Upload } from 'antd'
|
||||
import { Tooltip, Upload } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
@@ -142,13 +143,12 @@ const KnowledgeFiles: FC<KnowledgeContentProps> = ({ selectedBase, progressMap,
|
||||
<ItemContainer>
|
||||
<ItemHeader>
|
||||
<ResponsiveButton
|
||||
type="primary"
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddFile()
|
||||
}}
|
||||
disabled={disabled}>
|
||||
size="sm"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
startContent={<PlusIcon size={16} />}
|
||||
onPress={handleAddFile}
|
||||
isDisabled={disabled}>
|
||||
{t('knowledge.add_file')}
|
||||
</ResponsiveButton>
|
||||
</ItemHeader>
|
||||
@@ -202,7 +202,9 @@ const KnowledgeFiles: FC<KnowledgeContentProps> = ({ selectedBase, progressMap,
|
||||
actions: (
|
||||
<FlexAlignCenter>
|
||||
{item.uniqueId && (
|
||||
<Button type="text" icon={<RefreshIcon />} onClick={() => refreshItem(item)} />
|
||||
<Button variant="light" isIconOnly onPress={() => refreshItem(item)}>
|
||||
<RefreshIcon />
|
||||
</Button>
|
||||
)}
|
||||
{showPreprocessIcon(item) && (
|
||||
<StatusIconWrapper>
|
||||
@@ -224,12 +226,9 @@ const KnowledgeFiles: FC<KnowledgeContentProps> = ({ selectedBase, progressMap,
|
||||
type="file"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
<Button variant="light" color="danger" isIconOnly onPress={() => removeItem(item)}>
|
||||
<DeleteIcon size={14} className="lucide-custom" />
|
||||
</Button>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import RichEditPopup from '@renderer/components/Popups/RichEditPopup'
|
||||
import { DynamicVirtualList } from '@renderer/components/VirtualList'
|
||||
@@ -6,7 +7,6 @@ import FileItem from '@renderer/pages/files/FileItem'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { isMarkdownContent, markdownToPreviewText } from '@renderer/utils/markdownConverter'
|
||||
import { Button } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -82,13 +82,11 @@ const KnowledgeNotes: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ItemContainer>
|
||||
<ItemHeader>
|
||||
<ResponsiveButton
|
||||
type="primary"
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddNote()
|
||||
}}
|
||||
disabled={disabled}>
|
||||
variant="solid"
|
||||
color="primary"
|
||||
startContent={<PlusIcon size={16} />}
|
||||
onPress={handleAddNote}
|
||||
isDisabled={disabled}>
|
||||
{t('knowledge.add_note')}
|
||||
</ResponsiveButton>
|
||||
</ItemHeader>
|
||||
@@ -114,7 +112,9 @@ const KnowledgeNotes: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra: getDisplayTime(note),
|
||||
actions: (
|
||||
<FlexAlignCenter>
|
||||
<Button type="text" onClick={() => handleEditNote(note)} icon={<EditIcon size={14} />} />
|
||||
<Button variant="light" isIconOnly onPress={() => handleEditNote(note)}>
|
||||
<EditIcon size={14} />
|
||||
</Button>
|
||||
<StatusIconWrapper>
|
||||
<StatusIcon
|
||||
sourceId={note.id}
|
||||
@@ -123,12 +123,9 @@ const KnowledgeNotes: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
type="note"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(note)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
<Button variant="light" color="danger" isIconOnly onPress={() => removeItem(note)}>
|
||||
<DeleteIcon size={14} className="lucide-custom" />
|
||||
</Button>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
@@ -7,7 +8,7 @@ import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -88,13 +89,11 @@ const KnowledgeSitemaps: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ItemContainer>
|
||||
<ItemHeader>
|
||||
<ResponsiveButton
|
||||
type="primary"
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddSitemap()
|
||||
}}
|
||||
disabled={disabled}>
|
||||
variant="solid"
|
||||
color="primary"
|
||||
startContent={<PlusIcon size={16} />}
|
||||
onPress={handleAddSitemap}
|
||||
isDisabled={disabled}>
|
||||
{t('knowledge.add_sitemap')}
|
||||
</ResponsiveButton>
|
||||
</ItemHeader>
|
||||
@@ -126,7 +125,11 @@ const KnowledgeSitemaps: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra: getDisplayTime(item),
|
||||
actions: (
|
||||
<FlexAlignCenter>
|
||||
{item.uniqueId && <Button type="text" icon={<RefreshIcon />} onClick={() => refreshItem(item)} />}
|
||||
{item.uniqueId && (
|
||||
<Button variant="light" isIconOnly onPress={() => refreshItem(item)}>
|
||||
<RefreshIcon />
|
||||
</Button>
|
||||
)}
|
||||
<StatusIconWrapper>
|
||||
<StatusIcon
|
||||
sourceId={item.id}
|
||||
@@ -135,12 +138,9 @@ const KnowledgeSitemaps: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
type="sitemap"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
<Button variant="light" color="danger" isIconOnly onPress={() => removeItem(item)}>
|
||||
<DeleteIcon size={14} className="lucide-custom" />
|
||||
</Button>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { CopyIcon, DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
@@ -6,7 +7,7 @@ import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Button, Dropdown, Tooltip } from 'antd'
|
||||
import { Dropdown, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -116,13 +117,11 @@ const KnowledgeUrls: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ItemContainer>
|
||||
<ItemHeader>
|
||||
<ResponsiveButton
|
||||
type="primary"
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddUrl()
|
||||
}}
|
||||
disabled={disabled}>
|
||||
variant="solid"
|
||||
color="primary"
|
||||
startContent={<PlusIcon size={16} />}
|
||||
onPress={handleAddUrl}
|
||||
isDisabled={disabled}>
|
||||
{t('knowledge.add_url')}
|
||||
</ResponsiveButton>
|
||||
</ItemHeader>
|
||||
@@ -176,16 +175,17 @@ const KnowledgeUrls: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra: getDisplayTime(item),
|
||||
actions: (
|
||||
<FlexAlignCenter>
|
||||
{item.uniqueId && <Button type="text" icon={<RefreshIcon />} onClick={() => refreshItem(item)} />}
|
||||
{item.uniqueId && (
|
||||
<Button variant="light" isIconOnly onPress={() => refreshItem(item)}>
|
||||
<RefreshIcon />
|
||||
</Button>
|
||||
)}
|
||||
<StatusIconWrapper>
|
||||
<StatusIcon sourceId={item.id} base={base} getProcessingStatus={getProcessingStatus} type="url" />
|
||||
</StatusIconWrapper>
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
<Button variant="light" color="danger" isIconOnly onPress={() => removeItem(item)}>
|
||||
<DeleteIcon size={14} className="lucide-custom" />
|
||||
</Button>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DeleteOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import VideoPopup from '@renderer/components/Popups/VideoPopup'
|
||||
@@ -7,7 +8,7 @@ import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { FileTypes, isKnowledgeVideoItem } from '@renderer/types'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { Plus } from 'lucide-react'
|
||||
import VirtualList from 'rc-virtual-list'
|
||||
@@ -87,13 +88,11 @@ const KnowledgeVideos: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ItemContainer>
|
||||
<ItemHeader>
|
||||
<ResponsiveButton
|
||||
type="primary"
|
||||
icon={<Plus size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddVideo()
|
||||
}}
|
||||
disabled={disabled}>
|
||||
variant="solid"
|
||||
color="primary"
|
||||
startContent={<Plus size={16} />}
|
||||
onPress={handleAddVideo}
|
||||
isDisabled={disabled}>
|
||||
{t('knowledge.add_video')}
|
||||
</ResponsiveButton>
|
||||
</ItemHeader>
|
||||
@@ -139,7 +138,12 @@ const KnowledgeVideos: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
actions: (
|
||||
<FlexAlignCenter>
|
||||
{item.uniqueId && (
|
||||
<Button type="text" icon={<RefreshIcon />} onClick={() => refreshItem(item)} />
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<RefreshIcon />}
|
||||
isIconOnly
|
||||
onPress={() => refreshItem(item)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<StatusIconWrapper>
|
||||
@@ -150,7 +154,13 @@ const KnowledgeVideos: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
type="file"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button type="text" danger onClick={() => removeItem(item)} icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
variant="light"
|
||||
color="danger"
|
||||
startContent={<DeleteOutlined />}
|
||||
isIconOnly
|
||||
onPress={() => removeItem(item)}
|
||||
/>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Navbar, NavbarMain } from '@renderer/components/app/Navbar'
|
||||
import App from '@renderer/components/MinApp/MinApp'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { Button, Input } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import { Search, SettingsIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
@@ -56,10 +57,11 @@ const AppsPage: FC = () => {
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
variant="light"
|
||||
className="nodrag"
|
||||
icon={<SettingsIcon size={18} color="var(--color-text-2)" />}
|
||||
onClick={MinappSettingsPopup.show}
|
||||
startContent={<SettingsIcon size={18} color="var(--color-text-2)" />}
|
||||
isIconOnly
|
||||
onPress={MinappSettingsPopup.show}
|
||||
/>
|
||||
</NavbarMain>
|
||||
</Navbar>
|
||||
@@ -78,10 +80,11 @@ const AppsPage: FC = () => {
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
variant="light"
|
||||
className="nodrag"
|
||||
icon={<SettingsIcon size={18} color="var(--color-text-2)" />}
|
||||
onClick={() => MinappSettingsPopup.show()}
|
||||
startContent={<SettingsIcon size={18} color="var(--color-text-2)" />}
|
||||
isIconOnly
|
||||
onPress={() => MinappSettingsPopup.show()}
|
||||
/>
|
||||
</HeaderContainer>
|
||||
)}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { UndoOutlined } from '@ant-design/icons' // 导入重置图标
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { SettingDescription, SettingDivider, SettingRowTitle, SettingTitle } from '@renderer/pages/settings'
|
||||
import { Button, Slider, Tooltip } from 'antd'
|
||||
import { Slider, Tooltip } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -79,8 +80,8 @@ const MiniAppSettings: FC = () => {
|
||||
<Container>
|
||||
<SettingTitle style={{ display: 'flex', flexDirection: 'row', justifyContent: 'flex-end', alignItems: 'center' }}>
|
||||
<ButtonWrapper>
|
||||
<Button onClick={handleSwapMinApps}>{t('common.swap')}</Button>
|
||||
<Button onClick={handleResetMinApps}>{t('common.reset')}</Button>
|
||||
<Button onPress={handleSwapMinApps}>{t('common.swap')}</Button>
|
||||
<Button onPress={handleResetMinApps}>{t('common.reset')}</Button>
|
||||
</ButtonWrapper>
|
||||
</SettingTitle>
|
||||
<BorderedContainer>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { PlusOutlined, UploadOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { loadCustomMiniApp, ORIGIN_DEFAULT_MIN_APPS, updateDefaultMinApps } from '@renderer/config/minapps'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import type { MinAppType } from '@renderer/types'
|
||||
import { Button, Form, Input, Modal, Radio, Upload } from 'antd'
|
||||
import { Form, Input, Modal, Radio, Upload } from 'antd'
|
||||
import type { UploadFile } from 'antd/es/upload/interface'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
@@ -146,12 +147,12 @@ const NewAppButton: FC<Props> = ({ size = 60 }) => {
|
||||
fileList={fileList}
|
||||
onChange={handleFileChange}
|
||||
beforeUpload={() => false}>
|
||||
<Button icon={<UploadOutlined />}>{t('settings.miniapps.custom.logo_upload_button')}</Button>
|
||||
<Button startContent={<UploadOutlined />}>{t('settings.miniapps.custom.logo_upload_button')}</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
<Button variant="solid" color="primary" type="submit">
|
||||
{t('settings.miniapps.custom.save')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button, RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
@@ -21,7 +21,7 @@ import { translateText } from '@renderer/services/TranslateService'
|
||||
import type { FileMetadata } from '@renderer/types'
|
||||
import type { PaintingAction, PaintingsState } from '@renderer/types'
|
||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||
import { Avatar, Button, Input, InputNumber, Radio, Segmented, Select, Slider, Tooltip, Upload } from 'antd'
|
||||
import { Avatar, Input, InputNumber, Radio, Segmented, Select, Slider, Tooltip, Upload } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { Info } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -827,7 +827,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('paintings.title')}</NavbarCenter>
|
||||
{isMac && (
|
||||
<NavbarRight style={{ justifyContent: 'flex-end' }}>
|
||||
<Button size="small" className="nodrag" icon={<PlusOutlined />} onClick={handleAddPainting}>
|
||||
<Button size="sm" className="nodrag" startContent={<PlusOutlined />} onPress={handleAddPainting}>
|
||||
{t('paintings.button.new.image')}
|
||||
</Button>
|
||||
</NavbarRight>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button, RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import DMXAPIToImg from '@renderer/assets/images/providers/DMXAPI-to-img.webp'
|
||||
@@ -14,7 +14,7 @@ import FileManager from '@renderer/services/FileManager'
|
||||
import type { FileMetadata } from '@renderer/types'
|
||||
import { convertToBase64, uuid } from '@renderer/utils'
|
||||
import type { DmxapiPainting } from '@types'
|
||||
import { Avatar, Button, Input, InputNumber, Segmented, Select, Tooltip } from 'antd'
|
||||
import { Avatar, Input, InputNumber, Segmented, Select, Tooltip } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { Info } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -787,7 +787,7 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('paintings.title')}</NavbarCenter>
|
||||
{isMac && (
|
||||
<NavbarRight style={{ justifyContent: 'flex-end' }}>
|
||||
<Button size="small" className="nodrag" icon={<PlusOutlined />} onClick={createNewPainting}>
|
||||
<Button size="sm" className="nodrag" startContent={<PlusOutlined />} onPress={createNewPainting}>
|
||||
{t('paintings.button.new.image')}
|
||||
</Button>
|
||||
</NavbarRight>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
@@ -27,7 +28,7 @@ import { translateText } from '@renderer/services/TranslateService'
|
||||
import type { PaintingAction, PaintingsState } from '@renderer/types'
|
||||
import type { FileMetadata } from '@renderer/types'
|
||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||
import { Avatar, Button, Empty, InputNumber, Segmented, Select, Upload } from 'antd'
|
||||
import { Avatar, Empty, InputNumber, Segmented, Select, Upload } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
@@ -489,7 +490,7 @@ const NewApiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('paintings.title')}</NavbarCenter>
|
||||
{isMac && (
|
||||
<NavbarRight style={{ justifyContent: 'flex-end' }}>
|
||||
<Button size="small" className="nodrag" icon={<PlusOutlined />} onClick={handleAddPainting}>
|
||||
<Button size="sm" className="nodrag" startContent={<PlusOutlined />} onPress={handleAddPainting}>
|
||||
{t('paintings.button.new.image')}
|
||||
</Button>
|
||||
</NavbarRight>
|
||||
@@ -531,7 +532,7 @@ const NewApiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
description={t('paintings.no_image_generation_model', {
|
||||
endpoint_type: t('endpoint_type.image-generation')
|
||||
})}>
|
||||
<Button type="primary" onClick={handleShowAddModelPopup}>
|
||||
<Button variant="solid" color="primary" onPress={handleShowAddModelPopup}>
|
||||
{t('paintings.go_to_settings')}
|
||||
</Button>
|
||||
</Empty>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
|
||||
import { ColFlex, RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
@@ -25,7 +26,7 @@ import FileManager from '@renderer/services/FileManager'
|
||||
import { translateText } from '@renderer/services/TranslateService'
|
||||
import type { FileMetadata, Painting } from '@renderer/types'
|
||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||
import { Button, Input, InputNumber, Radio, Select, Slider, Tooltip } from 'antd'
|
||||
import { Input, InputNumber, Radio, Select, Slider, Tooltip } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { Info } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -374,10 +375,10 @@ const SiliconPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
{isMac && (
|
||||
<NavbarRight style={{ justifyContent: 'flex-end' }}>
|
||||
<Button
|
||||
size="small"
|
||||
size="sm"
|
||||
className="nodrag"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => setPainting(addPainting('siliconflow_paintings', getNewPainting()))}>
|
||||
startContent={<PlusOutlined />}
|
||||
onPress={() => setPainting(addPainting('siliconflow_paintings', getNewPainting()))}>
|
||||
{t('paintings.button.new.image')}
|
||||
</Button>
|
||||
</NavbarRight>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
@@ -15,7 +16,7 @@ import FileManager from '@renderer/services/FileManager'
|
||||
import { translateText } from '@renderer/services/TranslateService'
|
||||
import type { TokenFluxPainting } from '@renderer/types'
|
||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||
import { Avatar, Button, Select, Tooltip } from 'antd'
|
||||
import { Avatar, Select, Tooltip } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { Info } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -367,7 +368,7 @@ const TokenFluxPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('paintings.title')}</NavbarCenter>
|
||||
{isMac && (
|
||||
<NavbarRight style={{ justifyContent: 'flex-end' }}>
|
||||
<Button size="small" className="nodrag" icon={<PlusOutlined />} onClick={handleAddPainting}>
|
||||
<Button size="sm" className="nodrag" startContent={<PlusOutlined />} onPress={handleAddPainting}>
|
||||
{t('paintings.button.new.image')}
|
||||
</Button>
|
||||
</NavbarRight>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import AiProvider from '@renderer/aiCore'
|
||||
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
||||
@@ -11,7 +12,7 @@ import { useAllProviders } from '@renderer/hooks/useProvider'
|
||||
import { getProviderLabel } from '@renderer/i18n/label'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||
import { Avatar, Button, InputNumber, Radio, Select } from 'antd'
|
||||
import { Avatar, InputNumber, Radio, Select } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -342,8 +343,13 @@ const ZhipuPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
<Navbar>
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('paintings.title')}</NavbarCenter>
|
||||
{isMac && (
|
||||
<NavbarRight style={{ justifyContent: 'flex-end' }}>
|
||||
<Button size="small" className="nodrag" icon={<PlusOutlined />} onClick={handleAddPainting}>
|
||||
<NavbarRight>
|
||||
<Button
|
||||
size="sm"
|
||||
className="nodrag"
|
||||
variant="light"
|
||||
startContent={<PlusOutlined />}
|
||||
onPress={handleAddPainting}>
|
||||
{t('paintings.button.new.image')}
|
||||
</Button>
|
||||
</NavbarRight>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import ImageViewer from '@renderer/components/ImageViewer'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
import type { Painting } from '@renderer/types'
|
||||
import { Button, Spin } from 'antd'
|
||||
import { Spin } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -43,7 +44,7 @@ const Artboard: FC<ArtboardProps> = ({
|
||||
{painting.files.length > 0 ? (
|
||||
<ImageContainer>
|
||||
{painting.files.length > 1 && (
|
||||
<NavigationButton onClick={onPrevImage} style={{ left: 10 }}>
|
||||
<NavigationButton onPress={onPrevImage} className="left-2.5">
|
||||
←
|
||||
</NavigationButton>
|
||||
)}
|
||||
@@ -59,7 +60,7 @@ const Artboard: FC<ArtboardProps> = ({
|
||||
}}
|
||||
/>
|
||||
{painting.files.length > 1 && (
|
||||
<NavigationButton onClick={onNextImage} style={{ right: 10 }}>
|
||||
<NavigationButton onPress={onNextImage} className="right-2.5">
|
||||
→
|
||||
</NavigationButton>
|
||||
)}
|
||||
@@ -78,7 +79,7 @@ const Artboard: FC<ArtboardProps> = ({
|
||||
</ImageList>
|
||||
<div>
|
||||
{t('paintings.proxy_required')}
|
||||
<Button type="link" onClick={() => retry?.(painting)}>
|
||||
<Button variant="light" onPress={() => retry?.(painting)}>
|
||||
{t('paintings.image_retry')}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -96,7 +97,7 @@ const Artboard: FC<ArtboardProps> = ({
|
||||
<LoadingOverlay>
|
||||
<Spin size="large" />
|
||||
{loadText ? loadText : ''}
|
||||
<CancelButton onClick={onCancel}>{t('common.cancel')}</CancelButton>
|
||||
<CancelButton onPress={onCancel}>{t('common.cancel')}</CancelButton>
|
||||
</LoadingOverlay>
|
||||
)}
|
||||
</LoadingContainer>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { CloseOutlined, LinkOutlined, RedoOutlined, UploadOutlined } from '@ant-design/icons'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { convertToBase64 } from '@renderer/utils'
|
||||
import { Button, Input, InputNumber, Select, Upload } from 'antd'
|
||||
import { Input, InputNumber, Select, Upload } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
@@ -75,15 +76,7 @@ export const DynamicFormRender: React.FC<DynamicFormRenderProps> = ({
|
||||
handleImageUpload(propertyName, file, onChange)
|
||||
return false
|
||||
}}>
|
||||
<Button
|
||||
icon={<UploadOutlined />}
|
||||
title="Upload image file"
|
||||
style={{
|
||||
borderTopLeftRadius: 0,
|
||||
borderBottomLeftRadius: 0,
|
||||
height: '32px'
|
||||
}}
|
||||
/>
|
||||
<Button startContent={<UploadOutlined />} title="Upload image file" className="h-8 rounded-l-none" />
|
||||
</Upload>
|
||||
</div>
|
||||
|
||||
@@ -123,12 +116,12 @@ export const DynamicFormRender: React.FC<DynamicFormRenderProps> = ({
|
||||
{value.startsWith('data:') ? 'Uploaded image' : 'Image URL'}
|
||||
</div>
|
||||
<Button
|
||||
size="small"
|
||||
danger
|
||||
icon={<CloseOutlined />}
|
||||
onClick={() => onChange(propertyName, '')}
|
||||
size="sm"
|
||||
color="danger"
|
||||
startContent={<CloseOutlined />}
|
||||
onPress={() => onChange(propertyName, '')}
|
||||
title="Remove image"
|
||||
style={{ flexShrink: 0, minWidth: 'auto', padding: '0 8px' }}
|
||||
className="min-w-0 shrink-0 px-2"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -180,9 +173,9 @@ export const DynamicFormRender: React.FC<DynamicFormRenderProps> = ({
|
||||
max={schemaProperty.maximum}
|
||||
/>
|
||||
<Button
|
||||
size="small"
|
||||
icon={<RedoOutlined />}
|
||||
onClick={() => onChange(propertyName, generateRandomSeed())}
|
||||
size="sm"
|
||||
startContent={<RedoOutlined />}
|
||||
onPress={() => onChange(propertyName, generateRandomSeed())}
|
||||
title="Generate random seed"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { DeleteOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import IcImageUp from '@renderer/assets/images/paintings/ic_ImageUp.svg'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import type { FileMetadata } from '@renderer/types'
|
||||
import { Popconfirm, Upload } from 'antd'
|
||||
import { Button } from 'antd'
|
||||
import type { RcFile, UploadProps } from 'antd/es/upload'
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
@@ -45,7 +45,7 @@ const ImageUploader: React.FC<ImageUploaderProps> = ({
|
||||
<>
|
||||
<HeaderContainer>
|
||||
{fileMap.imageFiles && fileMap.imageFiles.length > 0 && (
|
||||
<Button size="small" onClick={onClearImages}>
|
||||
<Button size="sm" onPress={onClearImages}>
|
||||
清除全部
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { GithubOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import IndicatorLight from '@renderer/components/IndicatorLight'
|
||||
import { APP_NAME, AppLogo } from '@renderer/config/env'
|
||||
@@ -14,7 +15,7 @@ import { handleSaveData } from '@renderer/store'
|
||||
import { runAsyncFunction } from '@renderer/utils'
|
||||
import { UpgradeChannel } from '@shared/data/preference/preferenceTypes'
|
||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Avatar, Button, Progress, Radio, Row, Tag, Tooltip } from 'antd'
|
||||
import { Avatar, Progress, Radio, Row, Tag, Tooltip } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
import { Bug, FileCheck, Globe, Mail, Rss } from 'lucide-react'
|
||||
import { BadgeQuestionMark } from 'lucide-react'
|
||||
@@ -222,9 +223,9 @@ const AboutSettings: FC = () => {
|
||||
</Row>
|
||||
{!isPortable && (
|
||||
<CheckUpdateButton
|
||||
onClick={onCheckUpdate}
|
||||
loading={appUpdateState.checking}
|
||||
disabled={appUpdateState.downloading || appUpdateState.checking}>
|
||||
onPress={onCheckUpdate}
|
||||
isLoading={appUpdateState.checking}
|
||||
isDisabled={appUpdateState.downloading || appUpdateState.checking}>
|
||||
{appUpdateState.downloading
|
||||
? t('settings.about.downloading')
|
||||
: appUpdateState.available
|
||||
@@ -292,7 +293,7 @@ const AboutSettings: FC = () => {
|
||||
<BadgeQuestionMark size={18} />
|
||||
{t('docs.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={onOpenDocs}>{t('settings.about.website.button')}</Button>
|
||||
<Button onPress={onOpenDocs}>{t('settings.about.website.button')}</Button>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@@ -300,7 +301,7 @@ const AboutSettings: FC = () => {
|
||||
<Rss size={18} />
|
||||
{t('settings.about.releases.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={showReleases}>{t('settings.about.releases.button')}</Button>
|
||||
<Button onPress={showReleases}>{t('settings.about.releases.button')}</Button>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@@ -308,7 +309,7 @@ const AboutSettings: FC = () => {
|
||||
<Globe size={18} />
|
||||
{t('settings.about.website.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={() => onOpenWebsite('https://cherry-ai.com')}>{t('settings.about.website.button')}</Button>
|
||||
<Button onPress={() => onOpenWebsite('https://cherry-ai.com')}>{t('settings.about.website.button')}</Button>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@@ -316,7 +317,7 @@ const AboutSettings: FC = () => {
|
||||
<GithubOutlined size={18} />
|
||||
{t('settings.about.feedback.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={() => onOpenWebsite('https://github.com/CherryHQ/cherry-studio/issues/new/choose')}>
|
||||
<Button onPress={() => onOpenWebsite('https://github.com/CherryHQ/cherry-studio/issues/new/choose')}>
|
||||
{t('settings.about.feedback.button')}
|
||||
</Button>
|
||||
</SettingRow>
|
||||
@@ -326,7 +327,7 @@ const AboutSettings: FC = () => {
|
||||
<FileCheck size={18} />
|
||||
{t('settings.about.license.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={showLicense}>{t('settings.about.license.button')}</Button>
|
||||
<Button onPress={showLicense}>{t('settings.about.license.button')}</Button>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@@ -334,7 +335,7 @@ const AboutSettings: FC = () => {
|
||||
<Mail size={18} />
|
||||
{t('settings.about.contact.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={mailto}>{t('settings.about.contact.button')}</Button>
|
||||
<Button onPress={mailto}>{t('settings.about.contact.button')}</Button>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@@ -342,7 +343,7 @@ const AboutSettings: FC = () => {
|
||||
<Bug size={18} />
|
||||
{t('settings.about.debug.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={debug}>{t('settings.about.debug.open')}</Button>
|
||||
<Button onPress={debug}>{t('settings.about.debug.open')}</Button>
|
||||
</SettingRow>
|
||||
</SettingGroup>
|
||||
</SettingContainer>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { Box } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import MemoriesSettingsModal from '@renderer/pages/memory/settings-modal'
|
||||
import MemoryService from '@renderer/services/MemoryService'
|
||||
import { selectGlobalMemoryEnabled, selectMemoryConfig } from '@renderer/store/memory'
|
||||
import type { Assistant, AssistantSettings } from '@renderer/types'
|
||||
import { Alert, Button, Card, Space, Tooltip, Typography } from 'antd'
|
||||
import { Alert, Card, Space, Tooltip, Typography } from 'antd'
|
||||
import { useForm } from 'antd/es/form/Form'
|
||||
import { Settings2 } from 'lucide-react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
@@ -82,7 +83,7 @@ const AssistantMemorySettings: React.FC<Props> = ({ assistant, updateAssistant,
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Space>
|
||||
<Button type="text" icon={<Settings2 size={15} />} onClick={handleNavigateToMemory} />
|
||||
<Button variant="light" isIconOnly startContent={<Settings2 size={15} />} onPress={handleNavigateToMemory} />
|
||||
<Tooltip
|
||||
title={
|
||||
!globalMemoryEnabled
|
||||
@@ -108,7 +109,7 @@ const AssistantMemorySettings: React.FC<Props> = ({ assistant, updateAssistant,
|
||||
showIcon
|
||||
style={{ marginBottom: 16 }}
|
||||
action={
|
||||
<Button size="small" onClick={handleNavigateToMemory}>
|
||||
<Button size="sm" onPress={handleNavigateToMemory}>
|
||||
{t('memory.go_to_memory_page')}
|
||||
</Button>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import EditableNumber from '@renderer/components/EditableNumber'
|
||||
import { DeleteIcon, ResetIcon } from '@renderer/components/Icons'
|
||||
@@ -12,7 +13,7 @@ import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import { SettingRow } from '@renderer/pages/settings'
|
||||
import type { Assistant, AssistantSettingCustomParameters, AssistantSettings, Model } from '@renderer/types'
|
||||
import { modalConfirm } from '@renderer/utils'
|
||||
import { Button, Col, Divider, Input, InputNumber, Row, Select, Slider, Tooltip } from 'antd'
|
||||
import { Col, Divider, Input, InputNumber, Row, Select, Slider, Tooltip } from 'antd'
|
||||
import { isNull } from 'lodash'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -221,20 +222,20 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
<Label>{t('assistants.settings.default_model')}</Label>
|
||||
<RowFlex className="items-center gap-[5px]">
|
||||
<ModelSelectButton
|
||||
icon={defaultModel ? <ModelAvatar model={defaultModel} size={20} /> : <PlusIcon size={18} />}
|
||||
onClick={onSelectModel}>
|
||||
startContent={defaultModel ? <ModelAvatar model={defaultModel} size={20} /> : <PlusIcon size={18} />}
|
||||
onPress={onSelectModel}>
|
||||
<ModelName>{defaultModel ? defaultModel.name : t('agents.edit.model.select.title')}</ModelName>
|
||||
</ModelSelectButton>
|
||||
{defaultModel && (
|
||||
<Button
|
||||
color="danger"
|
||||
variant="filled"
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
onClick={() => {
|
||||
variant="solid"
|
||||
isIconOnly
|
||||
startContent={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
onPress={() => {
|
||||
setDefaultModel(undefined)
|
||||
updateAssistant({ ...assistant, defaultModel: undefined })
|
||||
}}
|
||||
danger
|
||||
/>
|
||||
)}
|
||||
</RowFlex>
|
||||
@@ -457,7 +458,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
<Divider style={{ margin: '10px 0' }} />
|
||||
<SettingRow style={{ minHeight: 30 }}>
|
||||
<Label>{t('models.custom_parameters')}</Label>
|
||||
<Button icon={<PlusIcon size={18} />} onClick={onAddCustomParameter}>
|
||||
<Button startContent={<PlusIcon size={18} />} onPress={onAddCustomParameter}>
|
||||
{t('models.add_parameter')}
|
||||
</Button>
|
||||
</SettingRow>
|
||||
@@ -484,17 +485,19 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
<Col span={10}>{renderParameterValueInput(param, index)}</Col>
|
||||
<Col span={2} style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Button
|
||||
size="sm"
|
||||
color="danger"
|
||||
variant="filled"
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
onClick={() => onDeleteCustomParameter(index)}
|
||||
variant="solid"
|
||||
isIconOnly
|
||||
startContent={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
onPress={() => onDeleteCustomParameter(index)}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
))}
|
||||
<Divider style={{ margin: '15px 0' }} />
|
||||
<RowFlex className="justify-end">
|
||||
<Button onClick={onReset} danger type="primary" icon={<ResetIcon size={16} />}>
|
||||
<Button onPress={onReset} color="danger" variant="solid" startContent={<ResetIcon size={16} />}>
|
||||
{t('chat.settings.reset')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'emoji-picker-element'
|
||||
|
||||
import { CloseCircleFilled } from '@ant-design/icons'
|
||||
import CloseCircleFilled from '@ant-design/icons/lib/icons/CloseCircleFilled'
|
||||
import { Box, RowFlex, SpaceBetweenRowFlex } from '@cherrystudio/ui'
|
||||
import { CodeEditor } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { Popover, PopoverContent, PopoverTrigger, Tooltip } from '@heroui/react'
|
||||
import EmojiPicker from '@renderer/components/EmojiPicker'
|
||||
import type { RichEditorRef } from '@renderer/components/RichEditor/types'
|
||||
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
|
||||
@@ -11,7 +13,7 @@ import { usePromptProcessor } from '@renderer/hooks/usePromptProcessor'
|
||||
import { estimateTextTokens } from '@renderer/services/TokenService'
|
||||
import type { Assistant, AssistantSettings } from '@renderer/types'
|
||||
import { getLeadingEmoji } from '@renderer/utils'
|
||||
import { Button, Input, Popover } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import { Edit, HelpCircle, Save } from 'lucide-react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -75,37 +77,34 @@ const AssistantPromptSettings: React.FC<Props> = ({ assistant, updateAssistant }
|
||||
<Container>
|
||||
<Box className="mb-2 font-bold">{t('common.name')}</Box>
|
||||
<RowFlex className="items-center gap-2">
|
||||
<Popover content={<EmojiPicker onEmojiClick={handleEmojiSelect} />} arrow trigger="click">
|
||||
<EmojiButtonWrapper>
|
||||
<Button
|
||||
<EmojiDeleteButtonWrapper>
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<Button className="h-7 min-w-7 p-1 text-lg">{emoji}</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<EmojiPicker onEmojiClick={handleEmojiSelect} />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
{emoji && (
|
||||
<CloseCircleFilled
|
||||
className="delete-icon z-50"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleEmojiDelete()
|
||||
}}
|
||||
style={{
|
||||
fontSize: 18,
|
||||
padding: '4px',
|
||||
minWidth: '28px',
|
||||
height: '28px'
|
||||
}}>
|
||||
{emoji}
|
||||
</Button>
|
||||
{emoji && (
|
||||
<CloseCircleFilled
|
||||
className="delete-icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleEmojiDelete()
|
||||
}}
|
||||
style={{
|
||||
display: 'none',
|
||||
position: 'absolute',
|
||||
top: '-8px',
|
||||
right: '-8px',
|
||||
fontSize: '16px',
|
||||
color: '#ff4d4f',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</EmojiButtonWrapper>
|
||||
</Popover>
|
||||
display: 'none',
|
||||
position: 'absolute',
|
||||
top: '-8px',
|
||||
right: '-8px',
|
||||
fontSize: '16px',
|
||||
color: '#ff4d4f',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</EmojiDeleteButtonWrapper>
|
||||
<Input
|
||||
placeholder={t('common.assistant') + t('common.name')}
|
||||
value={name}
|
||||
@@ -117,9 +116,16 @@ const AssistantPromptSettings: React.FC<Props> = ({ assistant, updateAssistant }
|
||||
<SettingDivider />
|
||||
<RowFlex className="mb-2 items-center gap-1">
|
||||
<Box style={{ fontWeight: 'bold' }}>{t('common.prompt')}</Box>
|
||||
<Popover title={t('agents.add.prompt.variables.tip.title')} content={promptVarsContent}>
|
||||
<Tooltip
|
||||
content={
|
||||
<>
|
||||
<h1 className="text-lg">{t('agents.add.prompt.variables.tip.title')}</h1>
|
||||
{promptVarsContent}
|
||||
</>
|
||||
}
|
||||
showArrow>
|
||||
<HelpCircle size={14} color="var(--color-text-2)" />
|
||||
</Popover>
|
||||
</Tooltip>
|
||||
</RowFlex>
|
||||
<TextAreaContainer>
|
||||
<RichEditorContainer>
|
||||
@@ -151,9 +157,10 @@ const AssistantPromptSettings: React.FC<Props> = ({ assistant, updateAssistant }
|
||||
<SpaceBetweenRowFlex className="mt-2.5 w-full justify-end">
|
||||
<TokenCount>Tokens: {tokenCount}</TokenCount>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={showPreview ? <Edit size={14} /> : <Save size={14} />}
|
||||
onClick={() => {
|
||||
variant="solid"
|
||||
color="primary"
|
||||
startContent={showPreview ? <Edit size={14} /> : <Save size={14} />}
|
||||
onPress={() => {
|
||||
const currentScrollTop = editorRef.current?.getScrollTop?.() || 0
|
||||
if (showPreview) {
|
||||
setShowPreview(false)
|
||||
@@ -180,7 +187,7 @@ const Container = styled.div`
|
||||
overflow: hidden;
|
||||
`
|
||||
|
||||
const EmojiButtonWrapper = styled.div`
|
||||
const EmojiDeleteButtonWrapper = styled.div`
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
|
||||
+14
-6
@@ -1,10 +1,11 @@
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { DraggableList } from '@renderer/components/DraggableList'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
import type { Assistant, QuickPhrase } from '@renderer/types'
|
||||
import { Button, Input, Modal, Popconfirm, Space } from 'antd'
|
||||
import { Input, Modal, Popconfirm, Space } from 'antd'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -86,7 +87,7 @@ const AssistantRegularPromptsSettings: FC<AssistantRegularPromptsSettingsProps>
|
||||
<Container>
|
||||
<SettingTitle>
|
||||
{t('assistants.settings.regular_phrases.title', 'Regular Prompts')}
|
||||
<Button type="text" icon={<PlusIcon size={18} />} onClick={handleAdd} />
|
||||
<Button variant="light" isIconOnly startContent={<PlusIcon size={18} />} onPress={handleAdd} />
|
||||
</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@@ -106,7 +107,13 @@ const AssistantRegularPromptsSettings: FC<AssistantRegularPromptsSettingsProps>
|
||||
extra: prompt.content,
|
||||
actions: (
|
||||
<Flex className="gap-1 opacity-60">
|
||||
<Button key="edit" type="text" icon={<EditIcon size={14} />} onClick={() => handleEdit(prompt)} />
|
||||
<Button
|
||||
key="edit"
|
||||
variant="light"
|
||||
isIconOnly
|
||||
startContent={<EditIcon size={14} />}
|
||||
onPress={() => handleEdit(prompt)}
|
||||
/>
|
||||
<Popconfirm
|
||||
title={t('assistants.settings.regular_phrases.delete', 'Delete Prompt')}
|
||||
description={t(
|
||||
@@ -119,9 +126,10 @@ const AssistantRegularPromptsSettings: FC<AssistantRegularPromptsSettingsProps>
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}>
|
||||
<Button
|
||||
key="delete"
|
||||
type="text"
|
||||
danger
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
variant="light"
|
||||
color="danger"
|
||||
isIconOnly
|
||||
startContent={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</Flex>
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import DividerWithText from '@renderer/components/DividerWithText'
|
||||
import { NutstoreIcon } from '@renderer/components/Icons/NutstoreIcons'
|
||||
@@ -20,7 +21,7 @@ import { reset } from '@renderer/services/BackupService'
|
||||
import type { AppInfo } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { occupiedDirs } from '@shared/config/constant'
|
||||
import { Button, Progress, Typography } from 'antd'
|
||||
import { Progress, Typography } from 'antd'
|
||||
import { FileText, FolderCog, FolderInput, FolderOpen, SaveIcon, Sparkle } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -602,10 +603,10 @@ const DataSettings: FC = () => {
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
|
||||
<RowFlex className="justify-between gap-[5px]">
|
||||
<Button onClick={BackupPopup.show} icon={<SaveIcon size={14} />}>
|
||||
<Button onPress={BackupPopup.show} startContent={<SaveIcon size={14} />}>
|
||||
{t('settings.general.backup.button')}
|
||||
</Button>
|
||||
<Button onClick={RestorePopup.show} icon={<FolderOpen size={14} />}>
|
||||
<Button onPress={RestorePopup.show} startContent={<FolderOpen size={14} />}>
|
||||
{t('settings.general.restore.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
@@ -632,7 +633,7 @@ const DataSettings: FC = () => {
|
||||
</PathText>
|
||||
<StyledIcon onClick={() => handleOpenPath(appInfo?.appDataPath)} style={{ flexShrink: 0 }} />
|
||||
<RowFlex className="ml-2 gap-[5px]">
|
||||
<Button onClick={handleSelectAppDataPath}>{t('settings.data.app_data.select')}</Button>
|
||||
<Button onPress={handleSelectAppDataPath}>{t('settings.data.app_data.select')}</Button>
|
||||
</RowFlex>
|
||||
</PathRow>
|
||||
</SettingRow>
|
||||
@@ -645,7 +646,7 @@ const DataSettings: FC = () => {
|
||||
</PathText>
|
||||
<StyledIcon onClick={() => handleOpenPath(appInfo?.logsPath)} style={{ flexShrink: 0 }} />
|
||||
<RowFlex className="ml-2 gap-[5px]">
|
||||
<Button onClick={() => handleOpenPath(appInfo?.logsPath)}>
|
||||
<Button onPress={() => handleOpenPath(appInfo?.logsPath)}>
|
||||
{t('settings.data.app_logs.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
@@ -655,7 +656,7 @@ const DataSettings: FC = () => {
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.data.app_knowledge.label')}</SettingRowTitle>
|
||||
<RowFlex className="items-center gap-[5px]">
|
||||
<Button onClick={handleRemoveAllFiles}>{t('settings.data.app_knowledge.button.delete')}</Button>
|
||||
<Button onPress={handleRemoveAllFiles}>{t('settings.data.app_knowledge.button.delete')}</Button>
|
||||
</RowFlex>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
@@ -665,14 +666,14 @@ const DataSettings: FC = () => {
|
||||
{cacheSize && <CacheText>({cacheSize}MB)</CacheText>}
|
||||
</SettingRowTitle>
|
||||
<RowFlex className="gap-[5px]">
|
||||
<Button onClick={handleClearCache}>{t('settings.data.clear_cache.button')}</Button>
|
||||
<Button onPress={handleClearCache}>{t('settings.data.clear_cache.button')}</Button>
|
||||
</RowFlex>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.reset.title')}</SettingRowTitle>
|
||||
<RowFlex className="gap-[5px]">
|
||||
<Button onClick={reset} danger>
|
||||
<Button onPress={reset} color="danger">
|
||||
{t('settings.general.reset.title')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { AppLogo } from '@renderer/config/env'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { Button, Space, Tooltip } from 'antd'
|
||||
import { Space, Tooltip } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -114,7 +115,7 @@ const JoplinSettings: FC = () => {
|
||||
placeholder={t('settings.data.joplin.token_placeholder')}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<Button onClick={handleJoplinConnectionCheck}>{t('settings.data.joplin.check.button')}</Button>
|
||||
<Button onPress={handleJoplinConnectionCheck}>{t('settings.data.joplin.check.button')}</Button>
|
||||
</Space.Compact>
|
||||
</RowFlex>
|
||||
</SettingRow>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { DeleteOutlined, FolderOpenOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { LocalBackupManager } from '@renderer/components/LocalBackupManager'
|
||||
@@ -10,7 +11,7 @@ import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { startAutoSync, stopAutoSync } from '@renderer/services/BackupService'
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import type { AppInfo } from '@renderer/types'
|
||||
import { Button, Input, Tooltip } from 'antd'
|
||||
import { Input, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -193,10 +194,14 @@ const LocalBackupSettings: React.FC = () => {
|
||||
placeholder={t('settings.data.local.directory.placeholder')}
|
||||
style={{ minWidth: 200, maxWidth: 400, flex: 1 }}
|
||||
/>
|
||||
<Button icon={<FolderOpenOutlined />} onClick={handleBrowseDirectory}>
|
||||
<Button startContent={<FolderOpenOutlined />} onPress={handleBrowseDirectory}>
|
||||
{t('common.browse')}
|
||||
</Button>
|
||||
<Button icon={<DeleteOutlined />} onClick={handleClearDirectory} disabled={!localBackupDir} danger>
|
||||
<Button
|
||||
startContent={<DeleteOutlined />}
|
||||
onPress={handleClearDirectory}
|
||||
isDisabled={!localBackupDir}
|
||||
color="danger">
|
||||
{t('common.clear')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
@@ -205,10 +210,14 @@ const LocalBackupSettings: React.FC = () => {
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
|
||||
<RowFlex className="justify-between gap-[5px]">
|
||||
<Button onClick={showBackupModal} icon={<SaveOutlined />} loading={backuping} disabled={!localBackupDir}>
|
||||
<Button
|
||||
onPress={showBackupModal}
|
||||
startContent={<SaveOutlined />}
|
||||
isLoading={backuping}
|
||||
isDisabled={!localBackupDir}>
|
||||
{t('settings.data.local.backup.button')}
|
||||
</Button>
|
||||
<Button onClick={showBackupManager} icon={<FolderOpenOutlined />} disabled={!localBackupDir}>
|
||||
<Button onPress={showBackupManager} startContent={<FolderOpenOutlined />} isDisabled={!localBackupDir}>
|
||||
{t('settings.data.local.restore.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { DeleteOutlined, FolderOpenOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { Button } from 'antd'
|
||||
import Input from 'antd/es/input/Input'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -86,7 +86,7 @@ const MarkdownExportSettings: FC = () => {
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
<Button onClick={handleSelectFolder} icon={<FolderOpenOutlined />}>
|
||||
<Button onPress={handleSelectFolder} startContent={<FolderOpenOutlined />}>
|
||||
{t('settings.data.markdown_export.select')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { Client } from '@notionhq/client'
|
||||
import { AppLogo } from '@renderer/config/env'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { Button, Space, Tooltip } from 'antd'
|
||||
import { Space, Tooltip } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -122,7 +123,7 @@ const NotionSettings: FC = () => {
|
||||
placeholder={t('settings.data.notion.api_key_placeholder')}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<Button onClick={handleNotionConnectionCheck}>{t('settings.data.notion.check.button')}</Button>
|
||||
<Button onPress={handleNotionConnectionCheck}>{t('settings.data.notion.check.button')}</Button>
|
||||
</Space.Compact>
|
||||
</RowFlex>
|
||||
</SettingRow>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CheckOutlined, FolderOutlined, LoadingOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import NutstorePathPopup from '@renderer/components/Popups/NutsorePathPopup'
|
||||
import Selector from '@renderer/components/Selector'
|
||||
@@ -20,7 +21,7 @@ import {
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import { modalConfirm } from '@renderer/utils'
|
||||
import { NUTSTORE_HOST } from '@shared/config/nutstore'
|
||||
import { Button, Input, Tooltip, Typography } from 'antd'
|
||||
import { Input, Tooltip, Typography } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
@@ -211,10 +212,10 @@ const NutstoreSettings: FC = () => {
|
||||
{isLogin ? (
|
||||
<RowFlex className="items-center justify-between gap-[5px]">
|
||||
<Button
|
||||
type={nsConnected ? 'primary' : 'default'}
|
||||
ghost={nsConnected}
|
||||
onClick={handleCheckConnection}
|
||||
loading={checkConnectionLoading}>
|
||||
variant={nsConnected ? 'ghost' : 'solid'}
|
||||
color={nsConnected ? 'primary' : 'default'}
|
||||
onPress={handleCheckConnection}
|
||||
isLoading={checkConnectionLoading}>
|
||||
{checkConnectionLoading ? (
|
||||
<LoadingOutlined spin />
|
||||
) : nsConnected ? (
|
||||
@@ -223,12 +224,12 @@ const NutstoreSettings: FC = () => {
|
||||
t('settings.data.nutstore.checkConnection.name')
|
||||
)}
|
||||
</Button>
|
||||
<Button type="primary" danger onClick={handleLayout}>
|
||||
<Button variant="solid" color="danger" onPress={handleLayout}>
|
||||
{t('settings.data.nutstore.logout.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
) : (
|
||||
<Button onClick={handleClickNutstoreSSO}>{t('settings.data.nutstore.login.button')}</Button>
|
||||
<Button onPress={handleClickNutstoreSSO}>{t('settings.data.nutstore.login.button')}</Button>
|
||||
)}
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
@@ -251,19 +252,17 @@ const NutstoreSettings: FC = () => {
|
||||
setNutstorePath(e.target.value)
|
||||
}}
|
||||
/>
|
||||
<Button type="default" onClick={handleClickPathChange}>
|
||||
<FolderOutlined />
|
||||
</Button>
|
||||
<Button variant="solid" onPress={handleClickPathChange} startContent={<FolderOutlined />} isIconOnly />
|
||||
</RowFlex>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
|
||||
<RowFlex className="justify-between gap-[5px]">
|
||||
<Button onClick={showBackupModal} loading={backuping}>
|
||||
<Button onPress={showBackupModal} isLoading={backuping}>
|
||||
{t('settings.data.nutstore.backup.button')}
|
||||
</Button>
|
||||
<Button onClick={showBackupManager} disabled={!nutstoreToken}>
|
||||
<Button onPress={showBackupManager} isDisabled={!nutstoreToken}>
|
||||
{t('settings.data.nutstore.restore.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { FolderOpenOutlined, InfoCircleOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { S3BackupManager } from '@renderer/components/S3BackupManager'
|
||||
import { S3BackupModal, useS3BackupModal } from '@renderer/components/S3Modals'
|
||||
@@ -10,7 +11,7 @@ import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { startAutoSync, stopAutoSync } from '@renderer/services/BackupService'
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import { Button, Input, Tooltip } from 'antd'
|
||||
import { Input, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
@@ -182,16 +183,16 @@ const S3Settings: FC = () => {
|
||||
<SettingRowTitle>{t('settings.data.s3.backup.operation')}</SettingRowTitle>
|
||||
<RowFlex className="justify-between gap-[5px]">
|
||||
<Button
|
||||
onClick={showBackupModal}
|
||||
icon={<SaveOutlined />}
|
||||
loading={backuping}
|
||||
disabled={!s3Endpoint || !s3Region || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey}>
|
||||
onPress={showBackupModal}
|
||||
startContent={<SaveOutlined />}
|
||||
isLoading={backuping}
|
||||
isDisabled={!s3Endpoint || !s3Region || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey}>
|
||||
{t('settings.data.s3.backup.button')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={showBackupManager}
|
||||
icon={<FolderOpenOutlined />}
|
||||
disabled={!s3Endpoint || !s3Region || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey}>
|
||||
onPress={showBackupManager}
|
||||
startContent={<FolderOpenOutlined />}
|
||||
isDisabled={!s3Endpoint || !s3Region || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey}>
|
||||
{t('settings.data.s3.backup.manager.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { AppLogo } from '@renderer/config/env'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { Button, Space, Tooltip } from 'antd'
|
||||
import { Space, Tooltip } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -117,7 +118,7 @@ const SiyuanSettings: FC = () => {
|
||||
placeholder={t('settings.data.siyuan.token_placeholder')}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<Button onClick={handleCheckConnection}>{t('settings.data.siyuan.check.button')}</Button>
|
||||
<Button onPress={handleCheckConnection}>{t('settings.data.siyuan.check.button')}</Button>
|
||||
</Space.Compact>
|
||||
</RowFlex>
|
||||
</SettingRow>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { FolderOpenOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import Selector from '@renderer/components/Selector'
|
||||
import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager'
|
||||
@@ -8,7 +9,7 @@ import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/We
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { startAutoSync, stopAutoSync } from '@renderer/services/BackupService'
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import { Button, Input, Tooltip } from 'antd'
|
||||
import { Input, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
@@ -147,10 +148,10 @@ const WebDavSettings: FC = () => {
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
|
||||
<RowFlex className="justify-between gap-[5px]">
|
||||
<Button onClick={showBackupModal} icon={<SaveOutlined />} loading={backuping}>
|
||||
<Button onPress={showBackupModal} startContent={<SaveOutlined />} isLoading={backuping}>
|
||||
{t('settings.data.webdav.backup.button')}
|
||||
</Button>
|
||||
<Button onClick={showBackupManager} icon={<FolderOpenOutlined />} disabled={!webdavHost}>
|
||||
<Button onPress={showBackupManager} startContent={<FolderOpenOutlined />} isDisabled={!webdavHost}>
|
||||
{t('settings.data.webdav.restore.button')}
|
||||
</Button>
|
||||
</RowFlex>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user