mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-15 01:48:06 +00:00
Compare commits
13 Commits
docs/weekl
...
v1.18.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0aedf9c694 | ||
|
|
98abb20e8d | ||
|
|
508f13b66d | ||
|
|
9f2aecf052 | ||
|
|
1215a23393 | ||
|
|
51fc93ef34 | ||
|
|
8c5ccb0346 | ||
|
|
e9383fc6b2 | ||
|
|
0825ea2f5d | ||
|
|
32ac59f0f4 | ||
|
|
8feb5af8fa | ||
|
|
2ac6159939 | ||
|
|
1071242359 |
4
.github/workflows/release.yaml
vendored
4
.github/workflows/release.yaml
vendored
@@ -2,8 +2,8 @@ name: Create Release Draft
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ closed ]
|
||||
branches: [ main, core/* ]
|
||||
types: [closed]
|
||||
branches: [main, core/*, desktop/*]
|
||||
paths:
|
||||
- 'package.json'
|
||||
|
||||
|
||||
@@ -270,6 +270,7 @@ export class ComfyPage {
|
||||
localStorage.clear()
|
||||
sessionStorage.clear()
|
||||
localStorage.setItem('Comfy.userId', id)
|
||||
localStorage.setItem('api-nodes-news-seen', 'true')
|
||||
}, this.id)
|
||||
}
|
||||
await this.goto()
|
||||
@@ -924,6 +925,12 @@ export class ComfyPage {
|
||||
return window['app'].canvas.ds.convertOffsetToCanvas(pos)
|
||||
}, pos)
|
||||
}
|
||||
|
||||
/** Get number of DOM widgets on the canvas. */
|
||||
async getDOMWidgetCount() {
|
||||
return await this.page.locator('.dom-widget').count()
|
||||
}
|
||||
|
||||
async getNodeRefById(id: NodeId) {
|
||||
return new NodeReference(id, this)
|
||||
}
|
||||
|
||||
@@ -31,4 +31,20 @@ test.describe('DOM Widget', () => {
|
||||
await comfyPage.nextFrame()
|
||||
await expect(comfyPage.canvas).toHaveScreenshot('focus-mode-on.png')
|
||||
})
|
||||
|
||||
// No DOM widget should be created by creation of interim LGraphNode objects.
|
||||
test('Copy node with DOM widget by dragging + alt', async ({ comfyPage }) => {
|
||||
const initialCount = await comfyPage.getDOMWidgetCount()
|
||||
|
||||
// TextEncodeNode1
|
||||
await comfyPage.page.mouse.move(618, 191)
|
||||
await comfyPage.page.keyboard.down('Alt')
|
||||
await comfyPage.page.mouse.down()
|
||||
await comfyPage.page.mouse.move(100, 100)
|
||||
await comfyPage.page.mouse.up()
|
||||
await comfyPage.page.keyboard.up('Alt')
|
||||
|
||||
const finalCount = await comfyPage.getDOMWidgetCount()
|
||||
expect(finalCount).toBe(initialCount + 1)
|
||||
})
|
||||
})
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@comfyorg/comfyui-frontend",
|
||||
"version": "1.18.6",
|
||||
"version": "1.18.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@comfyorg/comfyui-frontend",
|
||||
"version": "1.18.6",
|
||||
"version": "1.18.8",
|
||||
"license": "GPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@alloc/quick-lru": "^5.2.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@comfyorg/comfyui-frontend",
|
||||
"private": true,
|
||||
"version": "1.18.6",
|
||||
"version": "1.18.8",
|
||||
"type": "module",
|
||||
"repository": "https://github.com/Comfy-Org/ComfyUI_frontend",
|
||||
"homepage": "https://comfy.org",
|
||||
|
||||
BIN
src/assets/images/api-nodes-news.webp
Normal file
BIN
src/assets/images/api-nodes-news.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
69
src/components/dialog/content/ApiNodesNewsContent.vue
Normal file
69
src/components/dialog/content/ApiNodesNewsContent.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-12 p-2 w-96">
|
||||
<img src="@/assets/images/api-nodes-news.webp" alt="API Nodes News" />
|
||||
<div class="flex flex-col gap-2 justify-center items-center">
|
||||
<div class="text-xl">
|
||||
{{ $t('apiNodesNews.introducing') }}
|
||||
<span class="text-amber-500">API NODES</span>
|
||||
</div>
|
||||
<div class="text-muted">{{ $t('apiNodesNews.subtitle') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<div
|
||||
v-for="(step, index) in steps"
|
||||
:key="index"
|
||||
class="grid grid-cols-[auto_1fr] gap-2 items-center"
|
||||
>
|
||||
<Tag class="w-8 h-8" :value="index + 1" rounded />
|
||||
<div class="flex flex-col gap-2">
|
||||
<div>{{ step.title }}</div>
|
||||
<div v-if="step.subtitle" class="text-muted">
|
||||
{{ step.subtitle }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row justify-between">
|
||||
<Button label="Learn More" text @click="handleLearnMore" />
|
||||
<Button label="Close" @click="onClose" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from 'primevue/button'
|
||||
import Tag from 'primevue/tag'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const steps: {
|
||||
title: string
|
||||
subtitle?: string
|
||||
}[] = [
|
||||
{
|
||||
title: t('apiNodesNews.steps.step1.title'),
|
||||
subtitle: t('apiNodesNews.steps.step1.subtitle')
|
||||
},
|
||||
{
|
||||
title: t('apiNodesNews.steps.step2.title'),
|
||||
subtitle: t('apiNodesNews.steps.step2.subtitle')
|
||||
},
|
||||
{
|
||||
title: t('apiNodesNews.steps.step3.title')
|
||||
},
|
||||
{
|
||||
title: t('apiNodesNews.steps.step4.title')
|
||||
}
|
||||
]
|
||||
|
||||
const { onClose } = defineProps<{
|
||||
onClose: () => void
|
||||
}>()
|
||||
|
||||
const handleLearnMore = () => {
|
||||
window.open('https://blog.comfy.org/p/comfyui-native-api-nodes', '_blank')
|
||||
}
|
||||
</script>
|
||||
@@ -5,9 +5,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { LGraphNode } from '@comfyorg/litegraph'
|
||||
import { BadgePosition } from '@comfyorg/litegraph'
|
||||
import { LGraphBadge } from '@comfyorg/litegraph'
|
||||
import {
|
||||
BadgePosition,
|
||||
LGraphBadge,
|
||||
type LGraphNode
|
||||
} from '@comfyorg/litegraph'
|
||||
import _ from 'lodash'
|
||||
import { computed, onMounted, watch } from 'vue'
|
||||
|
||||
@@ -83,6 +85,29 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
node.badges.push(() => badge.value)
|
||||
|
||||
if (node.constructor.nodeData?.api_node) {
|
||||
const creditsBadge = computed(() => {
|
||||
return new LGraphBadge({
|
||||
text: '',
|
||||
iconOptions: {
|
||||
unicode: '\ue96b',
|
||||
fontFamily: 'PrimeIcons',
|
||||
color: '#FABC25',
|
||||
bgColor: '#353535',
|
||||
fontSize: 8
|
||||
},
|
||||
fgColor:
|
||||
colorPaletteStore.completedActivePalette.colors.litegraph_base
|
||||
.BADGE_FG_COLOR,
|
||||
bgColor:
|
||||
colorPaletteStore.completedActivePalette.colors.litegraph_base
|
||||
.BADGE_BG_COLOR
|
||||
})
|
||||
})
|
||||
|
||||
node.badges.push(() => creditsBadge.value)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -132,7 +132,8 @@ export function useSettingUI(
|
||||
creditsPanel,
|
||||
userPanel,
|
||||
keybindingPanel,
|
||||
extensionPanel
|
||||
extensionPanel,
|
||||
...(isElectron() ? [serverConfigPanel] : [])
|
||||
].filter((panel) => panel.component)
|
||||
)
|
||||
|
||||
|
||||
@@ -531,6 +531,32 @@
|
||||
"wan2_1_fun_inp": "Wan 2.1 Inpainting",
|
||||
"wan2_1_fun_control": "Wan 2.1 ControlNet"
|
||||
},
|
||||
"Image API": {
|
||||
"api_openai_image_1_t2i": "OpenAI Image-1 Text to Image",
|
||||
"api_openai_image_1_i2i": "OpenAI Image-1 Image to Image",
|
||||
"api_openai_image_1_inpaint": "OpenAI Image-1 Inpaint",
|
||||
"api_openai_image_1_multi_inputs": "OpenAI Image-1 Multi Inputs",
|
||||
"api-openai-dall-e-2-t2i": "Dall-E 2 Text to Image",
|
||||
"api-openai-dall-e-2-inpaint": "Dall-E 2 Inpaint",
|
||||
"api-openai-dall-e-3-t2i": "Dall-E 3 Text to Image",
|
||||
"api_bfl_flux_pro_t2i": "BFL Flux[Pro] Text to Image",
|
||||
"api_stability_sd3_t2i": "Stability SD3 Text to Image",
|
||||
"api_ideogram_v3_t2i": "Ideogram V3 Text to Image",
|
||||
"api_luma_photon_i2i": "Luma Photon Image to Image",
|
||||
"api_luma_photon_style_ref": "Luma Photon Style Reference",
|
||||
"api_recraft_image_gen_with_color_control": "Recraft Color Control Image Generation",
|
||||
"api_recraft_image_gen_with_style_control": "Recraft Style Control Image Generation",
|
||||
"api_recraft_vector_gen": "Recraft Vector Generation"
|
||||
},
|
||||
"Video API": {
|
||||
"api_luma_i2v": "Luma Image to Video",
|
||||
"api_kling_i2v": "Kling Image to Video",
|
||||
"api_veo2_i2v": "Veo2 Image to Video",
|
||||
"api_hailuo_minimax_i2v": "MiniMax Image to Video",
|
||||
"api_pika_scene": "Pika Scenes: Images to Video",
|
||||
"api_pixverse_template_i2v": "PixVerse Templates: Image to Video",
|
||||
"api_pixverse_t2v": "PixVerse Text to Video"
|
||||
},
|
||||
"Image": {
|
||||
"sd3_5_simple_example": "SD3.5 Simple",
|
||||
"sd3_5_large_canny_controlnet_example": "SD3.5 Large Canny ControlNet",
|
||||
@@ -1182,5 +1208,25 @@
|
||||
"provider": "Sign-in Provider",
|
||||
"notSet": "Not set",
|
||||
"updatePassword": "Update Password"
|
||||
},
|
||||
"apiNodesNews": {
|
||||
"introducing": "Introducing",
|
||||
"subtitle": "All External Models now available in ComfyUI",
|
||||
"steps": {
|
||||
"step1": {
|
||||
"title": "Login/Create an account:",
|
||||
"subtitle": "Settings > User > Login"
|
||||
},
|
||||
"step2": {
|
||||
"title": "Purchase credits:",
|
||||
"subtitle": "Settings > Credits > Buy Credits"
|
||||
},
|
||||
"step3": {
|
||||
"title": "Locate new API Nodes under 'API Node' section and add to the canvas"
|
||||
},
|
||||
"step4": {
|
||||
"title": "Run!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,26 @@
|
||||
"title": "Nodo(s) de API",
|
||||
"totalCost": "Costo total"
|
||||
},
|
||||
"apiNodesNews": {
|
||||
"introducing": "Presentamos",
|
||||
"steps": {
|
||||
"step1": {
|
||||
"subtitle": "Configuración > Usuario > Iniciar sesión",
|
||||
"title": "Inicia sesión/Crea una cuenta:"
|
||||
},
|
||||
"step2": {
|
||||
"subtitle": "Configuración > Créditos > Comprar créditos",
|
||||
"title": "Compra créditos:"
|
||||
},
|
||||
"step3": {
|
||||
"title": "Ubica los nuevos nodos API en la sección 'API Node' y agrégalos al lienzo"
|
||||
},
|
||||
"step4": {
|
||||
"title": "¡Ejecuta!"
|
||||
}
|
||||
},
|
||||
"subtitle": "Todos los modelos externos ahora disponibles en ComfyUI"
|
||||
},
|
||||
"apiNodesSignInDialog": {
|
||||
"message": "Este flujo de trabajo contiene nodos de API, que requieren que inicies sesión en tu cuenta para poder ejecutar.",
|
||||
"title": "Se requiere iniciar sesión para usar los nodos de API"
|
||||
@@ -1090,6 +1110,23 @@
|
||||
"sdxl_simple_example": "SDXL Simple",
|
||||
"sdxlturbo_example": "SDXL Turbo"
|
||||
},
|
||||
"Image API": {
|
||||
"api-openai-dall-e-2-inpaint": "Dall-E 2 Rellenar",
|
||||
"api-openai-dall-e-2-t2i": "Dall-E 2 Texto a Imagen",
|
||||
"api-openai-dall-e-3-t2i": "Dall-E 3 Texto a Imagen",
|
||||
"api_bfl_flux_pro_t2i": "BFL Flux[Pro] Texto a Imagen",
|
||||
"api_ideogram_v3_t2i": "Ideogram V3 Texto a Imagen",
|
||||
"api_luma_photon_i2i": "Luma Photon Imagen a Imagen",
|
||||
"api_luma_photon_style_ref": "Luma Photon Referencia de Estilo",
|
||||
"api_openai_image_1_i2i": "OpenAI Image-1 Imagen a Imagen",
|
||||
"api_openai_image_1_inpaint": "OpenAI Image-1 Rellenar",
|
||||
"api_openai_image_1_multi_inputs": "OpenAI Image-1 Múltiples Entradas",
|
||||
"api_openai_image_1_t2i": "OpenAI Image-1 Texto a Imagen",
|
||||
"api_recraft_image_gen_with_color_control": "Recraft Generación de Imagen con Control de Color",
|
||||
"api_recraft_image_gen_with_style_control": "Recraft Generación de Imagen con Control de Estilo",
|
||||
"api_recraft_vector_gen": "Recraft Generación de Vectores",
|
||||
"api_stability_sd3_t2i": "Stability SD3 Texto a Imagen"
|
||||
},
|
||||
"Upscaling": {
|
||||
"esrgan_example": "ESRGAN",
|
||||
"hiresfix_esrgan_workflow": "Flujo de Trabajo HiresFix ESRGAN",
|
||||
@@ -1107,6 +1144,15 @@
|
||||
"txt_to_image_to_video": "SVD Texto a Imagen a Video",
|
||||
"wan2_1_fun_control": "Wan 2.1 ControlNet",
|
||||
"wan2_1_fun_inp": "Wan 2.1 Relleno"
|
||||
},
|
||||
"Video API": {
|
||||
"api_hailuo_minimax_i2v": "MiniMax Imagen a Video",
|
||||
"api_kling_i2v": "Kling Imagen a Video",
|
||||
"api_luma_i2v": "Luma Imagen a Video",
|
||||
"api_pika_scene": "Pika Escenas: Imágenes a Video",
|
||||
"api_pixverse_t2v": "PixVerse Texto a Video",
|
||||
"api_pixverse_template_i2v": "PixVerse Plantillas: Imagen a Video",
|
||||
"api_veo2_i2v": "Veo2 Imagen a Video"
|
||||
}
|
||||
},
|
||||
"title": "Comienza con una Plantilla"
|
||||
|
||||
@@ -4,6 +4,26 @@
|
||||
"title": "Nœud(s) API",
|
||||
"totalCost": "Coût total"
|
||||
},
|
||||
"apiNodesNews": {
|
||||
"introducing": "Présentation",
|
||||
"steps": {
|
||||
"step1": {
|
||||
"subtitle": "Paramètres > Utilisateur > Connexion",
|
||||
"title": "Connectez-vous / Créez un compte :"
|
||||
},
|
||||
"step2": {
|
||||
"subtitle": "Paramètres > Crédits > Acheter des crédits",
|
||||
"title": "Achetez des crédits :"
|
||||
},
|
||||
"step3": {
|
||||
"title": "Trouvez les nouveaux nœuds API dans la section 'API Node' et ajoutez-les à la toile"
|
||||
},
|
||||
"step4": {
|
||||
"title": "Lancez !"
|
||||
}
|
||||
},
|
||||
"subtitle": "Tous les modèles externes sont désormais disponibles dans ComfyUI"
|
||||
},
|
||||
"apiNodesSignInDialog": {
|
||||
"message": "Ce flux de travail contient des nœuds API, qui nécessitent que vous soyez connecté à votre compte pour pouvoir fonctionner.",
|
||||
"title": "Connexion requise pour utiliser les nœuds API"
|
||||
@@ -1090,6 +1110,23 @@
|
||||
"sdxl_simple_example": "SDXL Simple",
|
||||
"sdxlturbo_example": "SDXL Turbo"
|
||||
},
|
||||
"Image API": {
|
||||
"api-openai-dall-e-2-inpaint": "Dall-E 2 Inpainting",
|
||||
"api-openai-dall-e-2-t2i": "Dall-E 2 Texte vers Image",
|
||||
"api-openai-dall-e-3-t2i": "Dall-E 3 Texte vers Image",
|
||||
"api_bfl_flux_pro_t2i": "BFL Flux[Pro] Texte vers Image",
|
||||
"api_ideogram_v3_t2i": "Ideogram V3 Texte vers Image",
|
||||
"api_luma_photon_i2i": "Luma Photon Image vers Image",
|
||||
"api_luma_photon_style_ref": "Luma Photon Référence de Style",
|
||||
"api_openai_image_1_i2i": "OpenAI Image-1 Image vers Image",
|
||||
"api_openai_image_1_inpaint": "OpenAI Image-1 Inpainting",
|
||||
"api_openai_image_1_multi_inputs": "OpenAI Image-1 Entrées Multiples",
|
||||
"api_openai_image_1_t2i": "OpenAI Image-1 Texte vers Image",
|
||||
"api_recraft_image_gen_with_color_control": "Recraft Génération d’Image avec Contrôle des Couleurs",
|
||||
"api_recraft_image_gen_with_style_control": "Recraft Génération d’Image avec Contrôle du Style",
|
||||
"api_recraft_vector_gen": "Recraft Génération de Vecteur",
|
||||
"api_stability_sd3_t2i": "Stability SD3 Texte vers Image"
|
||||
},
|
||||
"Upscaling": {
|
||||
"esrgan_example": "ESRGAN",
|
||||
"hiresfix_esrgan_workflow": "Flux de Travail ESRGAN HiresFix",
|
||||
@@ -1107,6 +1144,15 @@
|
||||
"txt_to_image_to_video": "Texte à Image à Vidéo",
|
||||
"wan2_1_fun_control": "Wan 2.1 ControlNet",
|
||||
"wan2_1_fun_inp": "Wan 2.1 Inpainting"
|
||||
},
|
||||
"Video API": {
|
||||
"api_hailuo_minimax_i2v": "MiniMax Image vers Vidéo",
|
||||
"api_kling_i2v": "Kling Image vers Vidéo",
|
||||
"api_luma_i2v": "Luma Image vers Vidéo",
|
||||
"api_pika_scene": "Pika Scènes : Images vers Vidéo",
|
||||
"api_pixverse_t2v": "PixVerse Texte vers Vidéo",
|
||||
"api_pixverse_template_i2v": "PixVerse Modèles : Image vers Vidéo",
|
||||
"api_veo2_i2v": "Veo2 Image vers Vidéo"
|
||||
}
|
||||
},
|
||||
"title": "Commencez avec un modèle"
|
||||
|
||||
@@ -4,6 +4,26 @@
|
||||
"title": "APIノード",
|
||||
"totalCost": "合計コスト"
|
||||
},
|
||||
"apiNodesNews": {
|
||||
"introducing": "紹介",
|
||||
"steps": {
|
||||
"step1": {
|
||||
"subtitle": "設定 > ユーザー > ログイン",
|
||||
"title": "ログイン/アカウント作成:"
|
||||
},
|
||||
"step2": {
|
||||
"subtitle": "設定 > クレジット > クレジットを購入",
|
||||
"title": "クレジットを購入:"
|
||||
},
|
||||
"step3": {
|
||||
"title": "「APIノード」セクションで新しいAPIノードを見つけてキャンバスに追加"
|
||||
},
|
||||
"step4": {
|
||||
"title": "実行!"
|
||||
}
|
||||
},
|
||||
"subtitle": "すべての外部モデルがComfyUIで利用可能になりました"
|
||||
},
|
||||
"apiNodesSignInDialog": {
|
||||
"message": "このワークフローにはAPIノードが含まれており、実行するためにはアカウントにサインインする必要があります。",
|
||||
"title": "APIノードを使用するためにはサインインが必要です"
|
||||
@@ -1090,6 +1110,23 @@
|
||||
"sdxl_simple_example": "SDXLシンプル",
|
||||
"sdxlturbo_example": "SDXLターボ"
|
||||
},
|
||||
"Image API": {
|
||||
"api-openai-dall-e-2-inpaint": "Dall-E 2 インペイント",
|
||||
"api-openai-dall-e-2-t2i": "Dall-E 2 テキストから画像へ",
|
||||
"api-openai-dall-e-3-t2i": "Dall-E 3 テキストから画像へ",
|
||||
"api_bfl_flux_pro_t2i": "BFL Flux[Pro] テキストから画像へ",
|
||||
"api_ideogram_v3_t2i": "Ideogram V3 テキストから画像へ",
|
||||
"api_luma_photon_i2i": "Luma Photon 画像から画像へ",
|
||||
"api_luma_photon_style_ref": "Luma Photon スタイル参照",
|
||||
"api_openai_image_1_i2i": "OpenAI Image-1 画像から画像へ",
|
||||
"api_openai_image_1_inpaint": "OpenAI Image-1 インペイント",
|
||||
"api_openai_image_1_multi_inputs": "OpenAI Image-1 複数入力",
|
||||
"api_openai_image_1_t2i": "OpenAI Image-1 テキストから画像へ",
|
||||
"api_recraft_image_gen_with_color_control": "Recraft カラーコントロール画像生成",
|
||||
"api_recraft_image_gen_with_style_control": "Recraft スタイルコントロール画像生成",
|
||||
"api_recraft_vector_gen": "Recraft ベクター生成",
|
||||
"api_stability_sd3_t2i": "Stability SD3 テキストから画像へ"
|
||||
},
|
||||
"Upscaling": {
|
||||
"esrgan_example": "ESRGAN",
|
||||
"hiresfix_esrgan_workflow": "HiresFix ESRGANワークフロー",
|
||||
@@ -1107,6 +1144,15 @@
|
||||
"txt_to_image_to_video": "テキストから画像へ、画像からビデオへ",
|
||||
"wan2_1_fun_control": "Wan 2.1 ControlNet",
|
||||
"wan2_1_fun_inp": "Wan 2.1 インペインティング"
|
||||
},
|
||||
"Video API": {
|
||||
"api_hailuo_minimax_i2v": "MiniMax 画像から動画へ",
|
||||
"api_kling_i2v": "Kling 画像から動画へ",
|
||||
"api_luma_i2v": "Luma 画像から動画へ",
|
||||
"api_pika_scene": "Pika シーン: 画像から動画へ",
|
||||
"api_pixverse_t2v": "PixVerse テキストから動画へ",
|
||||
"api_pixverse_template_i2v": "PixVerse テンプレート: 画像から動画へ",
|
||||
"api_veo2_i2v": "Veo2 画像から動画へ"
|
||||
}
|
||||
},
|
||||
"title": "テンプレートを利用して開始"
|
||||
|
||||
@@ -4,6 +4,26 @@
|
||||
"title": "API 노드(들)",
|
||||
"totalCost": "총 비용"
|
||||
},
|
||||
"apiNodesNews": {
|
||||
"introducing": "소개합니다",
|
||||
"steps": {
|
||||
"step1": {
|
||||
"subtitle": "설정 > 사용자 > 로그인",
|
||||
"title": "로그인/계정 생성:"
|
||||
},
|
||||
"step2": {
|
||||
"subtitle": "설정 > 크레딧 > 크레딧 구매",
|
||||
"title": "크레딧 구매:"
|
||||
},
|
||||
"step3": {
|
||||
"title": "'API Node' 섹션에서 새로운 API 노드를 찾아 캔버스에 추가하세요"
|
||||
},
|
||||
"step4": {
|
||||
"title": "실행!"
|
||||
}
|
||||
},
|
||||
"subtitle": "모든 외부 모델이 이제 ComfyUI에서 사용 가능합니다"
|
||||
},
|
||||
"apiNodesSignInDialog": {
|
||||
"message": "이 워크플로우에는 API 노드가 포함되어 있으며, 실행하려면 계정에 로그인해야 합니다.",
|
||||
"title": "API 노드 사용에 필요한 로그인"
|
||||
@@ -1090,6 +1110,23 @@
|
||||
"sdxl_simple_example": "간단한 SDXL 예제",
|
||||
"sdxlturbo_example": "SDXL 터보"
|
||||
},
|
||||
"Image API": {
|
||||
"api-openai-dall-e-2-inpaint": "Dall-E 2 인페인트",
|
||||
"api-openai-dall-e-2-t2i": "Dall-E 2 텍스트 투 이미지",
|
||||
"api-openai-dall-e-3-t2i": "Dall-E 3 텍스트 투 이미지",
|
||||
"api_bfl_flux_pro_t2i": "BFL Flux[Pro] 텍스트 투 이미지",
|
||||
"api_ideogram_v3_t2i": "Ideogram V3 텍스트 투 이미지",
|
||||
"api_luma_photon_i2i": "Luma Photon 이미지 투 이미지",
|
||||
"api_luma_photon_style_ref": "Luma Photon 스타일 참조",
|
||||
"api_openai_image_1_i2i": "OpenAI Image-1 이미지 투 이미지",
|
||||
"api_openai_image_1_inpaint": "OpenAI Image-1 인페인트",
|
||||
"api_openai_image_1_multi_inputs": "OpenAI Image-1 멀티 입력",
|
||||
"api_openai_image_1_t2i": "OpenAI Image-1 텍스트 투 이미지",
|
||||
"api_recraft_image_gen_with_color_control": "Recraft 색상 제어 이미지 생성",
|
||||
"api_recraft_image_gen_with_style_control": "Recraft 스타일 제어 이미지 생성",
|
||||
"api_recraft_vector_gen": "Recraft 벡터 생성",
|
||||
"api_stability_sd3_t2i": "Stability SD3 텍스트 투 이미지"
|
||||
},
|
||||
"Upscaling": {
|
||||
"esrgan_example": "ESRGAN",
|
||||
"hiresfix_esrgan_workflow": "HiresFix ESRGAN 워크플로우",
|
||||
@@ -1107,6 +1144,15 @@
|
||||
"txt_to_image_to_video": "텍스트 -> 이미지 -> 동영상",
|
||||
"wan2_1_fun_control": "Wan 2.1 컨트롤넷",
|
||||
"wan2_1_fun_inp": "Wan 2.1 인페인트"
|
||||
},
|
||||
"Video API": {
|
||||
"api_hailuo_minimax_i2v": "MiniMax 이미지 투 비디오",
|
||||
"api_kling_i2v": "Kling 이미지 투 비디오",
|
||||
"api_luma_i2v": "Luma 이미지 투 비디오",
|
||||
"api_pika_scene": "Pika 장면: 이미지 투 비디오",
|
||||
"api_pixverse_t2v": "PixVerse 텍스트 투 비디오",
|
||||
"api_pixverse_template_i2v": "PixVerse 템플릿: 이미지 투 비디오",
|
||||
"api_veo2_i2v": "Veo2 이미지 투 비디오"
|
||||
}
|
||||
},
|
||||
"title": "템플릿으로 시작하기"
|
||||
|
||||
@@ -4,6 +4,26 @@
|
||||
"title": "API Node(s)",
|
||||
"totalCost": "Общая стоимость"
|
||||
},
|
||||
"apiNodesNews": {
|
||||
"introducing": "Представляем",
|
||||
"steps": {
|
||||
"step1": {
|
||||
"subtitle": "Настройки > Пользователь > Войти",
|
||||
"title": "Войти/Создать аккаунт:"
|
||||
},
|
||||
"step2": {
|
||||
"subtitle": "Настройки > Кредиты > Купить кредиты",
|
||||
"title": "Купить кредиты:"
|
||||
},
|
||||
"step3": {
|
||||
"title": "Найдите новые API-узлы в разделе 'API Node' и добавьте их на холст"
|
||||
},
|
||||
"step4": {
|
||||
"title": "Запустить!"
|
||||
}
|
||||
},
|
||||
"subtitle": "Все внешние модели теперь доступны в ComfyUI"
|
||||
},
|
||||
"apiNodesSignInDialog": {
|
||||
"message": "Этот рабочий процесс содержит API Nodes, которые требуют входа в вашу учетную запись для выполнения.",
|
||||
"title": "Требуется вход для использования API Nodes"
|
||||
@@ -1090,6 +1110,23 @@
|
||||
"sdxl_simple_example": "SDXL Простой",
|
||||
"sdxlturbo_example": "SDXL Turbo"
|
||||
},
|
||||
"Image API": {
|
||||
"api-openai-dall-e-2-inpaint": "Dall-E 2: дорисовка",
|
||||
"api-openai-dall-e-2-t2i": "Dall-E 2: текст в изображение",
|
||||
"api-openai-dall-e-3-t2i": "Dall-E 3: текст в изображение",
|
||||
"api_bfl_flux_pro_t2i": "BFL Flux[Pro]: текст в изображение",
|
||||
"api_ideogram_v3_t2i": "Ideogram V3: текст в изображение",
|
||||
"api_luma_photon_i2i": "Luma Photon: изображение в изображение",
|
||||
"api_luma_photon_style_ref": "Luma Photon: стиль по образцу",
|
||||
"api_openai_image_1_i2i": "OpenAI Image-1: изображение в изображение",
|
||||
"api_openai_image_1_inpaint": "OpenAI Image-1: дорисовка",
|
||||
"api_openai_image_1_multi_inputs": "OpenAI Image-1: несколько входов",
|
||||
"api_openai_image_1_t2i": "OpenAI Image-1: текст в изображение",
|
||||
"api_recraft_image_gen_with_color_control": "Recraft: генерация изображения с управлением цветом",
|
||||
"api_recraft_image_gen_with_style_control": "Recraft: генерация изображения с управлением стилем",
|
||||
"api_recraft_vector_gen": "Recraft: генерация векторного изображения",
|
||||
"api_stability_sd3_t2i": "Stability SD3: текст в изображение"
|
||||
},
|
||||
"Upscaling": {
|
||||
"esrgan_example": "ESRGAN",
|
||||
"hiresfix_esrgan_workflow": "HiresFix ESRGAN Workflow",
|
||||
@@ -1107,6 +1144,15 @@
|
||||
"txt_to_image_to_video": "Текст в изображение в видео",
|
||||
"wan2_1_fun_control": "Wan 2.1 ControlNet",
|
||||
"wan2_1_fun_inp": "Wan 2.1 Inpainting"
|
||||
},
|
||||
"Video API": {
|
||||
"api_hailuo_minimax_i2v": "MiniMax: изображение в видео",
|
||||
"api_kling_i2v": "Kling: изображение в видео",
|
||||
"api_luma_i2v": "Luma: изображение в видео",
|
||||
"api_pika_scene": "Pika Scenes: изображения в видео",
|
||||
"api_pixverse_t2v": "PixVerse: текст в видео",
|
||||
"api_pixverse_template_i2v": "PixVerse Templates: изображение в видео",
|
||||
"api_veo2_i2v": "Veo2: изображение в видео"
|
||||
}
|
||||
},
|
||||
"title": "Начните с шаблона"
|
||||
|
||||
@@ -4,6 +4,26 @@
|
||||
"title": "API节点",
|
||||
"totalCost": "总成本"
|
||||
},
|
||||
"apiNodesNews": {
|
||||
"introducing": "介绍",
|
||||
"steps": {
|
||||
"step1": {
|
||||
"subtitle": "设置 > 用户 > 登录",
|
||||
"title": "登录/创建账户:"
|
||||
},
|
||||
"step2": {
|
||||
"subtitle": "设置 > 积分 > 购买积分",
|
||||
"title": "购买积分:"
|
||||
},
|
||||
"step3": {
|
||||
"title": "在“API 节点”部分找到新的 API 节点并添加到画布"
|
||||
},
|
||||
"step4": {
|
||||
"title": "运行!"
|
||||
}
|
||||
},
|
||||
"subtitle": "所有外部模型现已在 ComfyUI 中可用"
|
||||
},
|
||||
"apiNodesSignInDialog": {
|
||||
"message": "此工作流包含API节点,需要您登录账户才能运行。",
|
||||
"title": "使用API节点需要登录"
|
||||
@@ -1090,6 +1110,23 @@
|
||||
"sdxl_simple_example": "SDXL简单",
|
||||
"sdxlturbo_example": "SDXL Turbo"
|
||||
},
|
||||
"Image API": {
|
||||
"api-openai-dall-e-2-inpaint": "Dall-E 2 局部修复",
|
||||
"api-openai-dall-e-2-t2i": "Dall-E 2 文生图",
|
||||
"api-openai-dall-e-3-t2i": "Dall-E 3 文生图",
|
||||
"api_bfl_flux_pro_t2i": "BFL Flux[Pro] 文生图",
|
||||
"api_ideogram_v3_t2i": "Ideogram V3 文生图",
|
||||
"api_luma_photon_i2i": "Luma Photon 图生图",
|
||||
"api_luma_photon_style_ref": "Luma Photon 风格参考",
|
||||
"api_openai_image_1_i2i": "OpenAI Image-1 图生图",
|
||||
"api_openai_image_1_inpaint": "OpenAI Image-1 局部修复",
|
||||
"api_openai_image_1_multi_inputs": "OpenAI Image-1 多输入",
|
||||
"api_openai_image_1_t2i": "OpenAI Image-1 文生图",
|
||||
"api_recraft_image_gen_with_color_control": "Recraft 颜色控制图像生成",
|
||||
"api_recraft_image_gen_with_style_control": "Recraft 风格控制图像生成",
|
||||
"api_recraft_vector_gen": "Recraft 矢量生成",
|
||||
"api_stability_sd3_t2i": "Stability SD3 文生图"
|
||||
},
|
||||
"Upscaling": {
|
||||
"esrgan_example": "ESRGAN",
|
||||
"hiresfix_esrgan_workflow": "HiresFix ESRGAN工作流",
|
||||
@@ -1107,6 +1144,15 @@
|
||||
"txt_to_image_to_video": "文本到图像到视频",
|
||||
"wan2_1_fun_control": "Wan 2.1 ControlNet",
|
||||
"wan2_1_fun_inp": "Wan 2.1 图像修复"
|
||||
},
|
||||
"Video API": {
|
||||
"api_hailuo_minimax_i2v": "MiniMax 图生视频",
|
||||
"api_kling_i2v": "Kling 图生视频",
|
||||
"api_luma_i2v": "Luma 图生视频",
|
||||
"api_pika_scene": "Pika 场景:图转视频",
|
||||
"api_pixverse_t2v": "PixVerse 文转视频",
|
||||
"api_pixverse_template_i2v": "PixVerse 模板:图转视频",
|
||||
"api_veo2_i2v": "Veo2 图生视频"
|
||||
}
|
||||
},
|
||||
"title": "从模板开始"
|
||||
|
||||
@@ -267,6 +267,15 @@ export const addWidget = <W extends BaseDOMWidget<object | string>>(
|
||||
widget: W
|
||||
) => {
|
||||
node.addCustomWidget(widget)
|
||||
|
||||
if (node.graph) {
|
||||
useDomWidgetStore().registerWidget(widget)
|
||||
}
|
||||
|
||||
node.onAdded = useChainCallback(node.onAdded, () => {
|
||||
useDomWidgetStore().registerWidget(widget)
|
||||
})
|
||||
|
||||
node.onRemoved = useChainCallback(node.onRemoved, () => {
|
||||
widget.onRemove?.()
|
||||
})
|
||||
@@ -275,8 +284,6 @@ export const addWidget = <W extends BaseDOMWidget<object | string>>(
|
||||
widget.options.beforeResize?.call(widget, node)
|
||||
widget.options.afterResize?.call(widget, node)
|
||||
})
|
||||
|
||||
useDomWidgetStore().registerWidget(widget)
|
||||
}
|
||||
|
||||
LGraphNode.prototype.addDOMWidget = function <
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import ApiNodesNewsContent from '@/components/dialog/content/ApiNodesNewsContent.vue'
|
||||
import ApiNodesSignInContent from '@/components/dialog/content/ApiNodesSignInContent.vue'
|
||||
import ConfirmationDialogContent from '@/components/dialog/content/ConfirmationDialogContent.vue'
|
||||
import ErrorDialogContent from '@/components/dialog/content/ErrorDialogContent.vue'
|
||||
@@ -379,6 +380,32 @@ export const useDialogService = () => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a dialog for the API nodes news.
|
||||
* TODO: Remove the news dialog on next major feature release.
|
||||
*/
|
||||
function showApiNodesNewsDialog() {
|
||||
if (localStorage.getItem('api-nodes-news-seen') === 'true') {
|
||||
return
|
||||
}
|
||||
|
||||
return dialogStore.showDialog({
|
||||
key: 'api-nodes-news',
|
||||
component: ApiNodesNewsContent,
|
||||
props: {
|
||||
onClose: () => {
|
||||
dialogStore.closeDialog({ key: 'api-nodes-news' })
|
||||
localStorage.setItem('api-nodes-news-seen', 'true')
|
||||
}
|
||||
},
|
||||
dialogComponentProps: {
|
||||
closable: false,
|
||||
modal: false,
|
||||
position: 'bottomright'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
showLoadWorkflowWarning,
|
||||
showMissingModelsWarning,
|
||||
@@ -394,6 +421,7 @@ export const useDialogService = () => {
|
||||
showSignInDialog,
|
||||
showTopUpCreditsDialog,
|
||||
showUpdatePasswordDialog,
|
||||
showApiNodesNewsDialog,
|
||||
prompt,
|
||||
confirm
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
type IContextMenuValue,
|
||||
LGraphCanvas,
|
||||
LGraphEventMode,
|
||||
LGraphNode,
|
||||
LiteGraph,
|
||||
@@ -79,6 +80,13 @@ export const useLitegraphService = () => {
|
||||
this.#addOutputs(ComfyNode.nodeData.outputs)
|
||||
this.#setInitialSize()
|
||||
this.serialize_widgets = true
|
||||
|
||||
// Mark API Nodes yellow by default to distinguish with other nodes.
|
||||
if (ComfyNode.nodeData.api_node) {
|
||||
this.color = LGraphCanvas.node_colors.yellow.color
|
||||
this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor
|
||||
}
|
||||
|
||||
void extensionService.invokeExtensionsAsync('nodeCreated', this)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,20 @@ export const useWorkflowTemplatesStore = defineStore(
|
||||
const isLoaded = ref(false)
|
||||
|
||||
/**
|
||||
* Sort a list of templates in alphabetical order by name.
|
||||
* Sort a list of templates in alphabetical order by localized display name.
|
||||
*/
|
||||
const sortTemplateList = (templates: TemplateInfo[]) =>
|
||||
templates.sort((a, b) => a.name.localeCompare(b.name))
|
||||
templates.sort((a, b) => {
|
||||
const aName = st(
|
||||
`templateWorkflows.name.${normalizeI18nKey(a.name)}`,
|
||||
a.title ?? a.name
|
||||
)
|
||||
const bName = st(
|
||||
`templateWorkflows.name.${normalizeI18nKey(b.name)}`,
|
||||
b.name
|
||||
)
|
||||
return aName.localeCompare(bName)
|
||||
})
|
||||
|
||||
/**
|
||||
* Sort any template categories (grouped templates) that should be sorted.
|
||||
|
||||
@@ -42,6 +42,7 @@ import { StatusWsMessageStatus } from '@/schemas/apiSchema'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
import { setupAutoQueueHandler } from '@/services/autoQueueService'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useKeybindingService } from '@/services/keybindingService'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
import { useExecutionStore } from '@/stores/executionStore'
|
||||
@@ -241,6 +242,8 @@ const onGraphReady = () => {
|
||||
// Explicitly initialize nodeSearchService to avoid indexing delay when
|
||||
// node search is triggered
|
||||
useNodeDefStore().nodeSearchService.searchNode('')
|
||||
|
||||
useDialogService().showApiNodesNewsDialog()
|
||||
},
|
||||
{ timeout: 1000 }
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user