mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 19:09:52 +00:00
Linear mode bug fixes (#8054)
┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8054-Linear-mode-bug-fixes-2e86d73d365081ed8d75d6e2af679f6c) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
variant="textonly"
|
||||
@click="toggleHelpCenter"
|
||||
>
|
||||
{{ $t('menu.helpAndFeedback') }}
|
||||
<div class="not-md:hidden">{{ $t('menu.helpAndFeedback') }}</div>
|
||||
<i class="icon-[lucide--circle-help] ml-0.5" />
|
||||
<span
|
||||
v-if="shouldShowRedDot"
|
||||
|
||||
@@ -1234,7 +1234,7 @@ export function useCoreCommands(): ComfyCommand[] {
|
||||
{
|
||||
id: 'Comfy.ToggleLinear',
|
||||
icon: 'pi pi-database',
|
||||
label: 'toggle linear mode',
|
||||
label: 'Toggle Simple Mode',
|
||||
function: () => {
|
||||
const newMode = !canvasStore.linearMode
|
||||
app.rootGraph.extra.linearMode = newMode
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
"label": "Help Center"
|
||||
},
|
||||
"Comfy_ToggleLinear": {
|
||||
"label": "toggle linear mode"
|
||||
"label": "Toggle Simple Mode"
|
||||
},
|
||||
"Comfy_ToggleQPOV2": {
|
||||
"label": "Toggle Queue Panel V2"
|
||||
|
||||
@@ -1187,7 +1187,7 @@
|
||||
"Experimental: Enable AssetAPI": "Experimental: Enable AssetAPI",
|
||||
"Canvas Performance": "Canvas Performance",
|
||||
"Help Center": "Help Center",
|
||||
"toggle linear mode": "toggle simple mode",
|
||||
"toggle linear mode": "Toggle Simple Mode",
|
||||
"Toggle Queue Panel V2": "Toggle Queue Panel V2",
|
||||
"Toggle Theme (Dark/Light)": "Toggle Theme (Dark/Light)",
|
||||
"Undo": "Undo",
|
||||
@@ -2494,7 +2494,7 @@
|
||||
"linearMode": "Simple Mode",
|
||||
"beta": "Beta - Give Feedback",
|
||||
"graphMode": "Graph Mode",
|
||||
"dragAndDropImage": "Drag and drop an image",
|
||||
"dragAndDropImage": "Click to browse or drag an image",
|
||||
"runCount": "Run count:",
|
||||
"rerun": "Rerun",
|
||||
"reuseParameters": "Reuse Parameters",
|
||||
|
||||
@@ -23,6 +23,7 @@ import { useCommandStore } from '@/stores/commandStore'
|
||||
import { useExecutionStore } from '@/stores/executionStore'
|
||||
import { useQueueSettingsStore } from '@/stores/queueStore'
|
||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const commandStore = useCommandStore()
|
||||
const executionStore = useExecutionStore()
|
||||
@@ -55,13 +56,16 @@ function nodeToNodeData(node: LGraphNode) {
|
||||
? undefined
|
||||
: {
|
||||
iconClass: 'icon-[lucide--image]',
|
||||
label: t('linearMode.dragAndDropImage')
|
||||
label: t('linearMode.dragAndDropImage'),
|
||||
onClick: () => node.widgets?.[1]?.callback?.(undefined)
|
||||
}
|
||||
const nodeData = extractVueNodeData(node)
|
||||
for (const widget of nodeData.widgets ?? []) widget.slotMetadata = undefined
|
||||
|
||||
return {
|
||||
...nodeData,
|
||||
//note lastNodeErrors uses exeuctionid, node.id is execution for root
|
||||
hasErrors: !!executionStore.lastNodeErrors?.[node.id],
|
||||
|
||||
dropIndicator,
|
||||
onDragDrop: node.onDragDrop,
|
||||
@@ -69,13 +73,18 @@ function nodeToNodeData(node: LGraphNode) {
|
||||
}
|
||||
}
|
||||
const partitionedNodes = computed(() => {
|
||||
return partition(
|
||||
const parts = partition(
|
||||
graphNodes.value
|
||||
.filter((node) => node.mode === 0 && node.widgets?.length)
|
||||
.map(nodeToNodeData)
|
||||
.reverse(),
|
||||
(node) => ['MarkdownNote', 'Note'].includes(node.type)
|
||||
)
|
||||
for (const noteNode of parts[0]) {
|
||||
for (const widget of noteNode.widgets ?? [])
|
||||
widget.options = { ...widget.options, read_only: true }
|
||||
}
|
||||
return parts
|
||||
})
|
||||
|
||||
const batchCountWidget: SimplifiedWidget<number> = {
|
||||
@@ -165,7 +174,7 @@ defineExpose({ runButtonClick })
|
||||
<Popover
|
||||
v-if="partitionedNodes[0].length"
|
||||
align="start"
|
||||
class="overflow-y-auto overflow-x-clip max-h-(--reka-popover-content-available-height)"
|
||||
class="overflow-y-auto overflow-x-clip max-h-(--reka-popover-content-available-height) z-100"
|
||||
:reference="notesTo"
|
||||
side="left"
|
||||
:to="notesTo"
|
||||
@@ -217,7 +226,13 @@ defineExpose({ runButtonClick })
|
||||
>
|
||||
<NodeWidgets
|
||||
:node-data
|
||||
class="py-3 gap-y-4 **:[.col-span-2]:grid-cols-1 text-sm **:[.p-floatlabel]:h-35 rounded-lg"
|
||||
:class="
|
||||
cn(
|
||||
'py-3 gap-y-3 **:[.col-span-2]:grid-cols-1 not-has-[textarea]:flex-0 rounded-lg',
|
||||
nodeData.hasErrors &&
|
||||
'ring-2 ring-inset ring-node-stroke-error'
|
||||
)
|
||||
"
|
||||
:style="{ background: applyLightThemeColor(nodeData.bgcolor) }"
|
||||
/>
|
||||
</DropZone>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { downloadFile } from '@/base/common/downloadUtil'
|
||||
import Load3dViewerContent from '@/components/load3d/Load3dViewerContent.vue'
|
||||
import Popover from '@/components/ui/Popover.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { d, t } from '@/i18n'
|
||||
@@ -12,6 +11,7 @@ import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
|
||||
import { extractWorkflowFromAsset } from '@/platform/workflow/utils/workflowExtractionUtil'
|
||||
import ImagePreview from '@/renderer/extensions/linearMode/ImagePreview.vue'
|
||||
import Preview3d from '@/renderer/extensions/linearMode/Preview3d.vue'
|
||||
import VideoPreview from '@/renderer/extensions/linearMode/VideoPreview.vue'
|
||||
import {
|
||||
getMediaType,
|
||||
@@ -172,7 +172,7 @@ async function rerun(e: Event) {
|
||||
class="w-full max-w-128 m-auto my-12 overflow-y-auto"
|
||||
v-text="selectedOutput!.url"
|
||||
/>
|
||||
<Load3dViewerContent
|
||||
<Preview3d
|
||||
v-else-if="getMediaType(selectedOutput) === '3d'"
|
||||
:model-url="selectedOutput!.url"
|
||||
/>
|
||||
|
||||
@@ -277,6 +277,7 @@ useEventListener(document.body, 'keydown', (e: KeyboardEvent) => {
|
||||
'border-2'
|
||||
)
|
||||
"
|
||||
@click="selectedIndex = [index, key]"
|
||||
>
|
||||
<i
|
||||
:class="
|
||||
|
||||
44
src/renderer/extensions/linearMode/Preview3d.vue
Normal file
44
src/renderer/extensions/linearMode/Preview3d.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
import { useTemplateRef, watch } from 'vue'
|
||||
|
||||
import AnimationControls from '@/components/load3d/controls/AnimationControls.vue'
|
||||
import { useLoad3dViewer } from '@/composables/useLoad3dViewer'
|
||||
|
||||
const { modelUrl } = defineProps<{
|
||||
modelUrl: string
|
||||
}>()
|
||||
|
||||
const containerRef = useTemplateRef('containerRef')
|
||||
|
||||
const viewer = useLoad3dViewer()
|
||||
|
||||
watch([containerRef, () => modelUrl], async () => {
|
||||
if (!containerRef.value || !modelUrl) return
|
||||
|
||||
await viewer.initializeStandaloneViewer(containerRef.value, modelUrl)
|
||||
})
|
||||
|
||||
//TODO: refactor to add control buttons
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
ref="containerRef"
|
||||
class="relative w-full h-full"
|
||||
@mouseenter="viewer.handleMouseEnter"
|
||||
@mouseleave="viewer.handleMouseLeave"
|
||||
@resize="viewer.handleResize"
|
||||
>
|
||||
<div class="pointer-events-none absolute top-0 left-0 size-full">
|
||||
<AnimationControls
|
||||
v-if="viewer.animations.value && viewer.animations.value.length > 0"
|
||||
v-model:animations="viewer.animations.value"
|
||||
v-model:playing="viewer.playing.value"
|
||||
v-model:selected-speed="viewer.selectedSpeed.value"
|
||||
v-model:selected-animation="viewer.selectedAnimation.value"
|
||||
v-model:animation-progress="viewer.animationProgress.value"
|
||||
v-model:animation-duration="viewer.animationDuration.value"
|
||||
@seek="viewer.handleSeek"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -44,7 +44,10 @@ const bottomRightRef = useTemplateRef('bottomRightRef')
|
||||
const linearWorkflowRef = useTemplateRef('linearWorkflowRef')
|
||||
</script>
|
||||
<template>
|
||||
<div class="absolute w-full h-full">
|
||||
<div
|
||||
class="absolute w-full h-full"
|
||||
@wheel.capture="(e: WheelEvent) => outputHistoryRef?.onWheel(e)"
|
||||
>
|
||||
<div class="workflow-tabs-container pointer-events-auto h-9.5 w-full">
|
||||
<div class="flex h-full items-center">
|
||||
<WorkflowTabs />
|
||||
@@ -82,7 +85,10 @@ const linearWorkflowRef = useTemplateRef('linearWorkflowRef')
|
||||
/>
|
||||
<LinearControls ref="linearWorkflowRef" mobile />
|
||||
<div class="text-base-foreground flex items-center gap-4 justify-end m-4">
|
||||
<div v-text="t('linearMode.beta')" />
|
||||
<a
|
||||
href="https://form.typeform.com/to/gmVqFi8l"
|
||||
v-text="t('linearMode.beta')"
|
||||
/>
|
||||
<TypeformPopoverButton data-tf-widget="gmVqFi8l" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,7 +128,6 @@ const linearWorkflowRef = useTemplateRef('linearWorkflowRef')
|
||||
id="linearCenterPanel"
|
||||
:size="98"
|
||||
class="flex flex-col min-w-min gap-4 mx-2 px-10 pt-8 pb-4 relative text-muted-foreground outline-none"
|
||||
@wheel.capture="(e: WheelEvent) => outputHistoryRef?.onWheel(e)"
|
||||
>
|
||||
<LinearPreview
|
||||
:latent-preview="
|
||||
|
||||
Reference in New Issue
Block a user