feat: dark theme icon support (#28858)

This commit is contained in:
非法操作
2025-12-04 09:29:00 +08:00
committed by GitHub
parent 31481581e8
commit 3e5f683e90
23 changed files with 204 additions and 35 deletions

View File

@@ -6,6 +6,8 @@ import { getLanguage } from '@/i18n-config/language'
import cn from '@/utils/classnames'
import { RiAlertFill } from '@remixicon/react'
import React from 'react'
import useTheme from '@/hooks/use-theme'
import { Theme } from '@/types/app'
import Partner from '../base/badges/partner'
import Verified from '../base/badges/verified'
import Icon from '../card/base/card-icon'
@@ -50,7 +52,9 @@ const Card = ({
const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale
const { t } = useMixedTranslation(localeFromProps)
const { categoriesMap } = useCategories(t, true)
const { category, type, name, org, label, brief, icon, verified, badges = [] } = payload
const { category, type, name, org, label, brief, icon, icon_dark, verified, badges = [] } = payload
const { theme } = useTheme()
const iconSrc = theme === Theme.dark && icon_dark ? icon_dark : icon
const getLocalizedText = (obj: Record<string, string> | undefined) =>
obj ? renderI18nObject(obj, locale) : ''
const isPartner = badges.includes('partner')
@@ -71,7 +75,7 @@ const Card = ({
{!hideCornerMark && <CornerMark text={categoriesMap[type === 'bundle' ? type : category]?.label} />}
{/* Header */}
<div className="flex">
<Icon src={icon} installed={installed} installFailed={installFailed} />
<Icon src={iconSrc} installed={installed} installFailed={installFailed} />
<div className="ml-3 w-0 grow">
<div className="flex h-5 items-center">
<Title title={getLocalizedText(label)} />

View File

@@ -64,10 +64,12 @@ const InstallFromLocalPackage: React.FC<InstallFromLocalPackageProps> = ({
uniqueIdentifier,
} = result
const icon = await getIconUrl(manifest!.icon)
const iconDark = manifest.icon_dark ? await getIconUrl(manifest.icon_dark) : undefined
setUniqueIdentifier(uniqueIdentifier)
setManifest({
...manifest,
icon,
icon_dark: iconDark,
})
setStep(InstallStep.readyToInstall)
}, [getIconUrl])

View File

@@ -17,6 +17,7 @@ export const pluginManifestToCardPluginProps = (pluginManifest: PluginDeclaratio
brief: pluginManifest.description,
description: pluginManifest.description,
icon: pluginManifest.icon,
icon_dark: pluginManifest.icon_dark,
verified: pluginManifest.verified,
introduction: '',
repository: '',

View File

@@ -28,9 +28,9 @@ import {
RiHardDrive3Line,
} from '@remixicon/react'
import { useBoolean } from 'ahooks'
import { useTheme } from 'next-themes'
import React, { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import useTheme from '@/hooks/use-theme'
import Verified from '../base/badges/verified'
import { AutoUpdateLine } from '../../base/icons/src/vender/system'
import DeprecationNotice from '../base/deprecation-notice'
@@ -86,7 +86,7 @@ const DetailHeader = ({
alternative_plugin_id,
} = detail
const { author, category, name, label, description, icon, verified, tool } = detail.declaration || detail
const { author, category, name, label, description, icon, icon_dark, verified, tool } = detail.declaration || detail
const isTool = category === PluginCategoryEnum.tool
const providerBriefInfo = tool?.identity
const providerKey = `${plugin_id}/${providerBriefInfo?.name}`
@@ -109,6 +109,11 @@ const DetailHeader = ({
return false
}, [isFromMarketplace, latest_version, version])
const iconFileName = theme === 'dark' && icon_dark ? icon_dark : icon
const iconSrc = iconFileName
? (iconFileName.startsWith('http') ? iconFileName : `${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${iconFileName}`)
: ''
const detailUrl = useMemo(() => {
if (isFromGitHub)
return `https://github.com/${meta!.repo}`
@@ -214,7 +219,7 @@ const DetailHeader = ({
<div className={cn('shrink-0 border-b border-divider-subtle bg-components-panel-bg p-4 pb-3', isReadmeView && 'border-b-0 bg-transparent p-0')}>
<div className="flex">
<div className={cn('overflow-hidden rounded-xl border border-components-panel-border-subtle', isReadmeView && 'bg-components-panel-bg')}>
<Icon src={icon.startsWith('http') ? icon : `${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`} />
<Icon src={iconSrc} />
</div>
<div className="ml-3 w-0 grow">
<div className="flex h-5 items-center">

View File

@@ -14,11 +14,11 @@ import {
RiHardDrive3Line,
RiLoginCircleLine,
} from '@remixicon/react'
import { useTheme } from 'next-themes'
import type { FC } from 'react'
import React, { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { gte } from 'semver'
import useTheme from '@/hooks/use-theme'
import Verified from '../base/badges/verified'
import Badge from '../../base/badge'
import { Github } from '../../base/icons/src/public/common'
@@ -58,7 +58,7 @@ const PluginItem: FC<Props> = ({
status,
deprecated_reason,
} = plugin
const { category, author, name, label, description, icon, verified, meta: declarationMeta } = plugin.declaration
const { category, author, name, label, description, icon, icon_dark, verified, meta: declarationMeta } = plugin.declaration
const orgName = useMemo(() => {
return [PluginSource.github, PluginSource.marketplace].includes(source) ? author : ''
@@ -84,6 +84,10 @@ const PluginItem: FC<Props> = ({
const title = getValueFromI18nObject(label)
const descriptionText = getValueFromI18nObject(description)
const { enable_marketplace } = useGlobalPublicStore(s => s.systemFeatures)
const iconFileName = theme === 'dark' && icon_dark ? icon_dark : icon
const iconSrc = iconFileName
? (iconFileName.startsWith('http') ? iconFileName : `${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${iconFileName}`)
: ''
return (
<div
@@ -105,7 +109,7 @@ const PluginItem: FC<Props> = ({
<div className='flex h-10 w-10 items-center justify-center overflow-hidden rounded-xl border-[1px] border-components-panel-border-subtle'>
<img
className='h-full w-full'
src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`}
src={iconSrc}
alt={`plugin-${plugin_unique_identifier}-logo`}
/>
</div>

View File

@@ -71,6 +71,7 @@ export type PluginDeclaration = {
version: string
author: string
icon: string
icon_dark?: string
name: string
category: PluginCategoryEnum
label: Record<Locale, string>
@@ -248,7 +249,7 @@ export type PluginInfoFromMarketPlace = {
}
export type Plugin = {
type: 'plugin' | 'bundle' | 'model' | 'extension' | 'tool' | 'agent_strategy'
type: 'plugin' | 'bundle' | 'model' | 'extension' | 'tool' | 'agent_strategy' | 'datasource' | 'trigger'
org: string
author?: string
name: string
@@ -257,6 +258,7 @@ export type Plugin = {
latest_version: string
latest_package_identifier: string
icon: string
icon_dark?: string
verified: boolean
label: Record<Locale, string>
brief: Record<Locale, string>