From 83ffaf30c831ecda4a375ed2912fa74849bd74a1 Mon Sep 17 00:00:00 2001 From: AustinMroz Date: Sat, 7 Mar 2026 14:22:15 -0800 Subject: [PATCH] Yet further app fixes (#9523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Prevent selection of note nodes - Prevents selection of nodes with errors - A bit broader than the reported "can select missing nodes". A node with an error is a node that can not execute and thus can not be used in an app. - Updates the typeform survey - Add a collapsible list of all api nodes(/prices) contained in an app. - Needs to be prettied up for mobile still. image ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9523-Yet-further-app-fixes-31c6d73d365081de9150fbf2d3ec54dd) by [Unito](https://www.unito.io) --- src/components/builder/AppBuilder.vue | 12 ++- src/locales/en/main.json | 1 + .../extensions/linearMode/AppOutput.vue | 2 +- .../extensions/linearMode/LinearControls.vue | 51 ++--------- .../extensions/linearMode/PartnerNodeItem.vue | 14 +++ .../linearMode/PartnerNodesList.vue | 85 +++++++++++++++++++ .../vueNodes/components/LGraphNode.vue | 7 +- .../vueNodes/components/NodeWidgets.vue | 7 +- .../composables/usePartitionedBadges.ts | 52 ++++++++++++ src/stores/appModeStore.ts | 4 + src/views/LinearView.vue | 2 +- 11 files changed, 180 insertions(+), 57 deletions(-) create mode 100644 src/renderer/extensions/linearMode/PartnerNodeItem.vue create mode 100644 src/renderer/extensions/linearMode/PartnerNodesList.vue diff --git a/src/components/builder/AppBuilder.vue b/src/components/builder/AppBuilder.vue index 1b1dedb80c..d14d30f31e 100644 --- a/src/components/builder/AppBuilder.vue +++ b/src/components/builder/AppBuilder.vue @@ -27,7 +27,7 @@ import { app } from '@/scripts/app' import { DOMWidgetImpl } from '@/scripts/domWidget' import { useDialogService } from '@/services/dialogService' import { useAppMode } from '@/composables/useAppMode' -import { useAppModeStore } from '@/stores/appModeStore' +import { nodeTypeValidForApp, useAppModeStore } from '@/stores/appModeStore' import { resolveNode } from '@/utils/litegraphUtil' import { cn } from '@/utils/tailwindUtil' import { HideLayoutFieldKey } from '@/types/widgetTypes' @@ -162,7 +162,11 @@ function handleDown(e: MouseEvent) { } function handleClick(e: MouseEvent) { const [node, widget] = getHovered(e) ?? [] - if (node?.mode !== LGraphEventMode.ALWAYS) + if ( + node?.mode !== LGraphEventMode.ALWAYS || + !nodeTypeValidForApp(node.type) || + node.has_errors + ) return canvasInteractions.forwardEventToCanvas(e) if (!widget) { @@ -198,7 +202,9 @@ const renderedOutputs = computed(() => { return canvas .graph!.nodes.filter( (n) => - n.constructor.nodeData?.output_node && n.mode === LGraphEventMode.ALWAYS + n.constructor.nodeData?.output_node && + n.mode === LGraphEventMode.ALWAYS && + !n.has_errors ) .map(nodeToDisplayTuple) }) diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 317946b995..582e3dffb3 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -3179,6 +3179,7 @@ "loadTemplate": "Load a template", "cancelThisRun": "Cancel this run", "deleteAllAssets": "Delete all assets from this run", + "hasCreditCost": "Requires additional credits", "welcome": { "title": "App Mode", "message": "A simplified view that hides the node graph so you can focus on creating.", diff --git a/src/renderer/extensions/linearMode/AppOutput.vue b/src/renderer/extensions/linearMode/AppOutput.vue index 33b7fa559c..55a2057acd 100644 --- a/src/renderer/extensions/linearMode/AppOutput.vue +++ b/src/renderer/extensions/linearMode/AppOutput.vue @@ -25,7 +25,7 @@ function togglePromotion() {
import { useEventListener, useTimeout } from '@vueuse/core' -import { partition, remove, takeWhile } from 'es-toolkit' +import { remove, takeWhile } from 'es-toolkit' import { storeToRefs } from 'pinia' import { computed, ref, shallowRef } from 'vue' import { useI18n } from 'vue-i18n' @@ -19,6 +19,7 @@ import { useSettingStore } from '@/platform/settings/settingStore' import { useTelemetry } from '@/platform/telemetry' import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore' import DropZone from '@/renderer/extensions/linearMode/DropZone.vue' +import PartnerNodesList from '@/renderer/extensions/linearMode/PartnerNodesList.vue' import NodeWidgets from '@/renderer/extensions/vueNodes/components/NodeWidgets.vue' import { api } from '@/scripts/api' import { app } from '@/scripts/app' @@ -119,20 +120,6 @@ function nodeToNodeData(node: LGraphNode) { onDragOver: node.onDragOver } } -const partitionedNodes = computed(() => { - 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 -}) //TODO: refactor out of this file. //code length is small, but changes should propagate @@ -180,34 +167,6 @@ defineExpose({ runButtonClick }) v-text="workflowStore.activeWorkflow?.filename" />
- - -
- -
-