mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 12:05:54 +00:00
feat(extensions): fallback lucide icon when extension icon is missing
Render a tinted lucide icon (Puzzle / Server / Sparkles) on the extension card when the icon URL is empty or the image fails to load. Picked icons distinct from EventListener (AudioWaveform) and KnowledgeEngine (Book) to avoid visual collision with plugin component badges. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,16 @@ import { ExtensionCardVO, ExtensionType } from './ExtensionCardVO';
|
||||
import { useState } from 'react';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { BugIcon, ExternalLink, Ellipsis, Trash, ArrowUp } from 'lucide-react';
|
||||
import {
|
||||
BugIcon,
|
||||
ExternalLink,
|
||||
Ellipsis,
|
||||
Trash,
|
||||
ArrowUp,
|
||||
Server,
|
||||
Sparkles,
|
||||
Puzzle,
|
||||
} from 'lucide-react';
|
||||
import { getCloudServiceClientSync, systemInfo } from '@/app/infra/http';
|
||||
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -30,6 +39,17 @@ export default function ExtensionCardComponent({
|
||||
}: ExtensionCardComponentProps) {
|
||||
const { t } = useTranslation();
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||
const [iconFailed, setIconFailed] = useState(false);
|
||||
|
||||
const FallbackIcon =
|
||||
cardVO.type === 'mcp'
|
||||
? Server
|
||||
: cardVO.type === 'skill'
|
||||
? Sparkles
|
||||
: Puzzle;
|
||||
const iconSrc =
|
||||
cardVO.iconURL || httpClient.getPluginIconURL(cardVO.author, cardVO.name);
|
||||
const showFallback = iconFailed || !iconSrc;
|
||||
|
||||
const getTypeBadgeColor = (type: ExtensionType) => {
|
||||
switch (type) {
|
||||
@@ -202,14 +222,18 @@ export default function ExtensionCardComponent({
|
||||
onClick={() => onCardClick()}
|
||||
>
|
||||
<div className="w-full h-full flex flex-row items-start justify-start gap-[1.2rem]">
|
||||
<img
|
||||
src={
|
||||
cardVO.iconURL ||
|
||||
httpClient.getPluginIconURL(cardVO.author, cardVO.name)
|
||||
}
|
||||
alt="extension icon"
|
||||
className="w-16 h-16 rounded-[8%] flex-shrink-0"
|
||||
/>
|
||||
{showFallback ? (
|
||||
<div className="w-16 h-16 flex-shrink-0 flex items-center justify-center">
|
||||
<FallbackIcon className="w-12 h-12 text-blue-500" />
|
||||
</div>
|
||||
) : (
|
||||
<img
|
||||
src={iconSrc}
|
||||
alt="extension icon"
|
||||
className="w-16 h-16 rounded-[8%] flex-shrink-0"
|
||||
onError={() => setIconFailed(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex-1 min-w-0 h-full flex flex-col items-start justify-between gap-[0.6rem]">
|
||||
<div className="flex flex-col items-start justify-start w-full min-w-0 flex-1 overflow-hidden">
|
||||
|
||||
Reference in New Issue
Block a user