From 98da79910b40e30dbfeb738fe9beb0ecd34cfc89 Mon Sep 17 00:00:00 2001 From: Alexander Brown <448862+DrJKL@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:27:45 -0800 Subject: [PATCH] feat(assets): add ModelInfoPanel for asset browser right panel Amp-Thread-ID: https://ampcode.com/threads/T-019bc42f-b9b7-71de-9d8f-6584610ab21e Co-authored-by: Amp --- src/locales/en/main.json | 15 ++ .../assets/components/AssetBrowserModal.vue | 10 +- .../components/modelInfo/ModelInfoField.vue | 12 ++ .../components/modelInfo/ModelInfoPanel.vue | 140 ++++++++++++++++++ .../assets/utils/assetMetadataUtils.ts | 60 ++++++++ 5 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 src/platform/assets/components/modelInfo/ModelInfoField.vue create mode 100644 src/platform/assets/components/modelInfo/ModelInfoPanel.vue diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 9fd1284fd..19b731d6a 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -2385,6 +2385,21 @@ "assetCard": "{name} - {type} asset", "loadingAsset": "Loading asset" }, + "modelInfo": { + "title": "Model Info", + "basicInfo": "Basic Info", + "displayName": "Display Name", + "fileName": "File Name", + "source": "Source", + "viewOnSource": "View on {source}", + "modelTagging": "Model Tagging", + "modelType": "Model Type", + "compatibleBaseModels": "Compatible Base Models", + "additionalTags": "Additional Tags", + "modelDescription": "Model Description", + "triggerPhrases": "Trigger Phrases", + "description": "Description" + }, "media": { "threeDModelPlaceholder": "3D Model", "audioPlaceholder": "Audio" diff --git a/src/platform/assets/components/AssetBrowserModal.vue b/src/platform/assets/components/AssetBrowserModal.vue index b7db7494c..5db471458 100644 --- a/src/platform/assets/components/AssetBrowserModal.vue +++ b/src/platform/assets/components/AssetBrowserModal.vue @@ -60,12 +60,16 @@ @asset-deleted="refreshAssets" /> + + diff --git a/src/platform/assets/components/modelInfo/ModelInfoPanel.vue b/src/platform/assets/components/modelInfo/ModelInfoPanel.vue new file mode 100644 index 000000000..901b336e2 --- /dev/null +++ b/src/platform/assets/components/modelInfo/ModelInfoPanel.vue @@ -0,0 +1,140 @@ + + + diff --git a/src/platform/assets/utils/assetMetadataUtils.ts b/src/platform/assets/utils/assetMetadataUtils.ts index 2d32fa07f..2d50f3dbe 100644 --- a/src/platform/assets/utils/assetMetadataUtils.ts +++ b/src/platform/assets/utils/assetMetadataUtils.ts @@ -25,3 +25,63 @@ export function getAssetBaseModel(asset: AssetItem): string | null { ? asset.user_metadata.base_model : null } + +/** + * Gets the display name for an asset, falling back to filename + * @param asset - The asset to get display name from + * @returns The display name or filename + */ +export function getAssetDisplayName(asset: AssetItem): string { + return typeof asset.user_metadata?.display_name === 'string' + ? asset.user_metadata.display_name + : asset.name +} + +/** + * Safely extracts source URL from asset metadata + * @param asset - The asset to extract source URL from + * @returns The source URL or null if not present + */ +export function getAssetSourceUrl(asset: AssetItem): string | null { + return typeof asset.user_metadata?.source_url === 'string' + ? asset.user_metadata.source_url + : null +} + +/** + * Extracts trigger phrases from asset metadata + * @param asset - The asset to extract trigger phrases from + * @returns Array of trigger phrases + */ +export function getAssetTriggerPhrases(asset: AssetItem): string[] { + const phrases = asset.user_metadata?.trigger_phrases + if (Array.isArray(phrases)) { + return phrases.filter((p): p is string => typeof p === 'string') + } + if (typeof phrases === 'string') return [phrases] + return [] +} + +/** + * Extracts additional tags from asset user_metadata + * @param asset - The asset to extract tags from + * @returns Array of user-defined tags + */ +export function getAssetTags(asset: AssetItem): string[] { + const tags = asset.user_metadata?.tags + if (Array.isArray(tags)) { + return tags.filter((t): t is string => typeof t === 'string') + } + return [] +} + +/** + * Determines the source name from a URL + * @param url - The source URL + * @returns Human-readable source name + */ +export function getSourceName(url: string): string { + if (url.includes('civitai.com')) return 'Civitai' + if (url.includes('huggingface.co')) return 'Hugging Face' + return 'Source' +}