mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-11 08:19:01 +08:00
feat: add EmojiAvatar component and update component exports
- Introduced a new EmojiAvatar component for enhanced avatar functionality. - Updated index.ts to export the new EmojiAvatar alongside existing components. - Removed the old display/EmojiAvatar component to streamline the codebase. - Adjusted various components to utilize the new Avatar structure and styling.
This commit is contained in:
parent
ef4bede062
commit
99962b740c
43
packages/ui/src/components/base/Avatar/EmojiAvatar.tsx
Normal file
43
packages/ui/src/components/base/Avatar/EmojiAvatar.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { cn } from '@heroui/react'
|
||||||
|
import React, { memo } from 'react'
|
||||||
|
|
||||||
|
interface EmojiAvatarProps {
|
||||||
|
children: string
|
||||||
|
size?: number
|
||||||
|
fontSize?: number
|
||||||
|
onClick?: React.MouseEventHandler<HTMLDivElement>
|
||||||
|
className?: string
|
||||||
|
style?: React.CSSProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
const EmojiAvatar = ({
|
||||||
|
children,
|
||||||
|
size = 31,
|
||||||
|
fontSize,
|
||||||
|
onClick,
|
||||||
|
className,
|
||||||
|
style
|
||||||
|
}: EmojiAvatarProps) => (
|
||||||
|
<div
|
||||||
|
onClick={onClick}
|
||||||
|
className={cn(
|
||||||
|
'flex items-center justify-center',
|
||||||
|
'bg-background-soft border-border',
|
||||||
|
'rounded-[20%] cursor-pointer',
|
||||||
|
'transition-opacity hover:opacity-80',
|
||||||
|
'border-[0.5px]',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
fontSize: fontSize ?? size * 0.5,
|
||||||
|
...style
|
||||||
|
}}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
EmojiAvatar.displayName = 'EmojiAvatar'
|
||||||
|
|
||||||
|
export default memo(EmojiAvatar)
|
||||||
26
packages/ui/src/components/base/Avatar/index.tsx
Normal file
26
packages/ui/src/components/base/Avatar/index.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { AvatarProps as HeroUIAvatarProps } from '@heroui/react'
|
||||||
|
import { Avatar as HeroUIAvatar, AvatarGroup as HeroUIAvatarGroup, cn } from '@heroui/react'
|
||||||
|
|
||||||
|
import EmojiAvatar from './EmojiAvatar'
|
||||||
|
|
||||||
|
export interface AvatarProps extends Omit<HeroUIAvatarProps, 'size'> {
|
||||||
|
size?: 'xs' | 'sm' | 'md' | 'lg'
|
||||||
|
}
|
||||||
|
|
||||||
|
const Avatar = (props: AvatarProps) => {
|
||||||
|
const { size, className = '', ...rest } = props
|
||||||
|
const isExtraSmall = size === 'xs'
|
||||||
|
|
||||||
|
const resolvedSize = isExtraSmall ? undefined : size
|
||||||
|
const mergedClassName = cn(isExtraSmall && 'w-6 h-6 text-tiny', 'shadow-lg', className)
|
||||||
|
|
||||||
|
return <HeroUIAvatar size={resolvedSize} className={mergedClassName} {...rest} />
|
||||||
|
}
|
||||||
|
|
||||||
|
Avatar.displayName = 'Avatar'
|
||||||
|
|
||||||
|
const AvatarGroup = HeroUIAvatarGroup
|
||||||
|
|
||||||
|
AvatarGroup.displayName = 'AvatarGroup'
|
||||||
|
|
||||||
|
export { Avatar, AvatarGroup, EmojiAvatar }
|
||||||
@ -1,35 +0,0 @@
|
|||||||
// Original path: src/renderer/src/components/Avatar/EmojiAvatar.tsx
|
|
||||||
import { memo } from 'react'
|
|
||||||
|
|
||||||
interface EmojiAvatarProps {
|
|
||||||
children: string
|
|
||||||
size?: number
|
|
||||||
fontSize?: number
|
|
||||||
onClick?: React.MouseEventHandler<HTMLDivElement>
|
|
||||||
className?: string
|
|
||||||
style?: React.CSSProperties
|
|
||||||
ref?: React.RefObject<HTMLDivElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
const EmojiAvatar = ({ children, size = 31, fontSize, onClick, className = '', style, ref }: EmojiAvatarProps) => {
|
|
||||||
const computedFontSize = fontSize ?? size * 0.5
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
onClick={onClick}
|
|
||||||
className={`flex items-center justify-center rounded-[20%] border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 cursor-pointer transition-opacity hover:opacity-80 ${className}`}
|
|
||||||
style={{
|
|
||||||
width: `${size}px`,
|
|
||||||
height: `${size}px`,
|
|
||||||
fontSize: `${computedFontSize}px`,
|
|
||||||
...style
|
|
||||||
}}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
EmojiAvatar.displayName = 'EmojiAvatar'
|
|
||||||
|
|
||||||
export default memo(EmojiAvatar)
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
// Original path: src/renderer/src/components/ProviderAvatar.tsx
|
// Original path: src/renderer/src/components/ProviderAvatar.tsx
|
||||||
import { Avatar } from '@heroui/react'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
import { Avatar } from '../../base/Avatar'
|
||||||
import { generateColorFromChar, getFirstCharacter, getForegroundColor } from './utils'
|
import { generateColorFromChar, getFirstCharacter, getForegroundColor } from './utils'
|
||||||
|
|
||||||
interface ProviderAvatarProps {
|
interface ProviderAvatarProps {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
// Base Components
|
// Base Components
|
||||||
|
export { Avatar, AvatarGroup, type AvatarProps,EmojiAvatar } from './base/Avatar'
|
||||||
export { default as Button, type ButtonProps } from './base/Button'
|
export { default as Button, type ButtonProps } from './base/Button'
|
||||||
export { default as CopyButton } from './base/CopyButton'
|
export { default as CopyButton } from './base/CopyButton'
|
||||||
export { default as CustomCollapse } from './base/CustomCollapse'
|
export { default as CustomCollapse } from './base/CustomCollapse'
|
||||||
@ -17,7 +18,6 @@ export { getToastUtilities, type ToastUtilities } from './base/Toast'
|
|||||||
|
|
||||||
// Display Components
|
// Display Components
|
||||||
export { default as Ellipsis } from './display/Ellipsis'
|
export { default as Ellipsis } from './display/Ellipsis'
|
||||||
export { default as EmojiAvatar } from './display/EmojiAvatar'
|
|
||||||
export { default as ExpandableText } from './display/ExpandableText'
|
export { default as ExpandableText } from './display/ExpandableText'
|
||||||
export { default as ListItem } from './display/ListItem'
|
export { default as ListItem } from './display/ListItem'
|
||||||
export { default as MaxContextCount } from './display/MaxContextCount'
|
export { default as MaxContextCount } from './display/MaxContextCount'
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react'
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
import EmojiAvatar from '../../../src/components/display/EmojiAvatar'
|
import EmojiAvatar from '../../../src/components/base/Avatar/EmojiAvatar'
|
||||||
|
|
||||||
const meta: Meta<typeof EmojiAvatar> = {
|
const meta: Meta<typeof EmojiAvatar> = {
|
||||||
title: 'Display/EmojiAvatar',
|
title: 'Display/EmojiAvatar',
|
||||||
@ -1,53 +0,0 @@
|
|||||||
import React, { memo } from 'react'
|
|
||||||
import styled from 'styled-components'
|
|
||||||
|
|
||||||
interface EmojiAvatarProps {
|
|
||||||
children: string
|
|
||||||
size?: number
|
|
||||||
fontSize?: number
|
|
||||||
onClick?: React.MouseEventHandler<HTMLDivElement>
|
|
||||||
className?: string
|
|
||||||
style?: React.CSSProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
const EmojiAvatar = ({
|
|
||||||
ref,
|
|
||||||
children,
|
|
||||||
size = 31,
|
|
||||||
fontSize,
|
|
||||||
onClick,
|
|
||||||
className,
|
|
||||||
style
|
|
||||||
}: EmojiAvatarProps & { ref?: React.RefObject<HTMLDivElement | null> }) => (
|
|
||||||
<StyledEmojiAvatar
|
|
||||||
ref={ref}
|
|
||||||
$size={size}
|
|
||||||
$fontSize={fontSize ?? size * 0.5}
|
|
||||||
onClick={onClick}
|
|
||||||
className={className}
|
|
||||||
style={style}>
|
|
||||||
{children}
|
|
||||||
</StyledEmojiAvatar>
|
|
||||||
)
|
|
||||||
|
|
||||||
EmojiAvatar.displayName = 'EmojiAvatar'
|
|
||||||
|
|
||||||
const StyledEmojiAvatar = styled.div<{ $size: number; $fontSize: number }>`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: var(--color-background-soft);
|
|
||||||
border: 0.5px solid var(--color-border);
|
|
||||||
border-radius: 20%;
|
|
||||||
cursor: pointer;
|
|
||||||
width: ${(props) => props.$size}px;
|
|
||||||
height: ${(props) => props.$size}px;
|
|
||||||
font-size: ${(props) => props.$fontSize}px;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export default memo(EmojiAvatar)
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
|
import type { AvatarProps } from '@cherrystudio/ui'
|
||||||
|
import { Avatar, cn } from '@cherrystudio/ui'
|
||||||
import { getModelLogo } from '@renderer/config/models'
|
import { getModelLogo } from '@renderer/config/models'
|
||||||
import type { Model } from '@renderer/types'
|
import type { Model } from '@renderer/types'
|
||||||
import type { AvatarProps } from 'antd'
|
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import { first } from 'lodash'
|
import { first } from 'lodash'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
|
|
||||||
@ -12,21 +12,10 @@ interface Props {
|
|||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModelAvatar: FC<Props> = ({ model, size, props, className }) => {
|
const ModelAvatar: FC<Props> = ({ model, size, className, ...props }) => {
|
||||||
|
const classNames = cn('flex items-center justify-center', `h-[${size}px] w-[${size}px]`, `${className || ''}`)
|
||||||
return (
|
return (
|
||||||
<Avatar
|
<Avatar src={getModelLogo(model?.id || '')} {...props} className={classNames}>
|
||||||
src={getModelLogo(model?.id || '')}
|
|
||||||
style={{
|
|
||||||
width: size,
|
|
||||||
height: size,
|
|
||||||
minWidth: size,
|
|
||||||
minHeight: size,
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}}
|
|
||||||
{...props}
|
|
||||||
className={className}>
|
|
||||||
{first(model?.name)}
|
{first(model?.name)}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
ReloadOutlined
|
ReloadOutlined
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import WindowControls from '@renderer/components/WindowControls'
|
import WindowControls from '@renderer/components/WindowControls'
|
||||||
@ -25,7 +26,7 @@ import { useTimer } from '@renderer/hooks/useTimer'
|
|||||||
import type { MinAppType } from '@renderer/types'
|
import type { MinAppType } from '@renderer/types'
|
||||||
import { delay } from '@renderer/utils'
|
import { delay } from '@renderer/utils'
|
||||||
import { clearWebviewState, getWebviewLoaded, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
import { clearWebviewState, getWebviewLoaded, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
||||||
import { Alert, Avatar, Drawer, Tooltip } from 'antd'
|
import { Alert, Drawer, Tooltip } from 'antd'
|
||||||
import type { WebviewTag } from 'electron'
|
import type { WebviewTag } from 'electron'
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -550,7 +551,7 @@ const MinappPopupContainer: React.FC = () => {
|
|||||||
<EmptyView>
|
<EmptyView>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={currentAppInfo?.logo}
|
src={currentAppInfo?.logo}
|
||||||
size={80}
|
className="h-20 w-20"
|
||||||
style={{ border: '1px solid var(--color-border)', marginTop: -150 }}
|
style={{ border: '1px solid var(--color-border)', marginTop: -150 }}
|
||||||
/>
|
/>
|
||||||
<BeatLoader color="var(--color-text-2)" size={10} style={{ marginTop: 15 }} />
|
<BeatLoader color="var(--color-text-2)" size={10} style={{ marginTop: 15 }} />
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||||
import { getModelUniqId } from '@renderer/services/ModelService'
|
import { getModelUniqId } from '@renderer/services/ModelService'
|
||||||
import type { Model, Provider } from '@renderer/types'
|
import type { Model, Provider } from '@renderer/types'
|
||||||
import { matchKeywordsInString } from '@renderer/utils'
|
import { matchKeywordsInString } from '@renderer/utils'
|
||||||
import { getFancyProviderName } from '@renderer/utils/naming'
|
import { getFancyProviderName } from '@renderer/utils/naming'
|
||||||
import type { SelectProps } from 'antd'
|
import type { SelectProps } from 'antd'
|
||||||
import { Avatar, Select } from 'antd'
|
import { Select } from 'antd'
|
||||||
import { sortBy } from 'lodash'
|
import { sortBy } from 'lodash'
|
||||||
import type { BaseSelectRef } from 'rc-select'
|
import type { BaseSelectRef } from 'rc-select'
|
||||||
import { memo, useCallback, useMemo } from 'react'
|
import { memo, useCallback, useMemo } from 'react'
|
||||||
@ -107,7 +108,7 @@ const ModelSelector = ({
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||||
{showAvatar && <Avatar size={18} />}
|
{showAvatar && <Avatar className="h-[18px] w-[18px]" />}
|
||||||
<span>{t('knowledge.error.model_invalid')}</span>
|
<span>{t('knowledge.error.model_invalid')}</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { PushpinOutlined } from '@ant-design/icons'
|
import { PushpinOutlined } from '@ant-design/icons'
|
||||||
import { Flex } from '@cherrystudio/ui'
|
import { Flex } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { FreeTrialModelTag } from '@renderer/components/FreeTrialModelTag'
|
import { FreeTrialModelTag } from '@renderer/components/FreeTrialModelTag'
|
||||||
import ModelTagsWithLabel from '@renderer/components/ModelTagsWithLabel'
|
import ModelTagsWithLabel from '@renderer/components/ModelTagsWithLabel'
|
||||||
import { TopView } from '@renderer/components/TopView'
|
import { TopView } from '@renderer/components/TopView'
|
||||||
@ -12,7 +13,7 @@ import type { Model, ModelType, Provider } from '@renderer/types'
|
|||||||
import { objectEntries } from '@renderer/types'
|
import { objectEntries } from '@renderer/types'
|
||||||
import { classNames, filterModelsByKeywords, getFancyProviderName } from '@renderer/utils'
|
import { classNames, filterModelsByKeywords, getFancyProviderName } from '@renderer/utils'
|
||||||
import { getModelTags } from '@renderer/utils/model'
|
import { getModelTags } from '@renderer/utils/model'
|
||||||
import { Avatar, Divider, Empty, Modal, Tooltip } from 'antd'
|
import { Divider, Empty, Modal, Tooltip } from 'antd'
|
||||||
import { first, sortBy } from 'lodash'
|
import { first, sortBy } from 'lodash'
|
||||||
import { Settings2 } from 'lucide-react'
|
import { Settings2 } from 'lucide-react'
|
||||||
import React, {
|
import React, {
|
||||||
@ -124,7 +125,7 @@ const PopupContainer: React.FC<Props> = ({ model, filter: baseFilter, showTagFil
|
|||||||
</TagsContainer>
|
</TagsContainer>
|
||||||
),
|
),
|
||||||
icon: (
|
icon: (
|
||||||
<Avatar src={getModelLogo(model.id || '')} size={24}>
|
<Avatar src={getModelLogo(model.id || '')} size="xs">
|
||||||
{first(model.name) || 'M'}
|
{first(model.name) || 'M'}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { Center, ColFlex, RowFlex } from '@cherrystudio/ui'
|
import { Center, ColFlex, RowFlex } from '@cherrystudio/ui'
|
||||||
|
import { Avatar, EmojiAvatar } from '@cherrystudio/ui'
|
||||||
import { cacheService } from '@data/CacheService'
|
import { cacheService } from '@data/CacheService'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import DefaultAvatar from '@renderer/assets/images/avatar.png'
|
import DefaultAvatar from '@renderer/assets/images/avatar.png'
|
||||||
import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar'
|
|
||||||
import useAvatar from '@renderer/hooks/useAvatar'
|
import useAvatar from '@renderer/hooks/useAvatar'
|
||||||
import ImageStorage from '@renderer/services/ImageStorage'
|
import ImageStorage from '@renderer/services/ImageStorage'
|
||||||
import { compressImage, isEmoji } from '@renderer/utils'
|
import { compressImage, isEmoji } from '@renderer/utils'
|
||||||
import { Avatar, Dropdown, Input, Modal, Popover, Upload } from 'antd'
|
import { Dropdown, Input, Modal, Popover, Upload } from 'antd'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { PoeLogo } from '@renderer/components/Icons'
|
import { PoeLogo } from '@renderer/components/Icons'
|
||||||
import { getProviderLogo } from '@renderer/config/providers'
|
import { getProviderLogo } from '@renderer/config/providers'
|
||||||
import type { Provider } from '@renderer/types'
|
import type { Provider } from '@renderer/types'
|
||||||
import { generateColorFromChar, getFirstCharacter, getForegroundColor } from '@renderer/utils'
|
import { generateColorFromChar, getFirstCharacter, getForegroundColor } from '@renderer/utils'
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
@ -63,7 +63,13 @@ export const ProviderAvatarPrimitive: React.FC<ProviderAvatarPrimitiveProps> = (
|
|||||||
|
|
||||||
if (logoSrc) {
|
if (logoSrc) {
|
||||||
return (
|
return (
|
||||||
<ProviderLogo draggable="false" shape="circle" src={logoSrc} className={className} style={style} size={size} />
|
<ProviderLogo
|
||||||
|
draggable="false"
|
||||||
|
radius="full"
|
||||||
|
src={logoSrc}
|
||||||
|
className={className}
|
||||||
|
style={{ width: size, height: size, ...style }}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,10 +78,11 @@ export const ProviderAvatarPrimitive: React.FC<ProviderAvatarPrimitiveProps> = (
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ProviderLogo
|
<ProviderLogo
|
||||||
size={size}
|
radius="full"
|
||||||
shape="circle"
|
|
||||||
className={className}
|
className={className}
|
||||||
style={{
|
style={{
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
color,
|
color,
|
||||||
...style
|
...style
|
||||||
|
|||||||
@ -53,7 +53,7 @@ const ProviderLogoPicker: FC<Props> = ({ onProviderClick }) => {
|
|||||||
{filteredProviders.map(({ id, name, logo }) => (
|
{filteredProviders.map(({ id, name, logo }) => (
|
||||||
<Tooltip key={id} title={name} placement="top" mouseLeaveDelay={0}>
|
<Tooltip key={id} title={name} placement="top" mouseLeaveDelay={0}>
|
||||||
<LogoItem onClick={(e) => handleProviderClick(e, id)}>
|
<LogoItem onClick={(e) => handleProviderClick(e, id)}>
|
||||||
<ProviderAvatarPrimitive providerId={id} size={52} providerName={name} logoSrc={logo} />
|
<ProviderAvatarPrimitive providerId={id} style={{ width: '52px', height: '52px' }} providerName={name} logoSrc={logo} />
|
||||||
</LogoItem>
|
</LogoItem>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
import { Avatar, EmojiAvatar } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar'
|
|
||||||
import { isMac } from '@renderer/config/constant'
|
import { isMac } from '@renderer/config/constant'
|
||||||
import { UserAvatar } from '@renderer/config/env'
|
import { UserAvatar } from '@renderer/config/env'
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
@ -13,7 +13,7 @@ import { useSettings } from '@renderer/hooks/useSettings'
|
|||||||
import { getSidebarIconLabel, getThemeModeLabel } from '@renderer/i18n/label'
|
import { getSidebarIconLabel, getThemeModeLabel } from '@renderer/i18n/label'
|
||||||
import { isEmoji } from '@renderer/utils'
|
import { isEmoji } from '@renderer/utils'
|
||||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||||
import { Avatar, Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import {
|
import {
|
||||||
Code,
|
Code,
|
||||||
FileSearch,
|
FileSearch,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import PaddleocrLogo from '@renderer/assets/images/providers/paddleocr.png'
|
import PaddleocrLogo from '@renderer/assets/images/providers/paddleocr.png'
|
||||||
import TesseractLogo from '@renderer/assets/images/providers/Tesseract.js.png'
|
import TesseractLogo from '@renderer/assets/images/providers/Tesseract.js.png'
|
||||||
@ -7,7 +8,6 @@ import { useAppSelector } from '@renderer/store'
|
|||||||
import { addOcrProvider, removeOcrProvider, setImageOcrProviderId, updateOcrProviderConfig } from '@renderer/store/ocr'
|
import { addOcrProvider, removeOcrProvider, setImageOcrProviderId, updateOcrProviderConfig } from '@renderer/store/ocr'
|
||||||
import type { ImageOcrProvider, OcrProvider, OcrProviderConfig } from '@renderer/types'
|
import type { ImageOcrProvider, OcrProvider, OcrProviderConfig } from '@renderer/types'
|
||||||
import { isBuiltinOcrProvider, isBuiltinOcrProviderId, isImageOcrProvider } from '@renderer/types'
|
import { isBuiltinOcrProvider, isBuiltinOcrProviderId, isImageOcrProvider } from '@renderer/types'
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import { FileQuestionMarkIcon, MonitorIcon } from 'lucide-react'
|
import { FileQuestionMarkIcon, MonitorIcon } from 'lucide-react'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -72,11 +72,11 @@ export const useOcrProviders = () => {
|
|||||||
if (isBuiltinOcrProvider(p)) {
|
if (isBuiltinOcrProvider(p)) {
|
||||||
switch (p.id) {
|
switch (p.id) {
|
||||||
case 'tesseract':
|
case 'tesseract':
|
||||||
return <Avatar size={size} src={TesseractLogo} />
|
return <Avatar className={`h-[${size}px] w-[${size}px]`} src={TesseractLogo} />
|
||||||
case 'system':
|
case 'system':
|
||||||
return <MonitorIcon size={size} />
|
return <MonitorIcon size={size} />
|
||||||
case 'paddleocr':
|
case 'paddleocr':
|
||||||
return <Avatar size={size} src={PaddleocrLogo} />
|
return <Avatar className={`h-[${size}px] w-[${size}px]`} src={PaddleocrLogo} />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return <FileQuestionMarkIcon size={size} />
|
return <FileQuestionMarkIcon size={size} />
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import AiProvider from '@renderer/aiCore'
|
import AiProvider from '@renderer/aiCore'
|
||||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||||
import ModelSelector from '@renderer/components/ModelSelector'
|
import ModelSelector from '@renderer/components/ModelSelector'
|
||||||
@ -17,7 +18,7 @@ import { setIsBunInstalled } from '@renderer/store/mcp'
|
|||||||
import type { EndpointType, Model } from '@renderer/types'
|
import type { EndpointType, Model } from '@renderer/types'
|
||||||
import type { TerminalConfig } from '@shared/config/constant'
|
import type { TerminalConfig } from '@shared/config/constant'
|
||||||
import { codeTools, terminalApps } from '@shared/config/constant'
|
import { codeTools, terminalApps } from '@shared/config/constant'
|
||||||
import { Alert, Avatar, Checkbox, Input, Popover, Select, Space, Tooltip } from 'antd'
|
import { Alert, Checkbox, Input, Popover, Select, Space, Tooltip } from 'antd'
|
||||||
import { ArrowUpRight, Download, FolderOpen, HelpCircle, Terminal, X } from 'lucide-react'
|
import { ArrowUpRight, Download, FolderOpen, HelpCircle, Terminal, X } from 'lucide-react'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
@ -363,7 +364,7 @@ const CodeToolsPage: FC = () => {
|
|||||||
key={provider.id}
|
key={provider.id}
|
||||||
style={{ color: 'var(--color-text)', display: 'flex', alignItems: 'center', gap: 4 }}
|
style={{ color: 'var(--color-text)', display: 'flex', alignItems: 'center', gap: 4 }}
|
||||||
to={`/settings/provider?id=${provider.id}`}>
|
to={`/settings/provider?id=${provider.id}`}>
|
||||||
<ProviderLogo shape="square" src={getProviderLogo(provider.id)} size={20} />
|
<Avatar radius="md" src={getProviderLogo(provider.id)} className="h-5 w-5 rounded-md" />
|
||||||
{getProviderLabel(provider.id)}
|
{getProviderLabel(provider.id)}
|
||||||
<ArrowUpRight size={14} />
|
<ArrowUpRight size={14} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||||
import ModelTagsWithLabel from '@renderer/components/ModelTagsWithLabel'
|
import ModelTagsWithLabel from '@renderer/components/ModelTagsWithLabel'
|
||||||
import { type QuickPanelListItem, QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
import { type QuickPanelListItem, QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||||
@ -7,7 +8,7 @@ import { useProviders } from '@renderer/hooks/useProvider'
|
|||||||
import { getModelUniqId } from '@renderer/services/ModelService'
|
import { getModelUniqId } from '@renderer/services/ModelService'
|
||||||
import type { FileType, Model } from '@renderer/types'
|
import type { FileType, Model } from '@renderer/types'
|
||||||
import { getFancyProviderName } from '@renderer/utils'
|
import { getFancyProviderName } from '@renderer/utils'
|
||||||
import { Avatar, Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import { useLiveQuery } from 'dexie-react-hooks'
|
import { useLiveQuery } from 'dexie-react-hooks'
|
||||||
import { first, sortBy } from 'lodash'
|
import { first, sortBy } from 'lodash'
|
||||||
import { AtSign, CircleX, Plus } from 'lucide-react'
|
import { AtSign, CircleX, Plus } from 'lucide-react'
|
||||||
@ -135,7 +136,7 @@ const MentionModelsButton: FC<Props> = ({
|
|||||||
),
|
),
|
||||||
description: <ModelTagsWithLabel model={m} showLabel={false} size={10} style={{ opacity: 0.8 }} />,
|
description: <ModelTagsWithLabel model={m} showLabel={false} size={10} style={{ opacity: 0.8 }} />,
|
||||||
icon: (
|
icon: (
|
||||||
<Avatar src={getModelLogo(m.id)} size={20}>
|
<Avatar src={getModelLogo(m.id)} className="w-5 h-5">
|
||||||
{first(m.name)}
|
{first(m.name)}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
),
|
),
|
||||||
@ -171,7 +172,7 @@ const MentionModelsButton: FC<Props> = ({
|
|||||||
),
|
),
|
||||||
description: <ModelTagsWithLabel model={m} showLabel={false} size={10} style={{ opacity: 0.8 }} />,
|
description: <ModelTagsWithLabel model={m} showLabel={false} size={10} style={{ opacity: 0.8 }} />,
|
||||||
icon: (
|
icon: (
|
||||||
<Avatar src={getModelLogo(m.id)} size={20}>
|
<Avatar src={getModelLogo(m.id)} className="w-5 h-5">
|
||||||
{first(m.name)}
|
{first(m.name)}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import '@xyflow/react/dist/style.css'
|
import '@xyflow/react/dist/style.css'
|
||||||
|
|
||||||
import { RobotOutlined, UserOutlined } from '@ant-design/icons'
|
import { RobotOutlined, UserOutlined } from '@ant-design/icons'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
|
import { EmojiAvatar } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar'
|
|
||||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||||
import { getModelLogo } from '@renderer/config/models'
|
import { getModelLogo } from '@renderer/config/models'
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
@ -17,7 +18,7 @@ import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
|||||||
import type { Edge, Node, NodeTypes } from '@xyflow/react'
|
import type { Edge, Node, NodeTypes } from '@xyflow/react'
|
||||||
import { Controls, Handle, MiniMap, ReactFlow, ReactFlowProvider } from '@xyflow/react'
|
import { Controls, Handle, MiniMap, ReactFlow, ReactFlowProvider } from '@xyflow/react'
|
||||||
import { Position, useEdgesState, useNodesState } from '@xyflow/react'
|
import { Position, useEdgesState, useNodesState } from '@xyflow/react'
|
||||||
import { Avatar, Spin, Tooltip } from 'antd'
|
import { Spin, Tooltip } from 'antd'
|
||||||
import { isEqual } from 'lodash'
|
import { isEqual } from 'lodash'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
@ -77,7 +78,7 @@ const CustomNode: FC<{ data: any }> = ({ data }) => {
|
|||||||
avatar = <Avatar src={data.userAvatar} alt={title} />
|
avatar = <Avatar src={data.userAvatar} alt={title} />
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
avatar = <Avatar icon={<UserOutlined />} style={{ backgroundColor: 'var(--color-info)' }} />
|
avatar = <Avatar icon={<UserOutlined />} className="bg-info" />
|
||||||
}
|
}
|
||||||
} else if (nodeType === 'assistant') {
|
} else if (nodeType === 'assistant') {
|
||||||
borderColor = 'var(--color-primary)'
|
borderColor = 'var(--color-primary)'
|
||||||
@ -94,11 +95,11 @@ const CustomNode: FC<{ data: any }> = ({ data }) => {
|
|||||||
<Avatar
|
<Avatar
|
||||||
src={modelLogo}
|
src={modelLogo}
|
||||||
icon={!modelLogo ? <RobotOutlined /> : undefined}
|
icon={!modelLogo ? <RobotOutlined /> : undefined}
|
||||||
style={{ backgroundColor: 'var(--color-primary)' }}
|
className="bg-primary"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
avatar = <Avatar icon={<RobotOutlined />} style={{ backgroundColor: 'var(--color-primary)' }} />
|
avatar = <Avatar icon={<RobotOutlined />} className="bg-primary" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
import { Avatar, EmojiAvatar } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar'
|
|
||||||
import { APP_NAME, AppLogo, isLocalAi } from '@renderer/config/env'
|
import { APP_NAME, AppLogo, isLocalAi } from '@renderer/config/env'
|
||||||
import { getModelLogo } from '@renderer/config/models'
|
import { getModelLogo } from '@renderer/config/models'
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
@ -13,7 +13,6 @@ import { newMessagesActions } from '@renderer/store/newMessage'
|
|||||||
import type { Message } from '@renderer/types/newMessage'
|
import type { Message } from '@renderer/types/newMessage'
|
||||||
import { isEmoji, removeLeadingEmoji } from '@renderer/utils'
|
import { isEmoji, removeLeadingEmoji } from '@renderer/utils'
|
||||||
import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import { CircleChevronDown } from 'lucide-react'
|
import { CircleChevronDown } from 'lucide-react'
|
||||||
import { type FC, useCallback, useEffect, useRef, useState } from 'react'
|
import { type FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -227,8 +226,9 @@ const MessageAnchorLine: FC<MessageLineProps> = ({ messages }) => {
|
|||||||
{message.role === 'assistant' ? (
|
{message.role === 'assistant' ? (
|
||||||
<MessageItemAvatar
|
<MessageItemAvatar
|
||||||
src={avatarSource}
|
src={avatarSource}
|
||||||
size={size}
|
|
||||||
style={{
|
style={{
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
border: isLocalAi ? '1px solid var(--color-border-soft)' : 'none',
|
border: isLocalAi ? '1px solid var(--color-border-soft)' : 'none',
|
||||||
filter: theme === 'dark' ? 'invert(0.05)' : undefined
|
filter: theme === 'dark' ? 'invert(0.05)' : undefined
|
||||||
}}
|
}}
|
||||||
@ -246,7 +246,7 @@ const MessageAnchorLine: FC<MessageLineProps> = ({ messages }) => {
|
|||||||
{avatar}
|
{avatar}
|
||||||
</EmojiAvatar>
|
</EmojiAvatar>
|
||||||
) : (
|
) : (
|
||||||
<MessageItemAvatar src={avatar} size={size} />
|
<MessageItemAvatar src={avatar} style={{ width: size, height: size }} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
import { ArrowsAltOutlined, ShrinkOutlined } from '@ant-design/icons'
|
import { ArrowsAltOutlined, ShrinkOutlined } from '@ant-design/icons'
|
||||||
import { RowFlex } from '@cherrystudio/ui'
|
import { Avatar, AvatarGroup, RowFlex } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||||
import Scrollbar from '@renderer/components/Scrollbar'
|
import Scrollbar from '@renderer/components/Scrollbar'
|
||||||
|
import { getModelLogo } from '@renderer/config/models'
|
||||||
import type { Model } from '@renderer/types'
|
import type { Model } from '@renderer/types'
|
||||||
import { AssistantMessageStatus, type Message } from '@renderer/types/newMessage'
|
import { AssistantMessageStatus, type Message } from '@renderer/types/newMessage'
|
||||||
import { lightbulbSoftVariants } from '@renderer/utils/motionVariants'
|
import { lightbulbSoftVariants } from '@renderer/utils/motionVariants'
|
||||||
import type { MultiModelFoldDisplayMode } from '@shared/data/preference/preferenceTypes'
|
import type { MultiModelFoldDisplayMode } from '@shared/data/preference/preferenceTypes'
|
||||||
import { Avatar, Segmented as AntdSegmented, Tooltip } from 'antd'
|
import { Segmented as AntdSegmented, Tooltip } from 'antd'
|
||||||
|
import { first } from 'lodash'
|
||||||
import { motion } from 'motion/react'
|
import { motion } from 'motion/react'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { memo, useCallback } from 'react'
|
import { memo, useCallback } from 'react'
|
||||||
@ -83,7 +85,26 @@ const MessageGroupModelList: FC<MessageGroupModelListProps> = ({ messages, selec
|
|||||||
<ModelsContainer $displayMode={foldDisplayMode}>
|
<ModelsContainer $displayMode={foldDisplayMode}>
|
||||||
{isCompact ? (
|
{isCompact ? (
|
||||||
/* Compact style display */
|
/* Compact style display */
|
||||||
<Avatar.Group className="avatar-group">{messages.map((message) => renderLabel(message))}</Avatar.Group>
|
<AvatarGroup className="p-2" isBordered>
|
||||||
|
{messages.map((message) => {
|
||||||
|
const modelTip = message.model?.name
|
||||||
|
const isSelected = message.id === selectMessageId
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip key={message.id} title={modelTip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||||
|
<Avatar
|
||||||
|
src={getModelLogo(message.model?.id || '')}
|
||||||
|
name={first(message.model?.name)}
|
||||||
|
size="xs"
|
||||||
|
isBordered={isSelected}
|
||||||
|
color={isSelected ? 'primary' : 'default'}
|
||||||
|
onClick={() => setSelectedMessage(message)}
|
||||||
|
className="shadow-lg"
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</AvatarGroup>
|
||||||
) : (
|
) : (
|
||||||
/* Expanded style display */
|
/* Expanded style display */
|
||||||
<Segmented
|
<Segmented
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { RowFlex } from '@cherrystudio/ui'
|
import { RowFlex } from '@cherrystudio/ui'
|
||||||
|
import { Avatar, EmojiAvatar } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar'
|
|
||||||
import UserPopup from '@renderer/components/Popups/UserPopup'
|
import UserPopup from '@renderer/components/Popups/UserPopup'
|
||||||
import { APP_NAME, AppLogo, isLocalAi } from '@renderer/config/env'
|
import { APP_NAME, AppLogo, isLocalAi } from '@renderer/config/env'
|
||||||
import { getModelLogo } from '@renderer/config/models'
|
import { getModelLogo } from '@renderer/config/models'
|
||||||
@ -15,7 +15,7 @@ import { getModelName } from '@renderer/services/ModelService'
|
|||||||
import type { Assistant, Model, Topic } from '@renderer/types'
|
import type { Assistant, Model, Topic } from '@renderer/types'
|
||||||
import type { Message } from '@renderer/types/newMessage'
|
import type { Message } from '@renderer/types/newMessage'
|
||||||
import { firstLetter, isEmoji, removeLeadingEmoji } from '@renderer/utils'
|
import { firstLetter, isEmoji, removeLeadingEmoji } from '@renderer/utils'
|
||||||
import { Avatar, Checkbox, Tooltip } from 'antd'
|
import { Checkbox, Tooltip } from 'antd'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { Sparkle } from 'lucide-react'
|
import { Sparkle } from 'lucide-react'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
@ -86,7 +86,7 @@ const MessageHeader: FC<Props> = memo(({ assistant, model, message, topic, isGro
|
|||||||
{isAssistantMessage ? (
|
{isAssistantMessage ? (
|
||||||
<Avatar
|
<Avatar
|
||||||
src={avatarSource}
|
src={avatarSource}
|
||||||
size={35}
|
className="h-[35px] w-[35px]"
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '25%',
|
borderRadius: '25%',
|
||||||
cursor: showMinappIcon ? 'pointer' : 'default',
|
cursor: showMinappIcon ? 'pointer' : 'default',
|
||||||
@ -105,7 +105,7 @@ const MessageHeader: FC<Props> = memo(({ assistant, model, message, topic, isGro
|
|||||||
) : (
|
) : (
|
||||||
<Avatar
|
<Avatar
|
||||||
src={avatar}
|
src={avatar}
|
||||||
size={35}
|
className="h-[35px] w-[35px]"
|
||||||
style={{ borderRadius: '25%', cursor: 'pointer' }}
|
style={{ borderRadius: '25%', cursor: 'pointer' }}
|
||||||
onClick={() => UserPopup.show()}
|
onClick={() => UserPopup.show()}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
|
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
|
||||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||||
@ -5,7 +6,6 @@ import { useMinapps } from '@renderer/hooks/useMinapps'
|
|||||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||||
import TabsService from '@renderer/services/TabsService'
|
import TabsService from '@renderer/services/TabsService'
|
||||||
import { getWebviewLoaded, onWebviewStateChange, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
import { getWebviewLoaded, onWebviewStateChange, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import type { WebviewTag } from 'electron'
|
import type { WebviewTag } from 'electron'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
@ -187,7 +187,7 @@ const MinAppPage: FC = () => {
|
|||||||
</ToolbarWrapper>
|
</ToolbarWrapper>
|
||||||
{!isReady && (
|
{!isReady && (
|
||||||
<LoadingMask>
|
<LoadingMask>
|
||||||
<Avatar src={app.logo} size={60} style={{ border: '1px solid var(--color-border)' }} />
|
<Avatar src={app.logo} className="h-[60px] w-[60px] border border-border" />
|
||||||
<BeatLoader color="var(--color-text-2)" size={8} style={{ marginTop: 12 }} />
|
<BeatLoader color="var(--color-text-2)" size={8} style={{ marginTop: 12 }} />
|
||||||
</LoadingMask>
|
</LoadingMask>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import WebviewContainer from '@renderer/components/MinApp/WebviewContainer'
|
import WebviewContainer from '@renderer/components/MinApp/WebviewContainer'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import type { MinAppType } from '@renderer/types'
|
import type { MinAppType } from '@renderer/types'
|
||||||
import { getWebviewLoaded, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
import { getWebviewLoaded, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import type { WebviewTag } from 'electron'
|
import type { WebviewTag } from 'electron'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
@ -110,7 +110,7 @@ const MinAppFullPageView: FC<Props> = ({ app }) => {
|
|||||||
{!isReady && (
|
{!isReady && (
|
||||||
<LoadingMask>
|
<LoadingMask>
|
||||||
<LoadingOverlay>
|
<LoadingOverlay>
|
||||||
<Avatar src={app.logo} size={60} style={{ border: '1px solid var(--color-border)' }} />
|
<Avatar src={app.logo} className="h-[60px] w-[60px] border border-border" />
|
||||||
<BeatLoader color="var(--color-text-2)" size={8} style={{ marginTop: 12 }} />
|
<BeatLoader color="var(--color-text-2)" size={8} style={{ marginTop: 12 }} />
|
||||||
</LoadingOverlay>
|
</LoadingOverlay>
|
||||||
</LoadingMask>
|
</LoadingMask>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
|
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
|
||||||
import { Button, RowFlex } from '@cherrystudio/ui'
|
import { Button, RowFlex } from '@cherrystudio/ui'
|
||||||
import { Switch } from '@cherrystudio/ui'
|
import { Switch } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { useCache } from '@data/hooks/useCache'
|
import { useCache } from '@data/hooks/useCache'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
@ -21,7 +22,7 @@ import { translateText } from '@renderer/services/TranslateService'
|
|||||||
import type { FileMetadata } from '@renderer/types'
|
import type { FileMetadata } from '@renderer/types'
|
||||||
import type { PaintingAction, PaintingsState } from '@renderer/types'
|
import type { PaintingAction, PaintingsState } from '@renderer/types'
|
||||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||||
import { Avatar, Input, InputNumber, Radio, Segmented, Select, Slider, Tooltip, Upload } from 'antd'
|
import { Input, InputNumber, Radio, Segmented, Select, Slider, Tooltip, Upload } from 'antd'
|
||||||
import TextArea from 'antd/es/input/TextArea'
|
import TextArea from 'antd/es/input/TextArea'
|
||||||
import { Info } from 'lucide-react'
|
import { Info } from 'lucide-react'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
@ -839,10 +840,10 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
<SettingTitle style={{ marginBottom: 5 }}>{t('common.provider')}</SettingTitle>
|
<SettingTitle style={{ marginBottom: 5 }}>{t('common.provider')}</SettingTitle>
|
||||||
<SettingHelpLink target="_blank" href={aihubmixProvider.apiHost}>
|
<SettingHelpLink target="_blank" href={aihubmixProvider.apiHost}>
|
||||||
{t('paintings.learn_more')}
|
{t('paintings.learn_more')}
|
||||||
<ProviderLogo
|
<Avatar
|
||||||
shape="square"
|
radius="md"
|
||||||
src={getProviderLogo(aihubmixProvider.id)}
|
src={getProviderLogo(aihubmixProvider.id)}
|
||||||
size={16}
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
style={{ marginLeft: 5 }}
|
style={{ marginLeft: 5 }}
|
||||||
/>
|
/>
|
||||||
</SettingHelpLink>
|
</SettingHelpLink>
|
||||||
@ -852,7 +853,11 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
{providerOptions.map((provider) => (
|
{providerOptions.map((provider) => (
|
||||||
<Select.Option value={provider.value} key={provider.value}>
|
<Select.Option value={provider.value} key={provider.value}>
|
||||||
<SelectOptionContainer>
|
<SelectOptionContainer>
|
||||||
<ProviderLogo shape="square" src={getProviderLogo(provider.value || '')} size={16} />
|
<Avatar
|
||||||
|
radius="md"
|
||||||
|
src={getProviderLogo(provider.value || '')}
|
||||||
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
|
/>
|
||||||
{provider.label}
|
{provider.label}
|
||||||
</SelectOptionContainer>
|
</SelectOptionContainer>
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
|
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
|
||||||
import { Button, RowFlex } from '@cherrystudio/ui'
|
import { Button, RowFlex } from '@cherrystudio/ui'
|
||||||
import { Switch } from '@cherrystudio/ui'
|
import { Switch } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { useCache } from '@data/hooks/useCache'
|
import { useCache } from '@data/hooks/useCache'
|
||||||
import DMXAPIToImg from '@renderer/assets/images/providers/DMXAPI-to-img.webp'
|
import DMXAPIToImg from '@renderer/assets/images/providers/DMXAPI-to-img.webp'
|
||||||
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
||||||
@ -14,7 +15,7 @@ import FileManager from '@renderer/services/FileManager'
|
|||||||
import type { FileMetadata } from '@renderer/types'
|
import type { FileMetadata } from '@renderer/types'
|
||||||
import { convertToBase64, uuid } from '@renderer/utils'
|
import { convertToBase64, uuid } from '@renderer/utils'
|
||||||
import type { DmxapiPainting } from '@types'
|
import type { DmxapiPainting } from '@types'
|
||||||
import { Avatar, Input, InputNumber, Segmented, Select, Tooltip } from 'antd'
|
import { Input, InputNumber, Segmented, Select, Tooltip } from 'antd'
|
||||||
import TextArea from 'antd/es/input/TextArea'
|
import TextArea from 'antd/es/input/TextArea'
|
||||||
import { Info } from 'lucide-react'
|
import { Info } from 'lucide-react'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
@ -804,10 +805,10 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
<SettingHelpLink target="_blank" href={TOP_UP_URL}>
|
<SettingHelpLink target="_blank" href={TOP_UP_URL}>
|
||||||
{t('paintings.top_up')}
|
{t('paintings.top_up')}
|
||||||
</SettingHelpLink>
|
</SettingHelpLink>
|
||||||
<ProviderLogo
|
<Avatar
|
||||||
shape="square"
|
radius="md"
|
||||||
src={getProviderLogo(dmxapiProvider.id)}
|
src={getProviderLogo(dmxapiProvider.id)}
|
||||||
size={16}
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
style={{ marginLeft: 5 }}
|
style={{ marginLeft: 5 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -816,7 +817,11 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
{providerOptions.map((provider) => (
|
{providerOptions.map((provider) => (
|
||||||
<Select.Option value={provider.value} key={provider.value}>
|
<Select.Option value={provider.value} key={provider.value}>
|
||||||
<SelectOptionContainer>
|
<SelectOptionContainer>
|
||||||
<ProviderLogo shape="square" src={getProviderLogo(provider.value || '')} size={16} />
|
<Avatar
|
||||||
|
radius="md"
|
||||||
|
src={getProviderLogo(provider.value || '')}
|
||||||
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
|
/>
|
||||||
{provider.label}
|
{provider.label}
|
||||||
</SelectOptionContainer>
|
</SelectOptionContainer>
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
@ -1028,9 +1033,6 @@ const ProviderTitleContainer = styled.div`
|
|||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
`
|
`
|
||||||
|
|
||||||
const ProviderLogo = styled(Avatar)`
|
|
||||||
border: 0.5px solid var(--color-border);
|
|
||||||
`
|
|
||||||
const SelectOptionContainer = styled.div`
|
const SelectOptionContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons'
|
import { PlusOutlined } from '@ant-design/icons'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { useCache } from '@data/hooks/useCache'
|
import { useCache } from '@data/hooks/useCache'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
@ -28,7 +29,7 @@ import { translateText } from '@renderer/services/TranslateService'
|
|||||||
import type { PaintingAction, PaintingsState } from '@renderer/types'
|
import type { PaintingAction, PaintingsState } from '@renderer/types'
|
||||||
import type { FileMetadata } from '@renderer/types'
|
import type { FileMetadata } from '@renderer/types'
|
||||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||||
import { Avatar, Empty, InputNumber, Segmented, Select, Upload } from 'antd'
|
import { Empty, InputNumber, Segmented, Select, Upload } from 'antd'
|
||||||
import TextArea from 'antd/es/input/TextArea'
|
import TextArea from 'antd/es/input/TextArea'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@ -502,10 +503,10 @@ const NewApiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
<SettingTitle style={{ marginBottom: 5 }}>{t('common.provider')}</SettingTitle>
|
<SettingTitle style={{ marginBottom: 5 }}>{t('common.provider')}</SettingTitle>
|
||||||
<SettingHelpLink target="_blank" href={'https://docs.newapi.pro/apps/cherry-studio/'}>
|
<SettingHelpLink target="_blank" href={'https://docs.newapi.pro/apps/cherry-studio/'}>
|
||||||
{t('paintings.learn_more')}
|
{t('paintings.learn_more')}
|
||||||
<ProviderLogo
|
<Avatar
|
||||||
shape="square"
|
radius="md"
|
||||||
src={getProviderLogo(newApiProvider.id)}
|
src={getProviderLogo(newApiProvider.id)}
|
||||||
size={16}
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
style={{ marginLeft: 5 }}
|
style={{ marginLeft: 5 }}
|
||||||
/>
|
/>
|
||||||
</SettingHelpLink>
|
</SettingHelpLink>
|
||||||
@ -518,7 +519,11 @@ const NewApiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
{providerOptions.map((provider) => (
|
{providerOptions.map((provider) => (
|
||||||
<Select.Option value={provider.value} key={provider.value}>
|
<Select.Option value={provider.value} key={provider.value}>
|
||||||
<SelectOptionContainer>
|
<SelectOptionContainer>
|
||||||
<ProviderLogo shape="square" src={getProviderLogo(provider.value || '')} size={16} />
|
<Avatar
|
||||||
|
radius="md"
|
||||||
|
src={getProviderLogo(provider.value || '')}
|
||||||
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
|
/>
|
||||||
{provider.label}
|
{provider.label}
|
||||||
</SelectOptionContainer>
|
</SelectOptionContainer>
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
@ -787,10 +792,6 @@ const ToolbarMenu = styled.div`
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
`
|
`
|
||||||
|
|
||||||
const ProviderLogo = styled(Avatar)`
|
|
||||||
border: 0.5px solid var(--color-border);
|
|
||||||
`
|
|
||||||
|
|
||||||
// 添加新的样式组件
|
// 添加新的样式组件
|
||||||
const ModeSegmentedContainer = styled.div`
|
const ModeSegmentedContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons'
|
import { PlusOutlined } from '@ant-design/icons'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { useCache } from '@data/hooks/useCache'
|
import { useCache } from '@data/hooks/useCache'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
@ -16,7 +17,7 @@ import FileManager from '@renderer/services/FileManager'
|
|||||||
import { translateText } from '@renderer/services/TranslateService'
|
import { translateText } from '@renderer/services/TranslateService'
|
||||||
import type { TokenFluxPainting } from '@renderer/types'
|
import type { TokenFluxPainting } from '@renderer/types'
|
||||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||||
import { Avatar, Select, Tooltip } from 'antd'
|
import { Select, Tooltip } from 'antd'
|
||||||
import TextArea from 'antd/es/input/TextArea'
|
import TextArea from 'antd/es/input/TextArea'
|
||||||
import { Info } from 'lucide-react'
|
import { Info } from 'lucide-react'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
@ -381,7 +382,11 @@ const TokenFluxPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
<SettingTitle style={{ marginBottom: 8 }}>{t('common.provider')}</SettingTitle>
|
<SettingTitle style={{ marginBottom: 8 }}>{t('common.provider')}</SettingTitle>
|
||||||
<SettingHelpLink target="_blank" href="https://tokenflux.ai">
|
<SettingHelpLink target="_blank" href="https://tokenflux.ai">
|
||||||
{t('paintings.learn_more')}
|
{t('paintings.learn_more')}
|
||||||
<ProviderLogo shape="square" src={getProviderLogo('tokenflux')} size={16} style={{ marginLeft: 5 }} />
|
<Avatar
|
||||||
|
radius="md"
|
||||||
|
src={getProviderLogo('tokenflux')}
|
||||||
|
className="ml-[5px] h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
|
/>
|
||||||
</SettingHelpLink>
|
</SettingHelpLink>
|
||||||
</ProviderTitleContainer>
|
</ProviderTitleContainer>
|
||||||
|
|
||||||
@ -392,7 +397,11 @@ const TokenFluxPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
{providerOptions.map((provider) => (
|
{providerOptions.map((provider) => (
|
||||||
<Select.Option value={provider.value} key={provider.value}>
|
<Select.Option value={provider.value} key={provider.value}>
|
||||||
<SelectOptionContainer>
|
<SelectOptionContainer>
|
||||||
<ProviderLogo shape="square" src={getProviderLogo(provider.value || '')} size={16} />
|
<Avatar
|
||||||
|
radius="md"
|
||||||
|
src={getProviderLogo(provider.value || '')}
|
||||||
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
|
/>
|
||||||
{provider.label}
|
{provider.label}
|
||||||
</SelectOptionContainer>
|
</SelectOptionContainer>
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
@ -763,10 +772,6 @@ const InfoIcon = styled(Info)`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const ProviderLogo = styled(Avatar)`
|
|
||||||
border: 0.5px solid var(--color-border);
|
|
||||||
`
|
|
||||||
|
|
||||||
const ProviderTitleContainer = styled.div`
|
const ProviderTitleContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons'
|
import { PlusOutlined } from '@ant-design/icons'
|
||||||
import { RowFlex } from '@cherrystudio/ui'
|
import { RowFlex } from '@cherrystudio/ui'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { useCache } from '@data/hooks/useCache'
|
import { useCache } from '@data/hooks/useCache'
|
||||||
import AiProvider from '@renderer/aiCore'
|
import AiProvider from '@renderer/aiCore'
|
||||||
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
||||||
@ -12,7 +13,7 @@ import { useAllProviders } from '@renderer/hooks/useProvider'
|
|||||||
import { getProviderLabel } from '@renderer/i18n/label'
|
import { getProviderLabel } from '@renderer/i18n/label'
|
||||||
import FileManager from '@renderer/services/FileManager'
|
import FileManager from '@renderer/services/FileManager'
|
||||||
import { getErrorMessage, uuid } from '@renderer/utils'
|
import { getErrorMessage, uuid } from '@renderer/utils'
|
||||||
import { Avatar, InputNumber, Radio, Select } from 'antd'
|
import { InputNumber, Radio, Select } from 'antd'
|
||||||
import TextArea from 'antd/es/input/TextArea'
|
import TextArea from 'antd/es/input/TextArea'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
@ -367,9 +368,9 @@ const ZhipuPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
{t('paintings.paint_course')}
|
{t('paintings.paint_course')}
|
||||||
</SettingHelpLink>
|
</SettingHelpLink>
|
||||||
<ProviderLogo
|
<ProviderLogo
|
||||||
shape="square"
|
radius="md"
|
||||||
src={getProviderLogo(zhipuProvider.id)}
|
src={getProviderLogo(zhipuProvider.id)}
|
||||||
size={16}
|
className="h-4 w-4"
|
||||||
style={{ marginLeft: 5 }}
|
style={{ marginLeft: 5 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -378,7 +379,7 @@ const ZhipuPage: FC<{ Options: string[] }> = ({ Options }) => {
|
|||||||
{providerOptions.map((provider) => (
|
{providerOptions.map((provider) => (
|
||||||
<Select.Option value={provider.value} key={provider.value}>
|
<Select.Option value={provider.value} key={provider.value}>
|
||||||
<SelectOptionContainer>
|
<SelectOptionContainer>
|
||||||
<ProviderLogo shape="square" src={getProviderLogo(provider.value || '')} size={16} />
|
<ProviderLogo radius="md" src={getProviderLogo(provider.value || '')} className="h-4 w-4" />
|
||||||
{provider.label}
|
{provider.label}
|
||||||
</SelectOptionContainer>
|
</SelectOptionContainer>
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { GithubOutlined } from '@ant-design/icons'
|
|||||||
import { RowFlex } from '@cherrystudio/ui'
|
import { RowFlex } from '@cherrystudio/ui'
|
||||||
import { Switch } from '@cherrystudio/ui'
|
import { Switch } from '@cherrystudio/ui'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import IndicatorLight from '@renderer/components/IndicatorLight'
|
import IndicatorLight from '@renderer/components/IndicatorLight'
|
||||||
import { APP_NAME, AppLogo } from '@renderer/config/env'
|
import { APP_NAME, AppLogo } from '@renderer/config/env'
|
||||||
@ -15,7 +16,7 @@ import { handleSaveData } from '@renderer/store'
|
|||||||
import { runAsyncFunction } from '@renderer/utils'
|
import { runAsyncFunction } from '@renderer/utils'
|
||||||
import { UpgradeChannel } from '@shared/data/preference/preferenceTypes'
|
import { UpgradeChannel } from '@shared/data/preference/preferenceTypes'
|
||||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||||
import { Avatar, Progress, Radio, Row, Tag, Tooltip } from 'antd'
|
import { Progress, Radio, Row, Tag, Tooltip } from 'antd'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import { Bug, FileCheck, Globe, Mail, Rss } from 'lucide-react'
|
import { Bug, FileCheck, Globe, Mail, Rss } from 'lucide-react'
|
||||||
import { BadgeQuestionMark } from 'lucide-react'
|
import { BadgeQuestionMark } from 'lucide-react'
|
||||||
@ -208,7 +209,7 @@ const AboutSettings: FC = () => {
|
|||||||
strokeColor="#67ad5b"
|
strokeColor="#67ad5b"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Avatar src={AppLogo} size={80} style={{ minHeight: 80 }} />
|
<Avatar src={AppLogo} className="h-20 min-h-[80px] w-20" />
|
||||||
</AvatarWrapper>
|
</AvatarWrapper>
|
||||||
<VersionWrapper>
|
<VersionWrapper>
|
||||||
<Title>{APP_NAME}</Title>
|
<Title>{APP_NAME}</Title>
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { ExportOutlined } from '@ant-design/icons'
|
import { ExportOutlined } from '@ant-design/icons'
|
||||||
import { Flex } from '@cherrystudio/ui'
|
import { Flex } from '@cherrystudio/ui'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { ApiKeyListPopup } from '@renderer/components/Popups/ApiKeyListPopup'
|
import { ApiKeyListPopup } from '@renderer/components/Popups/ApiKeyListPopup'
|
||||||
import { getPreprocessProviderLogo, PREPROCESS_PROVIDER_CONFIG } from '@renderer/config/preprocessProviders'
|
import { getPreprocessProviderLogo, PREPROCESS_PROVIDER_CONFIG } from '@renderer/config/preprocessProviders'
|
||||||
import { usePreprocessProvider } from '@renderer/hooks/usePreprocess'
|
import { usePreprocessProvider } from '@renderer/hooks/usePreprocess'
|
||||||
import type { PreprocessProvider } from '@renderer/types'
|
import type { PreprocessProvider } from '@renderer/types'
|
||||||
import { formatApiKeys, hasObjectKey } from '@renderer/utils'
|
import { formatApiKeys, hasObjectKey } from '@renderer/utils'
|
||||||
import { Avatar, Divider, Input, Tooltip } from 'antd'
|
import { Divider, Input, Tooltip } from 'antd'
|
||||||
import Link from 'antd/es/typography/Link'
|
import Link from 'antd/es/typography/Link'
|
||||||
import { List } from 'lucide-react'
|
import { List } from 'lucide-react'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
@ -73,7 +74,11 @@ const PreprocessProviderSettings: FC<Props> = ({ provider: _provider }) => {
|
|||||||
<>
|
<>
|
||||||
<SettingTitle>
|
<SettingTitle>
|
||||||
<Flex className="items-center gap-2">
|
<Flex className="items-center gap-2">
|
||||||
<ProviderLogo shape="square" src={getPreprocessProviderLogo(preprocessProvider.id)} size={16} />
|
<Avatar
|
||||||
|
radius="md"
|
||||||
|
src={getPreprocessProviderLogo(preprocessProvider.id)}
|
||||||
|
className="h-4 w-4 border-[0.5px] border-[var(--color-border)]"
|
||||||
|
/>
|
||||||
|
|
||||||
<ProviderName> {preprocessProvider.name}</ProviderName>
|
<ProviderName> {preprocessProvider.name}</ProviderName>
|
||||||
{officialWebsite && preprocessProviderConfig?.websites && (
|
{officialWebsite && preprocessProviderConfig?.websites && (
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Flex, RowFlex } from '@cherrystudio/ui'
|
import { Flex, RowFlex } from '@cherrystudio/ui'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
import { Avatar, Select, Tooltip } from 'antd'
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
|
import { Select, Tooltip } from 'antd'
|
||||||
import { UserRoundPlus } from 'lucide-react'
|
import { UserRoundPlus } from 'lucide-react'
|
||||||
import { useCallback, useMemo } from 'react'
|
import { useCallback, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -25,7 +26,7 @@ const UserSelector: React.FC<UserSelectorProps> = ({ currentUser, uniqueUsers, o
|
|||||||
(userId: string, userName: string) => {
|
(userId: string, userName: string) => {
|
||||||
return (
|
return (
|
||||||
<RowFlex className="items-center gap-2.5">
|
<RowFlex className="items-center gap-2.5">
|
||||||
<Avatar size={20} style={{ background: 'var(--color-primary)' }}>
|
<Avatar className="h-5 w-5 bg-primary">
|
||||||
{getUserAvatar(userId)}
|
{getUserAvatar(userId)}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<span>{userName}</span>
|
<span>{userName}</span>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Flex } from '@cherrystudio/ui'
|
import { Flex } from '@cherrystudio/ui'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import ExpandableText from '@renderer/components/ExpandableText'
|
import ExpandableText from '@renderer/components/ExpandableText'
|
||||||
import ModelIdWithTags from '@renderer/components/ModelIdWithTags'
|
import ModelIdWithTags from '@renderer/components/ModelIdWithTags'
|
||||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||||
@ -10,7 +11,6 @@ import FileItem from '@renderer/pages/files/FileItem'
|
|||||||
import NewApiBatchAddModelPopup from '@renderer/pages/settings/ProviderSettings/ModelList/NewApiBatchAddModelPopup'
|
import NewApiBatchAddModelPopup from '@renderer/pages/settings/ProviderSettings/ModelList/NewApiBatchAddModelPopup'
|
||||||
import type { Model, Provider } from '@renderer/types'
|
import type { Model, Provider } from '@renderer/types'
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import { ChevronRight, Minus, Plus } from 'lucide-react'
|
import { ChevronRight, Minus, Plus } from 'lucide-react'
|
||||||
import React, { memo, useCallback, useMemo, useState } from 'react'
|
import React, { memo, useCallback, useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -202,7 +202,11 @@ const ModelListItem: React.FC<ModelListItemProps> = memo(({ model, provider, onA
|
|||||||
boxShadow: 'none'
|
boxShadow: 'none'
|
||||||
}}
|
}}
|
||||||
fileInfo={{
|
fileInfo={{
|
||||||
icon: <Avatar src={getModelLogo(model.id)}>{model?.name?.[0]?.toUpperCase()}</Avatar>,
|
icon: (
|
||||||
|
<Avatar src={getModelLogo(model.id)} size="sm">
|
||||||
|
{model?.name?.[0]?.toUpperCase()}
|
||||||
|
</Avatar>
|
||||||
|
),
|
||||||
name: <ModelIdWithTags model={model} />,
|
name: <ModelIdWithTags model={model} />,
|
||||||
extra: model.description && <ExpandableText text={model.description} />,
|
extra: model.description && <ExpandableText text={model.description} />,
|
||||||
ext: '.model',
|
ext: '.model',
|
||||||
|
|||||||
@ -64,6 +64,7 @@ const ModelListGroup: React.FC<ModelListGroupProps> = ({
|
|||||||
indicator: (
|
indicator: (
|
||||||
<Tooltip title={t('settings.models.manage.remove_whole_group')} mouseLeaveDelay={0}>
|
<Tooltip title={t('settings.models.manage.remove_whole_group')} mouseLeaveDelay={0}>
|
||||||
<Button
|
<Button
|
||||||
|
as="span"
|
||||||
variant="light"
|
variant="light"
|
||||||
className="toolbar-item"
|
className="toolbar-item"
|
||||||
startContent={<Minus size={14} />}
|
startContent={<Minus size={14} />}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { RowFlex } from '@cherrystudio/ui'
|
import { RowFlex } from '@cherrystudio/ui'
|
||||||
import { Button } from '@cherrystudio/ui'
|
import { Button } from '@cherrystudio/ui'
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { FreeTrialModelTag } from '@renderer/components/FreeTrialModelTag'
|
import { FreeTrialModelTag } from '@renderer/components/FreeTrialModelTag'
|
||||||
import { type HealthResult, HealthStatusIndicator } from '@renderer/components/HealthStatusIndicator'
|
import { type HealthResult, HealthStatusIndicator } from '@renderer/components/HealthStatusIndicator'
|
||||||
import ModelIdWithTags from '@renderer/components/ModelIdWithTags'
|
import ModelIdWithTags from '@renderer/components/ModelIdWithTags'
|
||||||
@ -7,7 +8,7 @@ import { getModelLogo } from '@renderer/config/models'
|
|||||||
import type { Model } from '@renderer/types'
|
import type { Model } from '@renderer/types'
|
||||||
import type { ModelWithStatus } from '@renderer/types/healthCheck'
|
import type { ModelWithStatus } from '@renderer/types/healthCheck'
|
||||||
import { maskApiKey } from '@renderer/utils/api'
|
import { maskApiKey } from '@renderer/utils/api'
|
||||||
import { Avatar, Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import { Bolt, Minus } from 'lucide-react'
|
import { Bolt, Minus } from 'lucide-react'
|
||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -37,7 +38,7 @@ const ModelListItem: React.FC<ModelListItemProps> = ({ ref, model, modelStatus,
|
|||||||
return (
|
return (
|
||||||
<ListItem ref={ref}>
|
<ListItem ref={ref}>
|
||||||
<RowFlex className="flex-1 items-center gap-2.5">
|
<RowFlex className="flex-1 items-center gap-2.5">
|
||||||
<Avatar src={getModelLogo(model.id)} size={24}>
|
<Avatar src={getModelLogo(model.id)} className="h-6 w-6">
|
||||||
{model?.name?.[0]?.toUpperCase()}
|
{model?.name?.[0]?.toUpperCase()}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<ModelIdWithTags
|
<ModelIdWithTags
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import '@renderer/assets/styles/selection-toolbar.css'
|
import '@renderer/assets/styles/selection-toolbar.css'
|
||||||
|
|
||||||
|
import { Avatar } from '@cherrystudio/ui'
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import { AppLogo } from '@renderer/config/env'
|
import { AppLogo } from '@renderer/config/env'
|
||||||
@ -8,7 +9,6 @@ import i18n from '@renderer/i18n'
|
|||||||
import { defaultLanguage } from '@shared/config/constant'
|
import { defaultLanguage } from '@shared/config/constant'
|
||||||
import type { SelectionActionItem } from '@shared/data/preference/preferenceTypes'
|
import type { SelectionActionItem } from '@shared/data/preference/preferenceTypes'
|
||||||
import { IpcChannel } from '@shared/IpcChannel'
|
import { IpcChannel } from '@shared/IpcChannel'
|
||||||
import { Avatar } from 'antd'
|
|
||||||
import { ClipboardCheck, ClipboardCopy, ClipboardX, MessageSquareHeart } from 'lucide-react'
|
import { ClipboardCheck, ClipboardCopy, ClipboardX, MessageSquareHeart } from 'lucide-react'
|
||||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user