fix(dashboard): cut duplicate API/icon spam, lazy-load provider assets
Share one /api/models fetch via useModelCaps cache, mount ModelSelectModal only when open, stop double fetchModelAliases on CLI tool cards, and resolve provider icons through a session 404 cache with missing PNGs + loading=lazy. Also include Claude Exa MCP toggle (claude-settings + ClaudeToolCard) that was already in the working tree. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
68566f53dc
commit
ccb0842d0a
50 files changed
+612
-392
No files matched your search
+8
@@ -350,6 +350,8 @@ export function GenericExampleCard({ providerId, kind }) {
|
||||
className="max-h-40 rounded-lg border border-border object-contain bg-sidebar"
|
||||
onError={(e) => { e.currentTarget.style.display = "none"; }}
|
||||
onLoad={(e) => { e.currentTarget.style.display = "block"; }}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -383,6 +385,8 @@ export function GenericExampleCard({ providerId, kind }) {
|
||||
className="max-h-40 rounded-lg border border-border object-contain bg-sidebar"
|
||||
onError={(e) => { e.currentTarget.style.display = "none"; }}
|
||||
onLoad={(e) => { e.currentTarget.style.display = "block"; }}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -487,6 +491,8 @@ export function GenericExampleCard({ providerId, kind }) {
|
||||
src={`data:image/png;base64,${partialImage.b64_json}`}
|
||||
alt="Partial"
|
||||
className="max-w-full rounded-lg border border-border mt-1.5 opacity-80"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -529,6 +535,8 @@ export function GenericExampleCard({ providerId, kind }) {
|
||||
src={binaryImageUrl || (result?.data?.data?.[0]?.b64_json ? `data:image/png;base64,${result.data.data[0].b64_json}` : result?.data?.data?.[0]?.url)}
|
||||
alt="Generated"
|
||||
className="max-w-full rounded-lg border border-border"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -357,7 +357,7 @@ export default function ComboDetailPage() {
|
||||
Download
|
||||
</a>
|
||||
</div>
|
||||
<img src={testResult.imageUrl} alt="Generated" className="max-w-full rounded-lg border border-border" />
|
||||
<img src={testResult.imageUrl} alt="Generated" className="max-w-full rounded-lg border border-border" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
)}
|
||||
{testResult.audioUrl && (
|
||||
@@ -393,18 +393,20 @@ export default function ComboDetailPage() {
|
||||
)}
|
||||
</Card>
|
||||
|
||||
<ModelSelectModal
|
||||
isOpen={showPicker}
|
||||
onClose={() => setShowPicker(false)}
|
||||
onSelect={handleAddModel}
|
||||
onDeselect={handleDeselectModel}
|
||||
activeProviders={connections}
|
||||
modelAliases={modelAliases}
|
||||
title={`Add ${kindLabel} Model`}
|
||||
kindFilter={combo.kind}
|
||||
addedModelValues={providers}
|
||||
closeOnSelect={false}
|
||||
/>
|
||||
{showPicker && (
|
||||
<ModelSelectModal
|
||||
isOpen={showPicker}
|
||||
onClose={() => setShowPicker(false)}
|
||||
onSelect={handleAddModel}
|
||||
onDeselect={handleDeselectModel}
|
||||
activeProviders={connections}
|
||||
modelAliases={modelAliases}
|
||||
title={`Add ${kindLabel} Model`}
|
||||
kindFilter={combo.kind}
|
||||
addedModelValues={providers}
|
||||
closeOnSelect={false}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user