mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-23 16:24:06 +00:00
Merge remote-tracking branch 'origin/main' into feat/new-workflow-templates
This commit is contained in:
@@ -118,7 +118,7 @@ const sortedGroups = (category: SettingTreeNode): ISettingGroup[] => {
|
||||
}
|
||||
|
||||
const handleSearch = (query: string) => {
|
||||
handleSearchBase(query)
|
||||
handleSearchBase(query.trim())
|
||||
activeCategory.value = query ? null : defaultCategory.value
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<template>
|
||||
<Transition name="slide-up">
|
||||
<!-- Wrapping panel in div to get correct ref because panel ref is not of raw dom el -->
|
||||
<div
|
||||
v-show="visible"
|
||||
ref="toolboxRef"
|
||||
style="
|
||||
transform: translate(calc(var(--tb-x) - 50%), calc(var(--tb-y) - 120%));
|
||||
"
|
||||
class="selection-toolbox fixed left-0 top-0 z-40"
|
||||
>
|
||||
<div
|
||||
ref="toolboxRef"
|
||||
style="transform: translate(var(--tb-x), var(--tb-y))"
|
||||
class="fixed left-0 top-0 z-40"
|
||||
>
|
||||
<Transition name="slide-up">
|
||||
<Panel
|
||||
class="rounded-lg"
|
||||
v-if="visible"
|
||||
class="rounded-lg selection-toolbox"
|
||||
:pt="{
|
||||
header: 'hidden',
|
||||
content: 'p-0 flex flex-row'
|
||||
@@ -33,8 +30,8 @@
|
||||
/>
|
||||
<HelpButton />
|
||||
</Panel>
|
||||
</div>
|
||||
</Transition>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -84,22 +81,31 @@ const extensionToolboxCommands = computed<ComfyCommandImpl[]>(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.selection-toolbox {
|
||||
transform: translateX(-50%) translateY(-120%);
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateX(-50%) translateY(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: translateX(-50%) translateY(-125%);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-50%) translateY(-120%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-up-enter-active {
|
||||
opacity: 1;
|
||||
transition: all 0.3s ease-out;
|
||||
animation: slideUp 125ms ease-out;
|
||||
}
|
||||
|
||||
.slide-up-leave-active {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.slide-up-enter-from {
|
||||
transform: translateY(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.slide-up-leave-to {
|
||||
transform: translateY(0);
|
||||
opacity: 0;
|
||||
animation: slideUp 25ms ease-out reverse;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -136,8 +136,6 @@ const closePopup = async () => {
|
||||
hide()
|
||||
}
|
||||
|
||||
// Learn more handled by anchor href
|
||||
|
||||
// const handleCTA = async () => {
|
||||
// window.open('https://docs.comfy.org/installation/update_comfyui', '_blank')
|
||||
// await closePopup()
|
||||
@@ -161,8 +159,10 @@ defineExpose({
|
||||
<style scoped>
|
||||
/* Popup container - positioning handled by parent */
|
||||
.whats-new-popup-container {
|
||||
--whats-new-popup-bottom: 1rem;
|
||||
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
bottom: var(--whats-new-popup-bottom);
|
||||
z-index: 1000;
|
||||
pointer-events: auto;
|
||||
}
|
||||
@@ -171,8 +171,8 @@ defineExpose({
|
||||
.help-center-arrow {
|
||||
position: absolute;
|
||||
bottom: calc(
|
||||
var(--sidebar-width, 4rem) + 0.25rem
|
||||
); /* Position toward center of help center icon */
|
||||
var(--sidebar-width) * 2 + var(--sidebar-width) / 2
|
||||
); /* Position to center of help center icon (2 icons below + half icon height for center) */
|
||||
transform: none;
|
||||
z-index: 999;
|
||||
pointer-events: none;
|
||||
@@ -185,7 +185,10 @@ defineExpose({
|
||||
|
||||
.whats-new-popup-container.sidebar-left.small-sidebar .help-center-arrow {
|
||||
left: -14px; /* Overlap with popup outline */
|
||||
bottom: calc(2.5rem + 0.25rem); /* Adjust for small sidebar */
|
||||
bottom: calc(
|
||||
var(--sidebar-width) * 2 + var(--sidebar-icon-size) / 2 -
|
||||
var(--whats-new-popup-bottom)
|
||||
); /* Position to center of help center icon (2 icons below + half icon height for center - whats new popup bottom position ) */
|
||||
}
|
||||
|
||||
/* Sidebar positioning classes applied by parent */
|
||||
|
||||
@@ -76,6 +76,22 @@ const getTabTooltipSuffix = (tab: SidebarTabExtension) => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Global CSS variables for sidebar
|
||||
* These variables need to be global (not scoped) because they are used by
|
||||
* teleported components like WhatsNewPopup that render outside the sidebar
|
||||
* but need to reference sidebar dimensions for proper positioning.
|
||||
*/
|
||||
:root {
|
||||
--sidebar-width: 4rem;
|
||||
--sidebar-icon-size: 1rem;
|
||||
}
|
||||
|
||||
:root:has(.side-tool-bar-container.small-sidebar) {
|
||||
--sidebar-width: 2.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.side-tool-bar-container {
|
||||
display: flex;
|
||||
@@ -88,9 +104,6 @@ const getTabTooltipSuffix = (tab: SidebarTabExtension) => {
|
||||
background-color: var(--comfy-menu-secondary-bg);
|
||||
color: var(--fg-color);
|
||||
box-shadow: var(--bar-shadow);
|
||||
|
||||
--sidebar-width: 4rem;
|
||||
--sidebar-icon-size: 1rem;
|
||||
}
|
||||
|
||||
.side-tool-bar-container.small-sidebar {
|
||||
|
||||
@@ -1332,6 +1332,9 @@ const apiNodeCosts: Record<string, { displayPrice: string | PricingFunction }> =
|
||||
return 'Token-based'
|
||||
}
|
||||
},
|
||||
GeminiImageNode: {
|
||||
displayPrice: '$0.03 per 1K tokens'
|
||||
},
|
||||
// OpenAI nodes
|
||||
OpenAIChatNode: {
|
||||
displayPrice: (node: LGraphNode): string => {
|
||||
|
||||
@@ -446,6 +446,9 @@ export function useCoreCommands(): ComfyCommand[] {
|
||||
)
|
||||
group.resizeTo(canvas.selectedItems, padding)
|
||||
canvas.graph?.add(group)
|
||||
|
||||
group.recomputeInsideNodes()
|
||||
|
||||
useTitleEditorStore().titleEditorTarget = group
|
||||
}
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ export const CORE_MENU_COMMANDS = [
|
||||
],
|
||||
[['Edit'], ['Comfy.Undo', 'Comfy.Redo']],
|
||||
[['Edit'], ['Comfy.OpenClipspace']],
|
||||
[['Edit'], ['Comfy.RefreshNodeDefinitions']],
|
||||
[
|
||||
['Help'],
|
||||
[
|
||||
|
||||
@@ -42,6 +42,8 @@ app.registerExtension({
|
||||
this.graph.add(group)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.graph.change()
|
||||
|
||||
group.recomputeInsideNodes()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
# Bash commands
|
||||
|
||||
- `npm run typecheck` Run the typechecker
|
||||
- `npm run build` Build the project
|
||||
- `npm run lint:fix` Run ESLint
|
||||
- `pnpm typecheck` Run the typechecker
|
||||
- `pnpm build` Build the project
|
||||
- `pnpm lint:fix` Run ESLint
|
||||
|
||||
# Code style
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ Use GitHub actions to release normal versions.
|
||||
|
||||
### Pre-release
|
||||
|
||||
The action directly translates `Version increment type` to the npm version command. `Pre-release ID (suffix)` is the option for the `--preid` argument.
|
||||
The action directly translates `Version increment type` to the pnpm version command. `Pre-release ID (suffix)` is the option for the `--preid` argument.
|
||||
|
||||
e.g. Use `prerelease` increment type to automatically bump the patch version and create a pre-release version. Subsequent runs of prerelease will update the prerelease version only.
|
||||
Use `patch` when ready to remove the pre-release suffix.
|
||||
|
||||
@@ -79,19 +79,20 @@ const messages = {
|
||||
#### Option A: Local Generation (Optional)
|
||||
```bash
|
||||
# Only if you have OpenAI API key configured
|
||||
npm run locale
|
||||
pnpm locale
|
||||
```
|
||||
|
||||
#### Option B: Let CI Handle It (Recommended)
|
||||
- Create your PR with the configuration changes above
|
||||
- Our GitHub CI will automatically generate translation files
|
||||
- Empty JSON files are fine - they'll be populated by the workflow
|
||||
- **Important**: Translation files will be generated during release PRs, not feature PRs
|
||||
- Empty JSON files are fine - they'll be populated during the next release workflow
|
||||
- For urgent translation needs, maintainers can manually trigger the workflow
|
||||
|
||||
### Step 3: Test Your Changes
|
||||
|
||||
```bash
|
||||
npm run typecheck # Check for TypeScript errors
|
||||
npm run dev # Start development server
|
||||
pnpm typecheck # Check for TypeScript errors
|
||||
pnpm dev # Start development server
|
||||
```
|
||||
|
||||
**Testing checklist:**
|
||||
@@ -110,11 +111,23 @@ npm run dev # Start development server
|
||||
|
||||
## What Happens in CI
|
||||
|
||||
Our automated translation workflow:
|
||||
Our automated translation workflow now runs on release PRs (version-bump-* branches) to improve development performance:
|
||||
|
||||
### For Feature PRs (Regular Development)
|
||||
- **No automatic translations** - faster reviews and fewer conflicts
|
||||
- **English-only development** - new strings show in English until release
|
||||
- **Focus on functionality** - reviewers see only your actual changes
|
||||
|
||||
### For Release PRs (version-bump-* branches)
|
||||
1. **Collects strings**: Scans the UI for translatable text
|
||||
2. **Updates English files**: Ensures all strings are captured
|
||||
2. **Updates English files**: Ensures all strings are captured
|
||||
3. **Generates translations**: Uses OpenAI API to translate to all configured languages
|
||||
4. **Commits back**: Automatically updates your PR with complete translations
|
||||
4. **Commits back**: Automatically updates the release PR with complete translations
|
||||
|
||||
### Manual Translation Updates
|
||||
If urgent translation updates are needed outside of releases, maintainers can:
|
||||
- Trigger the "Update Locales" workflow manually from GitHub Actions
|
||||
- The workflow supports manual dispatch for emergency translation updates
|
||||
|
||||
## File Structure
|
||||
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "تم رفض إذن الميكروفون",
|
||||
"migrate": "ترحيل",
|
||||
"missing": "مفقود",
|
||||
"moreWorkflows": "المزيد من سير العمل",
|
||||
"name": "الاسم",
|
||||
"newFolder": "مجلد جديد",
|
||||
"next": "التالي",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "Permiso de micrófono denegado",
|
||||
"migrate": "Migrar",
|
||||
"missing": "Faltante",
|
||||
"moreWorkflows": "Más flujos de trabajo",
|
||||
"name": "Nombre",
|
||||
"newFolder": "Nueva carpeta",
|
||||
"next": "Siguiente",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "Permission du microphone refusée",
|
||||
"migrate": "Migrer",
|
||||
"missing": "Manquant",
|
||||
"moreWorkflows": "Plus de workflows",
|
||||
"name": "Nom",
|
||||
"newFolder": "Nouveau dossier",
|
||||
"next": "Suivant",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "マイクの許可が拒否されました",
|
||||
"migrate": "移行する",
|
||||
"missing": "不足している",
|
||||
"moreWorkflows": "さらに多くのワークフロー",
|
||||
"name": "名前",
|
||||
"newFolder": "新しいフォルダー",
|
||||
"next": "次へ",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "마이크 권한이 거부되었습니다",
|
||||
"migrate": "이전(migrate)",
|
||||
"missing": "누락됨",
|
||||
"moreWorkflows": "더 많은 워크플로우",
|
||||
"name": "이름",
|
||||
"newFolder": "새 폴더",
|
||||
"next": "다음",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "Доступ к микрофону запрещён",
|
||||
"migrate": "Мигрировать",
|
||||
"missing": "Отсутствует",
|
||||
"moreWorkflows": "Больше рабочих процессов",
|
||||
"name": "Имя",
|
||||
"newFolder": "Новая папка",
|
||||
"next": "Далее",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "麥克風權限被拒絕",
|
||||
"migrate": "遷移",
|
||||
"missing": "缺少",
|
||||
"moreWorkflows": "更多工作流程",
|
||||
"name": "名稱",
|
||||
"newFolder": "新資料夾",
|
||||
"next": "下一步",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"micPermissionDenied": "麦克风权限被拒绝",
|
||||
"migrate": "迁移",
|
||||
"missing": "缺失",
|
||||
"moreWorkflows": "更多工作流",
|
||||
"name": "名称",
|
||||
"newFolder": "新文件夹",
|
||||
"next": "下一个",
|
||||
|
||||
@@ -63,6 +63,7 @@ import { ExtensionManager } from '@/types/extensionTypes'
|
||||
import type { NodeExecutionId } from '@/types/nodeIdentification'
|
||||
import { ColorAdjustOptions, adjustColor } from '@/utils/colorUtil'
|
||||
import { graphToPrompt } from '@/utils/executionUtil'
|
||||
import { forEachNode } from '@/utils/graphTraversalUtil'
|
||||
import {
|
||||
getNodeByExecutionId,
|
||||
triggerCallbackOnAllNodes
|
||||
@@ -1700,12 +1701,13 @@ export class ComfyApp {
|
||||
for (const nodeId in defs) {
|
||||
this.registerNodeDef(nodeId, defs[nodeId])
|
||||
}
|
||||
for (const node of this.graph.nodes) {
|
||||
// Refresh combo widgets in all nodes including those in subgraphs
|
||||
forEachNode(this.graph, (node) => {
|
||||
const def = defs[node.type]
|
||||
// Allow primitive nodes to handle refresh
|
||||
node.refreshComboInNode?.(defs)
|
||||
|
||||
if (!def?.input) continue
|
||||
if (!def?.input) return
|
||||
|
||||
if (node.widgets) {
|
||||
const nodeInputs = def.input
|
||||
@@ -1732,7 +1734,7 @@ export class ComfyApp {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
await useExtensionService().invokeExtensionsAsync(
|
||||
'refreshComboInNodes',
|
||||
|
||||
Reference in New Issue
Block a user