refactor: Centralize emoji detection utility and improve avatar rendering
This commit is contained in:
parent
92ab67eb3d
commit
efa9c6c546
@ -4,15 +4,15 @@ import ImageStorage from '@renderer/services/ImageStorage'
|
|||||||
import { useAppDispatch } from '@renderer/store'
|
import { useAppDispatch } from '@renderer/store'
|
||||||
import { setAvatar } from '@renderer/store/runtime'
|
import { setAvatar } from '@renderer/store/runtime'
|
||||||
import { setUserName } from '@renderer/store/settings'
|
import { setUserName } from '@renderer/store/settings'
|
||||||
import { compressImage } from '@renderer/utils'
|
import { compressImage, isEmoji } from '@renderer/utils'
|
||||||
import { Avatar , Input, Modal, Popover, Upload, Dropdown } from 'antd'
|
import { Avatar, Dropdown, Input, Modal, Popover, Upload } from 'antd'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
import EmojiPicker from '../EmojiPicker'
|
||||||
import { Center, HStack, VStack } from '../Layout'
|
import { Center, HStack, VStack } from '../Layout'
|
||||||
import { TopView } from '../TopView'
|
import { TopView } from '../TopView'
|
||||||
import EmojiPicker from '../EmojiPicker'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
resolve: (data: any) => void
|
resolve: (data: any) => void
|
||||||
@ -51,12 +51,6 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// modify the judgment function, more accurately detect Emoji
|
|
||||||
const isEmoji = (str: string) => {
|
|
||||||
// check if it is a string and is not base64 or URL format
|
|
||||||
return str && typeof str === 'string' && !str.startsWith('data:') && !str.startsWith('http');
|
|
||||||
}
|
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
key: 'upload',
|
key: 'upload',
|
||||||
@ -88,11 +82,12 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
{
|
{
|
||||||
key: 'emoji',
|
key: 'emoji',
|
||||||
label: (
|
label: (
|
||||||
<div onClick={(e) => {
|
<div
|
||||||
e.stopPropagation()
|
onClick={(e) => {
|
||||||
setEmojiPickerOpen(true)
|
e.stopPropagation()
|
||||||
setDropdownOpen(false)
|
setEmojiPickerOpen(true)
|
||||||
}}>
|
setDropdownOpen(false)
|
||||||
|
}}>
|
||||||
{t('settings.general.emoji_picker')}
|
{t('settings.general.emoji_picker')}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -134,11 +129,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
placement="bottom">
|
placement="bottom">
|
||||||
{isEmoji(avatar) ? (
|
{isEmoji(avatar) ? <EmojiAvatar>{avatar}</EmojiAvatar> : <UserAvatar src={avatar} />}
|
||||||
<EmojiAvatar>{avatar}</EmojiAvatar>
|
|
||||||
) : (
|
|
||||||
<UserAvatar src={avatar} />
|
|
||||||
)}
|
|
||||||
</Popover>
|
</Popover>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</VStack>
|
</VStack>
|
||||||
@ -147,7 +138,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
<Input
|
<Input
|
||||||
placeholder={t('settings.general.user_name.placeholder')}
|
placeholder={t('settings.general.user_name.placeholder')}
|
||||||
value={userName}
|
value={userName}
|
||||||
onChange={(e) => dispatch(setUserName(e.target.value))}
|
onChange={(e) => dispatch(setUserName(e.target.value.trim()))}
|
||||||
style={{ flex: 1, textAlign: 'center', width: '100%' }}
|
style={{ flex: 1, textAlign: 'center', width: '100%' }}
|
||||||
maxLength={30}
|
maxLength={30}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import useAvatar from '@renderer/hooks/useAvatar'
|
|||||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||||
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
|
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
|
import { isEmoji } from '@renderer/utils'
|
||||||
import type { MenuProps } from 'antd'
|
import type { MenuProps } from 'antd'
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import { Avatar } from 'antd'
|
import { Avatar } from 'antd'
|
||||||
@ -57,10 +58,6 @@ const Sidebar: FC = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const isEmoji = (str: string) => {
|
|
||||||
return str && typeof str === 'string' && !str.startsWith('data:') && !str.startsWith('http');
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
id="app-sidebar"
|
id="app-sidebar"
|
||||||
@ -69,7 +66,7 @@ const Sidebar: FC = () => {
|
|||||||
zIndex: minappShow ? 10000 : 'initial'
|
zIndex: minappShow ? 10000 : 'initial'
|
||||||
}}>
|
}}>
|
||||||
{isEmoji(avatar) ? (
|
{isEmoji(avatar) ? (
|
||||||
<EmojiAvatarSidebar onClick={onEditUser}>{avatar}</EmojiAvatarSidebar>
|
<EmojiAvatar onClick={onEditUser}>{avatar}</EmojiAvatar>
|
||||||
) : (
|
) : (
|
||||||
<AvatarImg src={avatar || UserAvatar} draggable={false} className="nodrag" onClick={onEditUser} />
|
<AvatarImg src={avatar || UserAvatar} draggable={false} className="nodrag" onClick={onEditUser} />
|
||||||
)}
|
)}
|
||||||
@ -229,7 +226,7 @@ const AvatarImg = styled(Avatar)`
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`
|
`
|
||||||
|
|
||||||
const EmojiAvatarSidebar = styled.div`
|
const EmojiAvatar = styled.div`
|
||||||
width: 31px;
|
width: 31px;
|
||||||
height: 31px;
|
height: 31px;
|
||||||
background-color: var(--color-background-soft);
|
background-color: var(--color-background-soft);
|
||||||
@ -242,6 +239,7 @@ const EmojiAvatarSidebar = styled.div`
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-webkit-app-region: none;
|
-webkit-app-region: none;
|
||||||
|
border: 0.5px solid var(--color-border);
|
||||||
`
|
`
|
||||||
|
|
||||||
const MainMenusContainer = styled.div`
|
const MainMenusContainer = styled.div`
|
||||||
|
|||||||
@ -8,17 +8,13 @@ import { useMessageStyle, useSettings } from '@renderer/hooks/useSettings'
|
|||||||
import { getMessageModelId } from '@renderer/services/MessagesService'
|
import { getMessageModelId } from '@renderer/services/MessagesService'
|
||||||
import { getModelName } from '@renderer/services/ModelService'
|
import { getModelName } from '@renderer/services/ModelService'
|
||||||
import { Assistant, Message, Model } from '@renderer/types'
|
import { Assistant, Message, Model } from '@renderer/types'
|
||||||
import { firstLetter, removeLeadingEmoji } from '@renderer/utils'
|
import { firstLetter, isEmoji, removeLeadingEmoji } from '@renderer/utils'
|
||||||
import { Avatar } from 'antd'
|
import { Avatar } from 'antd'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { CSSProperties, FC, memo, useCallback, useMemo } from 'react'
|
import { CSSProperties, FC, memo, useCallback, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
const isEmoji = (str: string) => {
|
|
||||||
return str && typeof str === 'string' && !str.startsWith('data:') && !str.startsWith('http');
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
message: Message
|
message: Message
|
||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
|
|||||||
@ -123,6 +123,19 @@ export function getLeadingEmoji(str: string): string {
|
|||||||
return match ? match[0] : ''
|
return match ? match[0] : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isEmoji(str: string) {
|
||||||
|
if (str.startsWith('data:')) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.startsWith('http')) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const emojiRegex = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F)+/u
|
||||||
|
return str.match(emojiRegex)
|
||||||
|
}
|
||||||
|
|
||||||
export function isFreeModel(model: Model) {
|
export function isFreeModel(model: Model) {
|
||||||
return (model.id + model.name).toLocaleLowerCase().includes('free')
|
return (model.id + model.name).toLocaleLowerCase().includes('free')
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user