mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-08 17:10:07 +00:00
Add a markdown image preview for the node help menu.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
<!-- Markdown fetched successfully -->
|
||||
<div
|
||||
v-else-if="!error"
|
||||
ref="markdownContainer"
|
||||
class="markdown-content"
|
||||
v-html="renderedHelpHtml"
|
||||
/>
|
||||
@@ -81,17 +82,50 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image Gallery for markdown images -->
|
||||
<ResultGallery
|
||||
v-model:activeIndex="galleryActiveIndex"
|
||||
:all-gallery-items="galleryItems"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import Button from 'primevue/button'
|
||||
import ProgressSpinner from 'primevue/progressspinner'
|
||||
import { computed } from 'vue'
|
||||
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import type { ComfyNodeDefImpl } from '@/stores/nodeDefStore'
|
||||
import { ResultItemImpl } from '@/stores/queueStore'
|
||||
import { useNodeHelpStore } from '@/stores/workspace/nodeHelpStore'
|
||||
|
||||
import ResultGallery from '../queue/ResultGallery.vue'
|
||||
|
||||
// Custom class for external markdown images
|
||||
class MarkdownImageItem extends ResultItemImpl {
|
||||
private _externalUrl: string
|
||||
|
||||
constructor(externalUrl: string, filename: string, index: number) {
|
||||
super({
|
||||
filename,
|
||||
subfolder: '',
|
||||
type: 'output',
|
||||
nodeId: `markdown-${index}`,
|
||||
mediaType: 'images'
|
||||
})
|
||||
this._externalUrl = externalUrl
|
||||
}
|
||||
|
||||
override get url(): string {
|
||||
return this._externalUrl
|
||||
}
|
||||
|
||||
override get urlWithTimestamp(): string {
|
||||
return this._externalUrl
|
||||
}
|
||||
}
|
||||
|
||||
const { node } = defineProps<{ node: ComfyNodeDefImpl }>()
|
||||
|
||||
const nodeHelpStore = useNodeHelpStore()
|
||||
@@ -101,6 +135,11 @@ defineEmits<{
|
||||
(e: 'close'): void
|
||||
}>()
|
||||
|
||||
// Gallery state for image preview
|
||||
const markdownContainer = ref<HTMLElement | null>(null)
|
||||
const galleryItems = ref<MarkdownImageItem[]>([])
|
||||
const galleryActiveIndex = ref(-1)
|
||||
|
||||
const inputList = computed(() =>
|
||||
Object.values(node.inputs).map((spec) => ({
|
||||
name: spec.name,
|
||||
@@ -116,6 +155,63 @@ const outputList = computed(() =>
|
||||
tooltip: spec.tooltip || ''
|
||||
}))
|
||||
)
|
||||
|
||||
// Track if we've already setup image preview to avoid re-setup
|
||||
const imagePreviewSetup = ref(false)
|
||||
|
||||
// Function to setup image preview functionality
|
||||
function setupImagePreview() {
|
||||
if (!markdownContainer.value || imagePreviewSetup.value) return
|
||||
|
||||
const imgs = Array.from(markdownContainer.value.querySelectorAll('img'))
|
||||
|
||||
// Only setup if there are images
|
||||
if (imgs.length === 0) return
|
||||
|
||||
// Update gallery items - create proper MarkdownImageItem instances
|
||||
galleryItems.value = imgs.map((img, index) => {
|
||||
// Extract filename from URL
|
||||
const url = new URL(img.src, window.location.origin)
|
||||
const filename = url.pathname.split('/').pop() || `image-${index}.jpg`
|
||||
|
||||
return new MarkdownImageItem(img.src, filename, index)
|
||||
})
|
||||
|
||||
// Add click handlers to images
|
||||
imgs.forEach((img, index) => {
|
||||
img.style.cursor = 'zoom-in'
|
||||
img.onclick = (e) => {
|
||||
e.preventDefault()
|
||||
galleryActiveIndex.value = index
|
||||
}
|
||||
})
|
||||
|
||||
imagePreviewSetup.value = true
|
||||
}
|
||||
|
||||
// Reset setup flag when content changes
|
||||
function resetImagePreviewSetup() {
|
||||
imagePreviewSetup.value = false
|
||||
galleryItems.value = []
|
||||
galleryActiveIndex.value = -1
|
||||
}
|
||||
|
||||
// Watch for changes in rendered HTML and setup image preview
|
||||
watch(renderedHelpHtml, async () => {
|
||||
resetImagePreviewSetup()
|
||||
await nextTick()
|
||||
setupImagePreview()
|
||||
})
|
||||
|
||||
// Watch for loading state changes
|
||||
watch([isLoading, error], () => {
|
||||
resetImagePreviewSetup()
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
setupImagePreview()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -242,4 +338,13 @@ const outputList = computed(() =>
|
||||
color: var(--p-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add hover effect for clickable images */
|
||||
.markdown-content :deep(img) {
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.markdown-content :deep(img:hover) {
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user