mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 15:40:10 +00:00
[refactor] WIP: checkNodeCompatibility refactor
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
v-model="selectedVersion"
|
||||
option-label="label"
|
||||
option-value="value"
|
||||
:options="versionOptions"
|
||||
:options="processedVersionOptions"
|
||||
:highlight-on-select="false"
|
||||
class="w-full max-h-[50vh] border-none shadow-none rounded-md"
|
||||
:pt="{
|
||||
@@ -35,19 +35,14 @@
|
||||
<template #option="slotProps">
|
||||
<div class="flex justify-between items-center w-full p-1">
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Show no icon for nightly versions since compatibility is uncertain -->
|
||||
<template v-if="slotProps.option.value === 'nightly'">
|
||||
<div class="w-4"></div>
|
||||
<!-- Empty space to maintain alignment -->
|
||||
</template>
|
||||
<template v-else>
|
||||
<i
|
||||
v-if="
|
||||
getVersionCompatibility(slotProps.option.value).hasConflict
|
||||
"
|
||||
v-if="slotProps.option.hasConflict"
|
||||
v-tooltip="{
|
||||
value: getVersionCompatibility(slotProps.option.value)
|
||||
.conflictMessage,
|
||||
value: slotProps.option.conflictMessage,
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-exclamation-triangle text-yellow-500"
|
||||
@@ -57,7 +52,7 @@
|
||||
<span>{{ slotProps.option.label }}</span>
|
||||
</div>
|
||||
<i
|
||||
v-if="selectedVersion === slotProps.option.value"
|
||||
v-if="slotProps.option.isSelected"
|
||||
class="pi pi-check text-highlight"
|
||||
/>
|
||||
</div>
|
||||
@@ -89,7 +84,7 @@ import { whenever } from '@vueuse/core'
|
||||
import Button from 'primevue/button'
|
||||
import Listbox from 'primevue/listbox'
|
||||
import ProgressSpinner from 'primevue/progressspinner'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import ContentDivider from '@/components/common/ContentDivider.vue'
|
||||
@@ -115,11 +110,12 @@ const emit = defineEmits<{
|
||||
const { t } = useI18n()
|
||||
const registryService = useComfyRegistryService()
|
||||
const managerStore = useComfyManagerStore()
|
||||
const { checkVersionCompatibility } = useConflictDetection()
|
||||
const { checkNodeCompatibility } = useConflictDetection()
|
||||
|
||||
const isQueueing = ref(false)
|
||||
|
||||
const selectedVersion = ref<string>('latest')
|
||||
|
||||
onMounted(() => {
|
||||
const initialVersion = getInitialSelectedVersion() ?? 'latest'
|
||||
selectedVersion.value =
|
||||
@@ -130,14 +126,14 @@ onMounted(() => {
|
||||
const getInitialSelectedVersion = () => {
|
||||
if (!nodePack.id) return
|
||||
|
||||
// If unclaimed, set selected version to nightly
|
||||
if (nodePack.publisher?.name === 'Unclaimed')
|
||||
return 'nightly' as ManagerComponents['schemas']['SelectedVersion']
|
||||
|
||||
// If node pack is installed, set selected version to the installed version
|
||||
if (managerStore.isPackInstalled(nodePack.id))
|
||||
return managerStore.getInstalledPackVersion(nodePack.id)
|
||||
|
||||
// If unclaimed, set selected version to nightly
|
||||
if (nodePack.publisher?.name === 'Unclaimed')
|
||||
return 'nightly' as ManagerComponents['schemas']['SelectedVersion']
|
||||
|
||||
// If node pack is not installed, set selected version to latest
|
||||
return nodePack.latest_version?.version
|
||||
}
|
||||
@@ -235,76 +231,35 @@ const handleSubmit = async () => {
|
||||
emit('submit')
|
||||
}
|
||||
|
||||
// Function to get version data (either from nodePack or fetchedVersions)
|
||||
const getVersionData = (version: string) => {
|
||||
// Use latest_version data for both "latest" and the actual latest version number
|
||||
const latestVersionNumber = nodePack.latest_version?.version
|
||||
const useLatestVersionData =
|
||||
version === 'latest' || version === latestVersionNumber
|
||||
|
||||
if (useLatestVersionData) {
|
||||
// For "latest" and the actual latest version number, use consistent data from latest_version
|
||||
const latestVersionData = nodePack.latest_version
|
||||
return {
|
||||
supported_os: latestVersionData?.supported_os ?? nodePack.supported_os,
|
||||
supported_accelerators:
|
||||
latestVersionData?.supported_accelerators ??
|
||||
nodePack.supported_accelerators,
|
||||
supported_comfyui_version:
|
||||
latestVersionData?.supported_comfyui_version ??
|
||||
nodePack.supported_comfyui_version,
|
||||
supported_comfyui_frontend_version:
|
||||
latestVersionData?.supported_comfyui_frontend_version ??
|
||||
nodePack.supported_comfyui_frontend_version
|
||||
...latestVersionData
|
||||
}
|
||||
}
|
||||
|
||||
if (version === 'nightly') {
|
||||
// For nightly, we can't determine exact compatibility since it's dynamic Git HEAD
|
||||
// But we can assume it's generally compatible (nightly = latest development)
|
||||
// Use nodePack data as fallback, but nightly is typically more permissive
|
||||
return {
|
||||
supported_os: nodePack.supported_os || [], // If no OS restrictions, assume all supported
|
||||
supported_accelerators: nodePack.supported_accelerators || [], // If no accelerator restrictions, assume all supported
|
||||
supported_comfyui_version: nodePack.supported_comfyui_version, // Use latest known requirement
|
||||
supported_comfyui_frontend_version:
|
||||
nodePack.supported_comfyui_frontend_version // Use latest known requirement
|
||||
}
|
||||
}
|
||||
|
||||
// For specific versions, find in fetched versions
|
||||
const versionData = fetchedVersions.value.find((v) => v.version === version)
|
||||
if (versionData) {
|
||||
return {
|
||||
supported_os: versionData.supported_os,
|
||||
supported_accelerators: versionData.supported_accelerators,
|
||||
supported_comfyui_version: versionData.supported_comfyui_version,
|
||||
supported_comfyui_frontend_version:
|
||||
versionData.supported_comfyui_frontend_version
|
||||
...versionData
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to nodePack data
|
||||
return {
|
||||
supported_os: nodePack.supported_os,
|
||||
supported_accelerators: nodePack.supported_accelerators,
|
||||
supported_comfyui_version: nodePack.supported_comfyui_version,
|
||||
supported_comfyui_frontend_version:
|
||||
nodePack.supported_comfyui_frontend_version
|
||||
...nodePack
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check version compatibility using centralized logic
|
||||
const checkVersionCompatibilityLocal = (
|
||||
versionData: ReturnType<typeof getVersionData>
|
||||
) => {
|
||||
return checkVersionCompatibility(versionData)
|
||||
}
|
||||
|
||||
// Main function to get version compatibility info
|
||||
const getVersionCompatibility = (version: string) => {
|
||||
const versionData = getVersionData(version)
|
||||
const compatibility = checkVersionCompatibilityLocal(versionData)
|
||||
const compatibility = checkNodeCompatibility(versionData)
|
||||
|
||||
const conflictMessage = compatibility.hasConflict
|
||||
? getJoinedConflictMessages(compatibility.conflicts, t)
|
||||
@@ -315,4 +270,33 @@ const getVersionCompatibility = (version: string) => {
|
||||
conflictMessage
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to determine if an option is selected.
|
||||
const isOptionSelected = (optionValue: string) => {
|
||||
if (selectedVersion.value === optionValue) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
optionValue === 'latest' &&
|
||||
selectedVersion.value === nodePack.latest_version?.version
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Checks if an option is selected, treating 'latest' as an alias for the actual latest version number.
|
||||
const processedVersionOptions = computed(() => {
|
||||
return versionOptions.value.map((option) => {
|
||||
const compatibility = getVersionCompatibility(option.value)
|
||||
const isSelected = isOptionSelected(option.value)
|
||||
|
||||
return {
|
||||
...option,
|
||||
hasConflict: compatibility.hasConflict,
|
||||
conflictMessage: compatibility.conflictMessage,
|
||||
isSelected: isSelected
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -17,36 +17,24 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { inject, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue'
|
||||
import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment'
|
||||
import { useConflictDetection } from '@/composables/useConflictDetection'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||
import { IsInstallingKey } from '@/types/comfyManagerTypes'
|
||||
import type { components } from '@/types/comfyRegistryTypes'
|
||||
import type { ConflictDetectionResult } from '@/types/conflictDetectionTypes'
|
||||
import { components as ManagerComponents } from '@/types/generatedManagerTypes'
|
||||
|
||||
type NodePack = components['schemas']['Node']
|
||||
|
||||
const { nodePacks, variant, label, hasConflict, skipConflictCheck } =
|
||||
defineProps<{
|
||||
nodePacks: NodePack[]
|
||||
variant?: 'default' | 'black'
|
||||
label?: string
|
||||
hasConflict?: boolean
|
||||
skipConflictCheck?: boolean
|
||||
}>()
|
||||
const { nodePacks, variant, label, hasConflict } = defineProps<{
|
||||
nodePacks: NodePack[]
|
||||
variant?: 'default' | 'black'
|
||||
label?: string
|
||||
hasConflict?: boolean
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
const isInstalling = inject(IsInstallingKey, ref(false))
|
||||
const managerStore = useComfyManagerStore()
|
||||
const { showNodeConflictDialog } = useDialogService()
|
||||
const { checkVersionCompatibility } = useConflictDetection()
|
||||
const { acknowledgeConflict, isConflictAcknowledged } =
|
||||
useConflictAcknowledgment()
|
||||
|
||||
const onClick = (): void => {
|
||||
isInstalling.value = true
|
||||
@@ -78,81 +66,37 @@ const createPayload = (
|
||||
const installPack = (item: NodePack) =>
|
||||
managerStore.installPack.call(createPayload(item))
|
||||
|
||||
// Function to check compatibility for uninstalled packages using centralized logic
|
||||
function checkUninstalledPackageCompatibility(
|
||||
pack: NodePack
|
||||
): ConflictDetectionResult | null {
|
||||
const compatibility = checkVersionCompatibility({
|
||||
supported_os: pack.supported_os,
|
||||
supported_accelerators: pack.supported_accelerators,
|
||||
supported_comfyui_version: pack.supported_comfyui_version,
|
||||
supported_comfyui_frontend_version: pack.supported_comfyui_frontend_version
|
||||
})
|
||||
|
||||
if (compatibility.hasConflict) {
|
||||
return {
|
||||
package_id: pack.id || 'unknown',
|
||||
package_name: pack.name || 'unknown',
|
||||
has_conflict: true,
|
||||
conflicts: compatibility.conflicts,
|
||||
is_compatible: false
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const installAllPacks = async () => {
|
||||
if (!nodePacks?.length) return
|
||||
|
||||
// TBD Install Anyway modal
|
||||
// if (hasConflict && !isConflictAcknowledged) {
|
||||
// showNodeConflictDialog({
|
||||
// conflictedPackages: nodePacks,
|
||||
// buttonText: t('manager.conflicts.installAnyway'),
|
||||
// onButtonClick: async () => {
|
||||
// // User chose "Install Anyway" - acknowledge all conflicts and proceed
|
||||
// for (const conflictedPack of packsWithConflicts) {
|
||||
// for (const conflict of conflictedPack.conflicts) {
|
||||
// acknowledgeConflict(
|
||||
// conflictedPack.package_id,
|
||||
// conflict.type,
|
||||
// '0.1.0'
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// // Proceed with installation
|
||||
// await performInstallation(uninstalledPacks)
|
||||
// }
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
const uninstalledPacks = nodePacks.filter(
|
||||
(pack) => !managerStore.isPackInstalled(pack.id)
|
||||
)
|
||||
if (!uninstalledPacks.length) return
|
||||
|
||||
// Skip conflict check if explicitly requested (e.g., from "Install Anyway" button)
|
||||
if (!skipConflictCheck) {
|
||||
// Check for conflicts in uninstalled packages
|
||||
const packsWithConflicts: ConflictDetectionResult[] = []
|
||||
|
||||
for (const pack of uninstalledPacks) {
|
||||
const conflicts = checkUninstalledPackageCompatibility(pack)
|
||||
if (conflicts) {
|
||||
// Check if conflicts have been acknowledged
|
||||
const hasUnacknowledgedConflicts = conflicts.conflicts.some(
|
||||
(conflict) => !isConflictAcknowledged(pack.id || '', conflict.type)
|
||||
)
|
||||
|
||||
if (hasUnacknowledgedConflicts) {
|
||||
packsWithConflicts.push(conflicts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are unacknowledged conflicts, show modal
|
||||
if (packsWithConflicts.length > 0) {
|
||||
showNodeConflictDialog({
|
||||
conflictedPackages: packsWithConflicts,
|
||||
buttonText: t('manager.conflicts.installAnyway'),
|
||||
onButtonClick: async () => {
|
||||
// User chose "Install Anyway" - acknowledge all conflicts and proceed
|
||||
for (const conflictedPack of packsWithConflicts) {
|
||||
for (const conflict of conflictedPack.conflicts) {
|
||||
acknowledgeConflict(
|
||||
conflictedPack.package_id,
|
||||
conflict.type,
|
||||
'0.1.0'
|
||||
)
|
||||
}
|
||||
}
|
||||
// Proceed with installation
|
||||
await performInstallation(uninstalledPacks)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// No conflicts or conflicts acknowledged - proceed with installation
|
||||
await performInstallation(uninstalledPacks)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ whenever(isInstalled, () => {
|
||||
isInstalling.value = false
|
||||
})
|
||||
|
||||
const { checkVersionCompatibility } = useConflictDetection()
|
||||
const { checkNodeCompatibility } = useConflictDetection()
|
||||
const { getConflictsForPackageByID } = useConflictDetectionStore()
|
||||
|
||||
const { t, d, n } = useI18n()
|
||||
@@ -107,22 +107,12 @@ const conflictResult = computed((): ConflictDetectionResult | null => {
|
||||
}
|
||||
|
||||
// For non-installed packages, perform compatibility check
|
||||
const compatibility = checkVersionCompatibility({
|
||||
supported_os: nodePack.supported_os,
|
||||
supported_accelerators: nodePack.supported_accelerators,
|
||||
supported_comfyui_version: nodePack.supported_comfyui_version,
|
||||
supported_comfyui_frontend_version:
|
||||
nodePack.supported_comfyui_frontend_version
|
||||
// TODO: Add when API provides these fields
|
||||
// supported_python_version: nodePack.supported_python_version,
|
||||
// is_banned: nodePack.is_banned,
|
||||
// has_registry_data: nodePack.has_registry_data
|
||||
})
|
||||
const compatibility = checkNodeCompatibility(nodePack)
|
||||
|
||||
if (compatibility.hasConflict && nodePack.id && nodePack.name) {
|
||||
if (compatibility.hasConflict) {
|
||||
return {
|
||||
package_id: nodePack.id,
|
||||
package_name: nodePack.name,
|
||||
package_id: nodePack.id || '',
|
||||
package_name: nodePack.name || '',
|
||||
has_conflict: true,
|
||||
conflicts: compatibility.conflicts,
|
||||
is_compatible: false
|
||||
@@ -133,7 +123,7 @@ const conflictResult = computed((): ConflictDetectionResult | null => {
|
||||
})
|
||||
|
||||
const hasCompatibilityIssues = computed(() => {
|
||||
return isInstalled.value && conflictResult.value?.has_conflict ? true : false
|
||||
return conflictResult.value?.has_conflict
|
||||
})
|
||||
|
||||
const infoItems = computed<InfoItem[]>(() => [
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:key="index"
|
||||
class="p-3 bg-yellow-800/20 rounded-md"
|
||||
>
|
||||
<div class="text-sm">
|
||||
<div class="text-sm break-words">
|
||||
{{ getConflictMessage(conflict, $t) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -45,7 +45,7 @@ const formattedDownloads = computed(() =>
|
||||
)
|
||||
|
||||
const { getConflictsForPackageByID } = useConflictDetectionStore()
|
||||
const { checkVersionCompatibility } = useConflictDetection()
|
||||
const { checkNodeCompatibility } = useConflictDetection()
|
||||
|
||||
const hasConflict = computed(() => {
|
||||
if (!nodePack.id) return false
|
||||
@@ -60,9 +60,7 @@ const hasConflict = computed(() => {
|
||||
}
|
||||
|
||||
// For uninstalled packages, check compatibility directly
|
||||
const compatibility = checkVersionCompatibility(nodePack)
|
||||
console.log(compatibility)
|
||||
|
||||
const compatibility = checkNodeCompatibility(nodePack)
|
||||
return compatibility.hasConflict
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
import { uniqBy } from 'lodash'
|
||||
import { computed, getCurrentInstance, onUnmounted, readonly, ref } from 'vue'
|
||||
import { uniqBy } from 'lodash';
|
||||
import { computed, getCurrentInstance, onUnmounted, readonly, ref } from 'vue';
|
||||
|
||||
|
||||
|
||||
import { useInstalledPacks } from '@/composables/nodePack/useInstalledPacks';
|
||||
import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment';
|
||||
import config from '@/config';
|
||||
import { useComfyManagerService } from '@/services/comfyManagerService';
|
||||
import { useComfyRegistryService } from '@/services/comfyRegistryService';
|
||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore';
|
||||
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore';
|
||||
import { useSystemStatsStore } from '@/stores/systemStatsStore';
|
||||
import type { SystemStats } from '@/types';
|
||||
import type { components } from '@/types/comfyRegistryTypes';
|
||||
import type { ConflictDetail, ConflictDetectionResponse, ConflictDetectionResult, ConflictDetectionSummary, ConflictType, Node, NodePackRequirements, SystemEnvironment } from '@/types/conflictDetectionTypes';
|
||||
import { cleanVersion, satisfiesVersion, utilCheckVersionCompatibility } from '@/utils/versionUtil';
|
||||
|
||||
|
||||
|
||||
|
||||
import { useInstalledPacks } from '@/composables/nodePack/useInstalledPacks'
|
||||
import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment'
|
||||
import config from '@/config'
|
||||
import { useComfyManagerService } from '@/services/comfyManagerService'
|
||||
import { useComfyRegistryService } from '@/services/comfyRegistryService'
|
||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
|
||||
import { useSystemStatsStore } from '@/stores/systemStatsStore'
|
||||
import type { SystemStats } from '@/types'
|
||||
import type { components } from '@/types/comfyRegistryTypes'
|
||||
import type {
|
||||
ConflictDetail,
|
||||
ConflictDetectionResponse,
|
||||
ConflictDetectionResult,
|
||||
ConflictDetectionSummary,
|
||||
ConflictType,
|
||||
Node,
|
||||
NodePackRequirements,
|
||||
SystemEnvironment
|
||||
} from '@/types/conflictDetectionTypes'
|
||||
import {
|
||||
cleanVersion,
|
||||
satisfiesVersion,
|
||||
checkVersionCompatibility as utilCheckVersionCompatibility
|
||||
} from '@/utils/versionUtil'
|
||||
|
||||
/**
|
||||
* Composable for conflict detection system.
|
||||
@@ -734,10 +727,12 @@ export function useConflictDetection() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check compatibility for a specific version of a package.
|
||||
* Check compatibility for a node.
|
||||
* Used by components like PackVersionSelectorPopover.
|
||||
*/
|
||||
function checkVersionCompatibility(node: Node) {
|
||||
function checkNodeCompatibility(
|
||||
node: Node | components['schemas']['NodeVersion']
|
||||
) {
|
||||
const systemStatsStore = useSystemStatsStore()
|
||||
const systemStats = systemStatsStore.systemStats
|
||||
if (!systemStats) return { hasConflict: false, conflicts: [] }
|
||||
@@ -856,7 +851,7 @@ export function useConflictDetection() {
|
||||
acknowledgePackageConflict,
|
||||
|
||||
// Helper functions for other components
|
||||
checkVersionCompatibility
|
||||
checkNodeCompatibility
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1302,6 +1297,7 @@ function generateSummary(
|
||||
const conflictsByType: Record<ConflictType, number> = {
|
||||
comfyui_version: 0,
|
||||
frontend_version: 0,
|
||||
import_failed: 0,
|
||||
os: 0,
|
||||
accelerator: 0,
|
||||
banned: 0,
|
||||
@@ -1374,4 +1370,4 @@ function getEmptySummary(): ConflictDetectionSummary {
|
||||
last_check_timestamp: new Date().toISOString(),
|
||||
check_duration_ms: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ export function isValidVersion(version: string): boolean {
|
||||
* @param supportedVersion Required version range string
|
||||
* @returns ConflictDetail object if incompatible, null if compatible
|
||||
*/
|
||||
export function checkVersionCompatibility(
|
||||
export function utilCheckVersionCompatibility(
|
||||
type: ConflictType,
|
||||
currentVersion: string,
|
||||
supportedVersion: string
|
||||
|
||||
Reference in New Issue
Block a user