mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 11:11:53 +00:00
refactor: simplify PackInstallButton isInstalling state management
- Remove isInstalling prop from PackInstallButton component - Use internal computed property with comfyManagerStore.isPackInstalling() - Remove redundant isInstalling computations from parent components - Fix test mocks for useConflictDetection and es-toolkit/compat - Clean up unused imports and inject dependencies This centralizes the installation state management in the store, reducing code duplication and complexity across components. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -36,7 +36,6 @@
|
|||||||
size="md"
|
size="md"
|
||||||
:disabled="!!error || missingNodePacks.length === 0"
|
:disabled="!!error || missingNodePacks.length === 0"
|
||||||
:is-loading="isLoading"
|
:is-loading="isLoading"
|
||||||
:is-installing="isInstalling"
|
|
||||||
:node-packs="missingNodePacks"
|
:node-packs="missingNodePacks"
|
||||||
:label="
|
:label="
|
||||||
isLoading
|
isLoading
|
||||||
@@ -59,11 +58,9 @@ import PackInstallButton from '@/components/dialog/content/manager/button/PackIn
|
|||||||
import { useMissingNodes } from '@/composables/nodePack/useMissingNodes'
|
import { useMissingNodes } from '@/composables/nodePack/useMissingNodes'
|
||||||
import { useComfyManagerService } from '@/services/comfyManagerService'
|
import { useComfyManagerService } from '@/services/comfyManagerService'
|
||||||
import { useDialogService } from '@/services/dialogService'
|
import { useDialogService } from '@/services/dialogService'
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
|
||||||
import type { MissingNodeType } from '@/types/comfy'
|
import type { MissingNodeType } from '@/types/comfy'
|
||||||
import { ManagerTab } from '@/types/comfyManagerTypes'
|
import { ManagerTab } from '@/types/comfyManagerTypes'
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
missingNodeTypes: MissingNodeType[]
|
missingNodeTypes: MissingNodeType[]
|
||||||
}>()
|
}>()
|
||||||
@@ -72,17 +69,8 @@ const props = defineProps<{
|
|||||||
const { missingNodePacks, isLoading, error, missingCoreNodes } =
|
const { missingNodePacks, isLoading, error, missingCoreNodes } =
|
||||||
useMissingNodes()
|
useMissingNodes()
|
||||||
|
|
||||||
const comfyManagerStore = useComfyManagerStore()
|
|
||||||
const isLegacyManager = ref(false)
|
const isLegacyManager = ref(false)
|
||||||
|
|
||||||
// Check if any of the missing packs are currently being installed
|
|
||||||
const isInstalling = computed(() => {
|
|
||||||
if (!missingNodePacks.value?.length) return false
|
|
||||||
return missingNodePacks.value.some((pack) =>
|
|
||||||
comfyManagerStore.isPackInstalling(pack.id)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const uniqueNodes = computed(() => {
|
const uniqueNodes = computed(() => {
|
||||||
const seenTypes = new Set()
|
const seenTypes = new Set()
|
||||||
return props.missingNodeTypes
|
return props.missingNodeTypes
|
||||||
|
|||||||
@@ -11,10 +11,14 @@ import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
|||||||
|
|
||||||
import PackEnableToggle from './PackEnableToggle.vue'
|
import PackEnableToggle from './PackEnableToggle.vue'
|
||||||
|
|
||||||
// Mock debounce to execute immediately
|
// Mock debounce and memoize to execute immediately
|
||||||
vi.mock('es-toolkit/compat', () => ({
|
vi.mock('es-toolkit/compat', async (importOriginal) => {
|
||||||
debounce: <T extends (...args: any[]) => any>(fn: T) => fn
|
const actual = (await importOriginal()) as any
|
||||||
}))
|
return {
|
||||||
|
...actual,
|
||||||
|
debounce: <T extends (...args: any[]) => any>(fn: T) => fn
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const mockNodePack = {
|
const mockNodePack = {
|
||||||
id: 'test-pack',
|
id: 'test-pack',
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ type NodePack = components['schemas']['Node']
|
|||||||
const {
|
const {
|
||||||
nodePacks,
|
nodePacks,
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
isInstalling = false,
|
|
||||||
label = 'Install',
|
label = 'Install',
|
||||||
size = 'sm',
|
size = 'sm',
|
||||||
hasConflict,
|
hasConflict,
|
||||||
@@ -55,7 +54,6 @@ const {
|
|||||||
} = defineProps<{
|
} = defineProps<{
|
||||||
nodePacks: NodePack[]
|
nodePacks: NodePack[]
|
||||||
isLoading?: boolean
|
isLoading?: boolean
|
||||||
isInstalling?: boolean
|
|
||||||
label?: string
|
label?: string
|
||||||
size?: ButtonSize
|
size?: ButtonSize
|
||||||
hasConflict?: boolean
|
hasConflict?: boolean
|
||||||
@@ -65,6 +63,12 @@ const {
|
|||||||
const managerStore = useComfyManagerStore()
|
const managerStore = useComfyManagerStore()
|
||||||
const { showNodeConflictDialog } = useDialogService()
|
const { showNodeConflictDialog } = useDialogService()
|
||||||
|
|
||||||
|
// Check if any of the packs are currently being installed
|
||||||
|
const isInstalling = computed(() => {
|
||||||
|
if (!nodePacks?.length) return false
|
||||||
|
return nodePacks.some((pack) => managerStore.isPackInstalling(pack.id))
|
||||||
|
})
|
||||||
|
|
||||||
const createPayload = (installItem: NodePack) => {
|
const createPayload = (installItem: NodePack) => {
|
||||||
if (!installItem.id) {
|
if (!installItem.id) {
|
||||||
throw new Error('Node ID is required for installation')
|
throw new Error('Node ID is required for installation')
|
||||||
@@ -107,14 +111,12 @@ const installAllPacks = async () => {
|
|||||||
buttonText: t('manager.conflicts.installAnyway'),
|
buttonText: t('manager.conflicts.installAnyway'),
|
||||||
onButtonClick: async () => {
|
onButtonClick: async () => {
|
||||||
// Proceed with installation
|
// Proceed with installation
|
||||||
// isInstalling.value = true
|
|
||||||
await performInstallation(nodePacks)
|
await performInstallation(nodePacks)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// No conflicts or conflicts acknowledged - proceed with installation
|
// No conflicts or conflicts acknowledged - proceed with installation
|
||||||
// isInstalling.value = true
|
|
||||||
await performInstallation(nodePacks)
|
await performInstallation(nodePacks)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +126,7 @@ const performInstallation = async (packs: NodePack[]) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const computedLabel = computed(() =>
|
const computedLabel = computed(() =>
|
||||||
isInstalling
|
isInstalling.value
|
||||||
? t('g.installing')
|
? t('g.installing')
|
||||||
: label ??
|
: label ??
|
||||||
(nodePacks.length > 1 ? t('manager.installSelected') : t('g.install'))
|
(nodePacks.length > 1 ? t('manager.installSelected') : t('g.install'))
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
v-else
|
v-else
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
size="md"
|
size="md"
|
||||||
:is-installing="isInstalling"
|
|
||||||
:node-packs="nodePacks"
|
:node-packs="nodePacks"
|
||||||
:has-conflict="hasConflict"
|
:has-conflict="hasConflict"
|
||||||
/>
|
/>
|
||||||
@@ -42,7 +41,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject, ref, watch } from 'vue'
|
import { inject, ref, watch } from 'vue'
|
||||||
|
|
||||||
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
||||||
import PackInstallButton from '@/components/dialog/content/manager/button/PackInstallButton.vue'
|
import PackInstallButton from '@/components/dialog/content/manager/button/PackInstallButton.vue'
|
||||||
@@ -73,10 +72,4 @@ watch(
|
|||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check if any of the packs are currently being installed
|
|
||||||
const isInstalling = computed(() => {
|
|
||||||
if (!nodePacks?.length) return false
|
|
||||||
return nodePacks.some((pack) => managerStore.isPackInstalling(pack.id))
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
v-else
|
v-else
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
size="md"
|
size="md"
|
||||||
:is-installing="isInstalling"
|
|
||||||
:node-packs="nodePacks"
|
:node-packs="nodePacks"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -77,12 +76,6 @@ watch(
|
|||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check if any of the packs are currently being installed
|
|
||||||
const isInstalling = computed(() => {
|
|
||||||
if (!nodePacks?.length) return false
|
|
||||||
return nodePacks.some((pack) => managerStore.isPackInstalling(pack.id))
|
|
||||||
})
|
|
||||||
|
|
||||||
const getPackNodes = async (pack: components['schemas']['Node']) => {
|
const getPackNodes = async (pack: components['schemas']['Node']) => {
|
||||||
if (!pack.latest_version?.version) return []
|
if (!pack.latest_version?.version) return []
|
||||||
const nodeDefs = await getNodeDefs.call({
|
const nodeDefs = await getNodeDefs.call({
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
<template v-if="!isInstalled">
|
<template v-if="!isInstalled">
|
||||||
<PackInstallButton
|
<PackInstallButton
|
||||||
:node-packs="[nodePack]"
|
:node-packs="[nodePack]"
|
||||||
:is-installing="isInstalling"
|
|
||||||
:has-conflict="uninstalledPackConflict.hasConflict"
|
:has-conflict="uninstalledPackConflict.hasConflict"
|
||||||
:conflict-info="uninstalledPackConflict.conflicts"
|
:conflict-info="uninstalledPackConflict.conflicts"
|
||||||
/>
|
/>
|
||||||
@@ -39,7 +38,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import PackEnableToggle from '@/components/dialog/content/manager/button/PackEnableToggle.vue'
|
import PackEnableToggle from '@/components/dialog/content/manager/button/PackEnableToggle.vue'
|
||||||
@@ -48,7 +47,6 @@ import { useConflictDetection } from '@/composables/useConflictDetection'
|
|||||||
import { useImportFailedDetection } from '@/composables/useImportFailedDetection'
|
import { useImportFailedDetection } from '@/composables/useImportFailedDetection'
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||||
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
|
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
|
||||||
import { IsInstallingKey } from '@/types/comfyManagerTypes'
|
|
||||||
import type { components } from '@/types/comfyRegistryTypes'
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
|
|
||||||
const { nodePack } = defineProps<{
|
const { nodePack } = defineProps<{
|
||||||
@@ -57,7 +55,6 @@ const { nodePack } = defineProps<{
|
|||||||
|
|
||||||
const { isPackInstalled } = useComfyManagerStore()
|
const { isPackInstalled } = useComfyManagerStore()
|
||||||
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
|
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
|
||||||
const isInstalling = inject(IsInstallingKey)
|
|
||||||
|
|
||||||
const { n, t } = useI18n()
|
const { n, t } = useI18n()
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
<PackInstallButton
|
<PackInstallButton
|
||||||
v-if="isMissingTab && missingNodePacks.length > 0"
|
v-if="isMissingTab && missingNodePacks.length > 0"
|
||||||
:disabled="isLoading || !!error"
|
:disabled="isLoading || !!error"
|
||||||
:is-installing="isInstalling"
|
|
||||||
:node-packs="missingNodePacks"
|
:node-packs="missingNodePacks"
|
||||||
:label="$t('manager.installAllMissingNodes')"
|
:label="$t('manager.installAllMissingNodes')"
|
||||||
/>
|
/>
|
||||||
@@ -73,7 +72,6 @@ import PackUpdateButton from '@/components/dialog/content/manager/button/PackUpd
|
|||||||
import SearchFilterDropdown from '@/components/dialog/content/manager/registrySearchBar/SearchFilterDropdown.vue'
|
import SearchFilterDropdown from '@/components/dialog/content/manager/registrySearchBar/SearchFilterDropdown.vue'
|
||||||
import { useMissingNodes } from '@/composables/nodePack/useMissingNodes'
|
import { useMissingNodes } from '@/composables/nodePack/useMissingNodes'
|
||||||
import { useUpdateAvailableNodes } from '@/composables/nodePack/useUpdateAvailableNodes'
|
import { useUpdateAvailableNodes } from '@/composables/nodePack/useUpdateAvailableNodes'
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
|
||||||
import {
|
import {
|
||||||
type SearchOption,
|
type SearchOption,
|
||||||
SortableAlgoliaField
|
SortableAlgoliaField
|
||||||
@@ -104,15 +102,6 @@ const { t } = useI18n()
|
|||||||
// Get missing node packs from workflow with loading and error states
|
// Get missing node packs from workflow with loading and error states
|
||||||
const { missingNodePacks, isLoading, error } = useMissingNodes()
|
const { missingNodePacks, isLoading, error } = useMissingNodes()
|
||||||
|
|
||||||
const comfyManagerStore = useComfyManagerStore()
|
|
||||||
|
|
||||||
// Check if any of the missing packs are currently being installed
|
|
||||||
const isInstalling = computed(() => {
|
|
||||||
if (!missingNodePacks.value?.length) return false
|
|
||||||
return missingNodePacks.value.some((pack) =>
|
|
||||||
comfyManagerStore.isPackInstalling(pack.id)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
// Use the composable to get update available nodes
|
// Use the composable to get update available nodes
|
||||||
const { hasUpdateAvailable, updateAvailableNodePacks } =
|
const { hasUpdateAvailable, updateAvailableNodePacks } =
|
||||||
useUpdateAvailableNodes()
|
useUpdateAvailableNodes()
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ vi.mock('@/stores/dialogStore')
|
|||||||
vi.mock('@/stores/settingStore')
|
vi.mock('@/stores/settingStore')
|
||||||
vi.mock('@/stores/commandStore')
|
vi.mock('@/stores/commandStore')
|
||||||
vi.mock('@/services/comfyManagerService')
|
vi.mock('@/services/comfyManagerService')
|
||||||
|
vi.mock('@/composables/useConflictDetection', () => ({
|
||||||
|
useConflictDetection: vi.fn(() => ({
|
||||||
|
conflictedPackages: { value: [] },
|
||||||
|
performConflictDetection: vi.fn().mockResolvedValue(undefined)
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
|
||||||
// Mock useEventListener to capture the event handler
|
// Mock useEventListener to capture the event handler
|
||||||
let reconnectHandler: (() => void) | null = null
|
let reconnectHandler: (() => void) | null = null
|
||||||
|
|||||||
Reference in New Issue
Block a user