Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -2197,6 +2197,10 @@
"vueNodesMigrationMainMenu": {
"message": "Switch back to Nodes 2.0 anytime from the main menu."
},
"linearMode": {
"share": "Share",
"openWorkflow": "Open Workflow"
},
"missingNodes": {
"cloud": {
"title": "These nodes aren't available on Comfy Cloud yet",
Expand Down
32 changes: 24 additions & 8 deletions src/views/LinearView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Splitter from 'primevue/splitter'
import SplitterPanel from 'primevue/splitterpanel'
import { computed } from 'vue'

import ExtensionSlot from '@/components/common/ExtensionSlot.vue'
import CurrentUserButton from '@/components/topbar/CurrentUserButton.vue'
import LoginButton from '@/components/topbar/LoginButton.vue'
import TopbarBadges from '@/components/topbar/TopbarBadges.vue'
Expand All @@ -14,20 +15,20 @@ import {
isValidWidgetValue,
safeWidgetMapper
} from '@/composables/graph/useGraphNodeManager'
import { useAssetsSidebarTab } from '@/composables/sidebarTabs/useAssetsSidebarTab'
import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useTelemetry } from '@/platform/telemetry'
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import NodeWidgets from '@/renderer/extensions/vueNodes/components/NodeWidgets.vue'
import WidgetInputNumberInput from '@/renderer/extensions/vueNodes/widgets/components/WidgetInputNumber.vue'
import { app } from '@/scripts/app'
import { useCommandStore } from '@/stores/commandStore'
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
//import { useQueueStore } from '@/stores/queueStore'
import { useQueueSettingsStore } from '@/stores/queueStore'
import { isElectron } from '@/utils/envUtil'

//const queueStore = useQueueStore()
const nodeOutputStore = useNodeOutputStore()
const commandStore = useCommandStore()
const nodeDatas = computed(() => {
Expand Down Expand Up @@ -114,9 +115,16 @@ function openFeedback() {
class="h-[calc(100%-38px)] w-full bg-comfy-menu-secondary-bg"
:pt="{ gutter: { class: 'bg-transparent w-4 -mx-3' } }"
>
<SplitterPanel :size="1" class="min-w-min bg-comfy-menu-bg">
<div
class="sidebar-content-container h-full w-full overflow-x-hidden overflow-y-auto border-r-1 border-node-component-border"
>
<ExtensionSlot :extension="useAssetsSidebarTab()" />
</div>
</SplitterPanel>
Comment on lines +118 to +124
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid calling composables directly in the template.

Calling useAssetsSidebarTab() directly in the template (line 122) is an anti-pattern in Vue because:

  • Composables are re-executed on every render
  • May cause reactivity and lifecycle management issues
  • Goes against Vue's composition API best practices

Apply this diff to fix:

 const { isLoggedIn } = useCurrentUser()
 const isDesktop = isElectron()
+const assetsSidebarExtension = useAssetsSidebarTab()

 const batchCountWidget = {

Then update the template:

-        <ExtensionSlot :extension="useAssetsSidebarTab()" />
+        <ExtensionSlot :extension="assetsSidebarExtension" />

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/views/LinearView.vue around lines 118 to 124, the template is calling the
composable useAssetsSidebarTab() directly which causes it to run on every
render; move the composable invocation into the component's script setup (or
setup function), assign its return value to a const (or computed/ref as
appropriate), and then use that variable in the template's ExtensionSlot prop
(replace :extension="useAssetsSidebarTab()" with :extension="assetsSidebarTab"
or similar); ensure the variable is exported/returned from setup so the template
can access it.

<SplitterPanel
:size="99"
class="flex flex-row overflow-y-auto flex-wrap min-w-min gap-4"
:size="98"
class="flex flex-row overflow-y-auto flex-wrap min-w-min gap-4 m-4"
>
<img
v-for="previewUrl in nodeOutputStore.latestOutput"
Expand All @@ -132,18 +140,26 @@ function openFeedback() {
</SplitterPanel>
<SplitterPanel :size="1" class="flex flex-col gap-1 p-1 min-w-min">
<div
class="actionbar-container flex h-12 items-center rounded-lg border border-[var(--interface-stroke)] p-2 gap-2 bg-comfy-menu-bg justify-center"
class="actionbar-container flex h-12 items-center rounded-lg border border-[var(--interface-stroke)] p-2 gap-2 bg-comfy-menu-bg justify-end"
>
<Button label="Feedback" severity="secondary" @click="openFeedback" />
<Button
label="Open Workflow"
:label="t('g.feedback')"
severity="secondary"
@click="openFeedback"
/>
<Button
:label="t('linearMode.openWorkflow')"
severity="secondary"
class="min-w-max"
icon="icon-[comfy--workflow]"
icon-pos="right"
@click="useCanvasStore().linearMode = false"
/>
<!--<Button label="Share" severity="contrast" /> Temporarily disabled-->
<Button
:label="t('linearMode.share')"
severity="contrast"
@click="useWorkflowService().exportWorkflow('workflow', 'workflow')"
/>
<CurrentUserButton v-if="isLoggedIn" />
<LoginButton v-else-if="isDesktop" />
</div>
Expand Down