feat: dark theme icon support (#28858)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import type { ToolWithProvider } from '../../types'
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { ToolDefaultValue } from '../types'
|
||||
@@ -10,9 +10,13 @@ import { useGetLanguage } from '@/context/i18n'
|
||||
import BlockIcon from '../../block-icon'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { Theme } from '@/types/app'
|
||||
import { basePath } from '@/utils/var'
|
||||
|
||||
const normalizeProviderIcon = (icon: ToolWithProvider['icon']) => {
|
||||
const normalizeProviderIcon = (icon?: ToolWithProvider['icon']) => {
|
||||
if (!icon)
|
||||
return icon
|
||||
if (typeof icon === 'string' && basePath && icon.startsWith('/') && !icon.startsWith(`${basePath}/`))
|
||||
return `${basePath}${icon}`
|
||||
return icon
|
||||
@@ -36,6 +40,20 @@ const ToolItem: FC<Props> = ({
|
||||
const { t } = useTranslation()
|
||||
|
||||
const language = useGetLanguage()
|
||||
const { theme } = useTheme()
|
||||
const normalizedIcon = useMemo<ToolWithProvider['icon']>(() => {
|
||||
return normalizeProviderIcon(provider.icon) ?? provider.icon
|
||||
}, [provider.icon])
|
||||
const normalizedIconDark = useMemo(() => {
|
||||
if (!provider.icon_dark)
|
||||
return undefined
|
||||
return normalizeProviderIcon(provider.icon_dark) ?? provider.icon_dark
|
||||
}, [provider.icon_dark])
|
||||
const providerIcon = useMemo(() => {
|
||||
if (theme === Theme.dark && normalizedIconDark)
|
||||
return normalizedIconDark
|
||||
return normalizedIcon
|
||||
}, [theme, normalizedIcon, normalizedIconDark])
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
@@ -49,7 +67,7 @@ const ToolItem: FC<Props> = ({
|
||||
size='md'
|
||||
className='mb-2'
|
||||
type={BlockEnum.Tool}
|
||||
toolIcon={provider.icon}
|
||||
toolIcon={providerIcon}
|
||||
/>
|
||||
<div className='mb-1 text-sm leading-5 text-text-primary'>{payload.label[language]}</div>
|
||||
<div className='text-xs leading-[18px] text-text-secondary'>{payload.description[language]}</div>
|
||||
@@ -73,7 +91,8 @@ const ToolItem: FC<Props> = ({
|
||||
provider_name: provider.name,
|
||||
plugin_id: provider.plugin_id,
|
||||
plugin_unique_identifier: provider.plugin_unique_identifier,
|
||||
provider_icon: normalizeProviderIcon(provider.icon),
|
||||
provider_icon: normalizedIcon,
|
||||
provider_icon_dark: normalizedIconDark,
|
||||
tool_name: payload.name,
|
||||
tool_label: payload.label[language],
|
||||
tool_description: payload.description[language],
|
||||
|
||||
@@ -14,11 +14,15 @@ import ActionItem from './action-item'
|
||||
import BlockIcon from '../../block-icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useHover } from 'ahooks'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { Theme } from '@/types/app'
|
||||
import McpToolNotSupportTooltip from '../../nodes/_base/components/mcp-tool-not-support-tooltip'
|
||||
import { Mcp } from '@/app/components/base/icons/src/vender/other'
|
||||
import { basePath } from '@/utils/var'
|
||||
|
||||
const normalizeProviderIcon = (icon: ToolWithProvider['icon']) => {
|
||||
const normalizeProviderIcon = (icon?: ToolWithProvider['icon']) => {
|
||||
if (!icon)
|
||||
return icon
|
||||
if (typeof icon === 'string' && basePath && icon.startsWith('/') && !icon.startsWith(`${basePath}/`))
|
||||
return `${basePath}${icon}`
|
||||
return icon
|
||||
@@ -59,6 +63,20 @@ const Tool: FC<Props> = ({
|
||||
const isHovering = useHover(ref)
|
||||
const isMCPTool = payload.type === CollectionType.mcp
|
||||
const isShowCanNotChooseMCPTip = !canChooseMCPTool && isMCPTool
|
||||
const { theme } = useTheme()
|
||||
const normalizedIcon = useMemo<ToolWithProvider['icon']>(() => {
|
||||
return normalizeProviderIcon(payload.icon) ?? payload.icon
|
||||
}, [payload.icon])
|
||||
const normalizedIconDark = useMemo(() => {
|
||||
if (!payload.icon_dark)
|
||||
return undefined
|
||||
return normalizeProviderIcon(payload.icon_dark) ?? payload.icon_dark
|
||||
}, [payload.icon_dark])
|
||||
const providerIcon = useMemo<ToolWithProvider['icon']>(() => {
|
||||
if (theme === Theme.dark && normalizedIconDark)
|
||||
return normalizedIconDark
|
||||
return normalizedIcon
|
||||
}, [theme, normalizedIcon, normalizedIconDark])
|
||||
const getIsDisabled = useCallback((tool: ToolType) => {
|
||||
if (!selectedTools || !selectedTools.length) return false
|
||||
return selectedTools.some(selectedTool => (selectedTool.provider_name === payload.name || selectedTool.provider_name === payload.id) && selectedTool.tool_name === tool.name)
|
||||
@@ -95,7 +113,8 @@ const Tool: FC<Props> = ({
|
||||
provider_name: payload.name,
|
||||
plugin_id: payload.plugin_id,
|
||||
plugin_unique_identifier: payload.plugin_unique_identifier,
|
||||
provider_icon: normalizeProviderIcon(payload.icon),
|
||||
provider_icon: normalizedIcon,
|
||||
provider_icon_dark: normalizedIconDark,
|
||||
tool_name: tool.name,
|
||||
tool_label: tool.label[language],
|
||||
tool_description: tool.description[language],
|
||||
@@ -177,7 +196,8 @@ const Tool: FC<Props> = ({
|
||||
provider_name: payload.name,
|
||||
plugin_id: payload.plugin_id,
|
||||
plugin_unique_identifier: payload.plugin_unique_identifier,
|
||||
provider_icon: normalizeProviderIcon(payload.icon),
|
||||
provider_icon: normalizedIcon,
|
||||
provider_icon_dark: normalizedIconDark,
|
||||
tool_name: tool.name,
|
||||
tool_label: tool.label[language],
|
||||
tool_description: tool.description[language],
|
||||
@@ -192,7 +212,7 @@ const Tool: FC<Props> = ({
|
||||
<BlockIcon
|
||||
className='shrink-0'
|
||||
type={BlockEnum.Tool}
|
||||
toolIcon={payload.icon}
|
||||
toolIcon={providerIcon}
|
||||
/>
|
||||
<div className='ml-2 flex w-0 grow items-center text-sm text-text-primary'>
|
||||
<span className='max-w-[250px] truncate'>{notShowProvider ? actions[0]?.label[language] : payload.label[language]}</span>
|
||||
|
||||
@@ -10,6 +10,17 @@ import BlockIcon from '@/app/components/workflow/block-icon'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type { TriggerDefaultValue, TriggerWithProvider } from '@/app/components/workflow/block-selector/types'
|
||||
import TriggerPluginActionItem from './action-item'
|
||||
import { Theme } from '@/types/app'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { basePath } from '@/utils/var'
|
||||
|
||||
const normalizeProviderIcon = (icon?: TriggerWithProvider['icon']) => {
|
||||
if (!icon)
|
||||
return icon
|
||||
if (typeof icon === 'string' && basePath && icon.startsWith('/') && !icon.startsWith(`${basePath}/`))
|
||||
return `${basePath}${icon}`
|
||||
return icon
|
||||
}
|
||||
|
||||
type Props = {
|
||||
className?: string
|
||||
@@ -26,6 +37,7 @@ const TriggerPluginItem: FC<Props> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const language = useGetLanguage()
|
||||
const { theme } = useTheme()
|
||||
const notShowProvider = payload.type === CollectionType.workflow
|
||||
const actions = payload.events
|
||||
const hasAction = !notShowProvider
|
||||
@@ -55,6 +67,23 @@ const TriggerPluginItem: FC<Props> = ({
|
||||
|
||||
return payload.author || ''
|
||||
}, [payload.author, payload.type, t])
|
||||
const normalizedIcon = useMemo<TriggerWithProvider['icon']>(() => {
|
||||
return normalizeProviderIcon(payload.icon) ?? payload.icon
|
||||
}, [payload.icon])
|
||||
const normalizedIconDark = useMemo(() => {
|
||||
if (!payload.icon_dark)
|
||||
return undefined
|
||||
return normalizeProviderIcon(payload.icon_dark) ?? payload.icon_dark
|
||||
}, [payload.icon_dark])
|
||||
const providerIcon = useMemo<TriggerWithProvider['icon']>(() => {
|
||||
if (theme === Theme.dark && normalizedIconDark)
|
||||
return normalizedIconDark
|
||||
return normalizedIcon
|
||||
}, [normalizedIcon, normalizedIconDark, theme])
|
||||
const providerWithResolvedIcon = useMemo(() => ({
|
||||
...payload,
|
||||
icon: providerIcon,
|
||||
}), [payload, providerIcon])
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -99,7 +128,7 @@ const TriggerPluginItem: FC<Props> = ({
|
||||
<BlockIcon
|
||||
className='shrink-0'
|
||||
type={BlockEnum.TriggerPlugin}
|
||||
toolIcon={payload.icon}
|
||||
toolIcon={providerIcon}
|
||||
/>
|
||||
<div className='ml-2 flex min-w-0 flex-1 items-center text-sm text-text-primary'>
|
||||
<span className='max-w-[200px] truncate'>{notShowProvider ? actions[0]?.label[language] : payload.label[language]}</span>
|
||||
@@ -118,7 +147,7 @@ const TriggerPluginItem: FC<Props> = ({
|
||||
actions.map(action => (
|
||||
<TriggerPluginActionItem
|
||||
key={action.name}
|
||||
provider={payload}
|
||||
provider={providerWithResolvedIcon}
|
||||
payload={action}
|
||||
onSelect={onSelect}
|
||||
disabled={false}
|
||||
|
||||
@@ -59,6 +59,7 @@ export type ToolDefaultValue = PluginCommonDefaultValue & {
|
||||
meta?: PluginMeta
|
||||
plugin_id?: string
|
||||
provider_icon?: Collection['icon']
|
||||
provider_icon_dark?: Collection['icon']
|
||||
plugin_unique_identifier?: string
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user