Add GPU selection to desktop installer (#1888)

* Remove redundant code

* Add GPU picker screen to installer

* Permit jumping installation steps when visited

* Prevent sad girl from covering buttons

* Update gpu options to match availability

* Ensure install screen renders inside bounds

* Pre-select GPU detected by desktop native

* Redesign GPU selection screen

* Prevent text highlight on installer stepper

* Add translations for GPU picker

* Rename for clarity

* Remove unused code

* Update electron types

* Update locales [skip ci]

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
filtered
2024-12-17 10:26:40 +11:00
committed by GitHub
parent a441908db3
commit 601b739f75
14 changed files with 441 additions and 68 deletions

8
package-lock.json generated
View File

@@ -10,7 +10,7 @@
"license": "GPL-3.0-only",
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
"@comfyorg/comfyui-electron-types": "^0.3.32",
"@comfyorg/comfyui-electron-types": "^0.3.34",
"@comfyorg/litegraph": "^0.8.46",
"@primevue/themes": "^4.0.5",
"@vueuse/core": "^11.0.0",
@@ -1951,9 +1951,9 @@
"dev": true
},
"node_modules/@comfyorg/comfyui-electron-types": {
"version": "0.3.32",
"resolved": "https://registry.npmjs.org/@comfyorg/comfyui-electron-types/-/comfyui-electron-types-0.3.32.tgz",
"integrity": "sha512-nftu7zFj1Xz6kOrZ+dcmYv+zF0KG23u2HmTOgTZh/Z5nJrC46raxHtHTlazER10cltUl2BozrE98+dWz3gDo3Q==",
"version": "0.3.34",
"resolved": "https://registry.npmjs.org/@comfyorg/comfyui-electron-types/-/comfyui-electron-types-0.3.34.tgz",
"integrity": "sha512-l4+llMrUh/nUxuBC1A1Zicu6EAZ74pDJPm14zQpyLleNeyj71FKIkgX/hIpbCegv5CwRgYXEdEN8FqTTKugf/A==",
"license": "GPL-3.0-only"
},
"node_modules/@comfyorg/litegraph": {

View File

@@ -82,7 +82,7 @@
},
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
"@comfyorg/comfyui-electron-types": "^0.3.32",
"@comfyorg/comfyui-electron-types": "^0.3.34",
"@comfyorg/litegraph": "^0.8.46",
"@primevue/themes": "^4.0.5",
"@vueuse/core": "^11.0.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="21.59mm" height="6.922mm" version="1.1" viewBox="0 0 21.59 6.922" xmlns="http://www.w3.org/2000/svg">
<path d="m6.667 0.941v1.345h-0.305v-1.345h-0.699v1.345h-0.304v-1.651h0.304v0.291q3e-3 -0.06 0.027-0.113 0.024-0.054 0.065-0.093 0.041-0.04 0.096-0.062 0.054-0.023 0.116-0.023h0.393q0.06 0 0.114 0.023 0.054 0.021 0.096 0.062 0.041 0.038 0.066 0.093 0.026 0.052 0.027 0.113 3e-3 -0.06 0.026-0.113 0.024-0.054 0.065-0.093 0.041-0.04 0.096-0.062 0.054-0.023 0.116-0.023h0.393q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119v1.347h-0.298v-1.345zm1.512 0.624q0-0.063 0.023-0.117 0.024-0.055 0.065-0.097 0.041-0.041 0.097-0.065 0.055-0.024 0.117-0.024h0.787v-0.321h-0.996v-0.305h0.996q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119v1.346h-0.302v-0.279q-4e-3 0.057-0.031 0.108-0.026 0.051-0.068 0.089-0.04 0.037-0.093 0.058-0.052 0.021-0.111 0.021h-0.483q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119zm0.303 0.415h0.787v-0.415h-0.786zm3.063 0.306h-0.306v-1.345h-0.851v1.345h-0.304v-1.651h0.303v0.291q3e-3 -0.06 0.027-0.113 0.024-0.054 0.065-0.093 0.041-0.04 0.096-0.062 0.054-0.023 0.116-0.023h0.545q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119zm0.508-1.651h0.303v1.346h0.851v-1.346h0.305v1.651h-0.304v-0.279q-4e-3 0.057-0.031 0.108-0.026 0.051-0.068 0.089-0.04 0.037-0.093 0.058-0.052 0.021-0.111 0.021h-0.547q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119zm1.969 0.93q0-0.063 0.023-0.117 0.024-0.055 0.065-0.097 0.041-0.041 0.097-0.065 0.055-0.024 0.117-0.024h0.787v-0.321h-0.996v-0.305h0.996q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119v1.346h-0.302v-0.279q-4e-3 0.057-0.031 0.108-0.026 0.051-0.068 0.089-0.04 0.037-0.093 0.058-0.052 0.021-0.111 0.021h-0.483q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119zm0.303 0.415h0.787v-0.415h-0.786zm1.906-1.98v2.286h-0.304v-2.286z" fill="#fff"/>
<path d="m0.303 4.909v1.04h0.787v-0.279h0.305v0.279q0 0.063-0.024 0.119-0.023 0.055-0.065 0.097-0.04 0.04-0.096 0.065-0.055 0.023-0.119 0.023h-0.788q-0.062 0-0.117-0.023-0.056-0.023-0.098-0.063-0.04-0.042-0.065-0.098-0.023-0.056-0.023-0.119v-1.04q0-0.063 0.023-0.119 0.024-0.055 0.065-0.096t0.097-0.065q0.055-0.024 0.117-0.024h0.787q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119v0.279h-0.302v-0.279zm3.029 1.04q0 0.063-0.024 0.119-0.023 0.055-0.065 0.097-0.04 0.04-0.096 0.065-0.054 0.023-0.117 0.023h-0.821q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119v-1.04q0-0.063 0.023-0.119 0.024-0.055 0.065-0.096t0.097-0.065q0.055-0.024 0.117-0.024h0.82q0.063 0 0.117 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119zm-1.123-1.04v1.04h0.82v-1.04zm3.092 1.345h-0.305v-1.345h-0.851v1.345h-0.304v-1.651h0.303v0.291q3e-3 -0.06 0.027-0.113 0.024-0.054 0.065-0.093 0.041-0.04 0.096-0.062 0.054-0.023 0.116-0.023h0.545q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119zm1.12-1.981v0.33h0.542v0.305h-0.541v1.345h-0.305v-1.344h-0.403v-0.305h0.403v-0.33q0-0.063 0.023-0.117 0.024-0.055 0.066-0.097 0.041-0.041 0.097-0.065 0.055-0.024 0.117-0.024h0.542v0.305zm1.277 0.33v1.651h-0.305v-1.651zm-0.32-0.635h0.336v0.317h-0.336zm0.844 0.941q0-0.063 0.023-0.119 0.024-0.055 0.065-0.096t0.097-0.065q0.055-0.024 0.117-0.024h0.547q0.06 0 0.114 0.023 0.054 0.021 0.094 0.062 0.041 0.038 0.066 0.093 0.026 0.052 0.027 0.113v-0.291h0.305v2.012q0 0.063-0.024 0.119-0.023 0.055-0.065 0.096-0.04 0.041-0.096 0.065-0.055 0.024-0.119 0.024h-0.964v-0.305h0.964v-0.424h-0.851q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119zm1.154 0.976v-0.976h-0.851v0.976zm0.813-1.282h0.303v1.345h0.851v-1.345h0.305v1.651h-0.305v-0.279q-4e-3 0.057-0.031 0.108-0.026 0.051-0.068 0.089-0.04 0.037-0.093 0.058-0.052 0.021-0.111 0.021h-0.547q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119zm2.272 0.305v1.345h-0.303v-1.651h0.303v0.291q3e-3 -0.06 0.027-0.113 0.024-0.054 0.065-0.093 0.041-0.04 0.096-0.062 0.054-0.023 0.116-0.023h0.324q0.063 0 0.117 0.024 0.055 0.023 0.097 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119v0.279h-0.305v-0.279zm1.314 0.624q0-0.063 0.023-0.117 0.024-0.055 0.065-0.097 0.041-0.041 0.097-0.065 0.055-0.024 0.117-0.024h0.787v-0.319h-0.996v-0.305h0.996q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119v1.345h-0.305v-0.279q-4e-3 0.057-0.031 0.108-0.026 0.051-0.068 0.089-0.04 0.037-0.093 0.058-0.052 0.021-0.111 0.021h-0.483q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119zm0.303 0.415h0.787v-0.415h-0.787zm1.505-1.345h0.403v-0.508h0.305v0.508h0.542v0.305h-0.542v1.04h0.542v0.305h-0.542q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.041-0.041-0.066-0.097-0.023-0.055-0.023-0.119v-1.04h-0.403zm2.08 0v1.651h-0.299v-1.649zm-0.314-0.634h0.336v0.317h-0.336zm2.272 1.981q0 0.063-0.024 0.119-0.023 0.055-0.065 0.097-0.04 0.04-0.096 0.065-0.054 0.023-0.117 0.023h-0.82q-0.062 0-0.117-0.023-0.055-0.024-0.097-0.065-0.04-0.041-0.065-0.097-0.023-0.055-0.023-0.119v-1.04q0-0.063 0.023-0.119 0.024-0.055 0.065-0.096t0.097-0.065q0.055-0.024 0.117-0.024h0.82q0.063 0 0.117 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119zm-1.123-1.04v1.04h0.82v-1.04zm3.092 1.345h-0.305v-1.345h-0.851v1.345h-0.303v-1.651h0.303v0.291q3e-3 -0.06 0.027-0.113 0.024-0.054 0.065-0.093 0.041-0.04 0.096-0.062 0.054-0.023 0.116-0.023h0.545q0.063 0 0.119 0.024 0.055 0.023 0.096 0.065 0.041 0.04 0.065 0.096 0.024 0.055 0.024 0.119z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -0,0 +1,6 @@
<svg enable-background="new 0 0 974.7 179.7" version="1.1" viewBox="0 0 974.7 179.7" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" width="110" height="44"><title> Artificial Intelligence Computing Leadership from NVIDIA</title>
<path fill="#FFFFFF" d="m962.1 144.1v-2.7h1.7c0.9 0 2.2 0.1 2.2 1.2s-0.7 1.5-1.8 1.5h-2.1m0 1.9h1.2l2.7 4.7h2.9l-3-4.9c1.5 0.1 2.7-1 2.8-2.5v-0.4c0-2.6-1.8-3.4-4.8-3.4h-4.3v11.2h2.5v-4.7m12.6-0.9c0-6.6-5.1-10.4-10.8-10.4s-10.8 3.8-10.8 10.4 5.1 10.4 10.8 10.4 10.8-3.8 10.8-10.4m-3.2 0c0.2 4.2-3.1 7.8-7.3 8h-0.3c-4.4 0.2-8.1-3.3-8.3-7.7s3.3-8.1 7.7-8.3 8.1 3.3 8.3 7.7c-0.1 0.1-0.1 0.2-0.1 0.3z"></path>
<path fill="#FFFFFF" d="m578.2 34v118h33.3v-118h-33.3zm-262-0.2v118.1h33.6v-91.7l26.2 0.1c8.6 0 14.6 2.1 18.7 6.5 5.3 5.6 7.4 14.7 7.4 31.2v53.9h32.6v-65.2c0-46.6-29.7-52.9-58.7-52.9h-59.8zm315.7 0.2v118h54c28.8 0 38.2-4.8 48.3-15.5 7.2-7.5 11.8-24.1 11.8-42.2 0-16.6-3.9-31.4-10.8-40.6-12.2-16.5-30-19.7-56.6-19.7h-46.7zm33 25.6h14.3c20.8 0 34.2 9.3 34.2 33.5s-13.4 33.6-34.2 33.6h-14.3v-67.1zm-134.7-25.6l-27.8 93.5-26.6-93.5h-36l38 118h48l38.4-118h-34zm231.4 118h33.3v-118h-33.3v118zm93.4-118l-46.5 117.9h32.8l7.4-20.9h55l7 20.8h35.7l-46.9-117.8h-44.5zm21.6 21.5l20.2 55.2h-41l20.8-55.2z">
</path>
<path fill="#76B900" d="m101.3 53.6v-16.2c1.6-0.1 3.2-0.2 4.8-0.2 44.4-1.4 73.5 38.2 73.5 38.2s-31.4 43.6-65.1 43.6c-4.5 0-8.9-0.7-13.1-2.1v-49.2c17.3 2.1 20.8 9.7 31.1 27l23.1-19.4s-16.9-22.1-45.3-22.1c-3-0.1-6 0.1-9 0.4m0-53.6v24.2l4.8-0.3c61.7-2.1 102 50.6 102 50.6s-46.2 56.2-94.3 56.2c-4.2 0-8.3-0.4-12.4-1.1v15c3.4 0.4 6.9 0.7 10.3 0.7 44.8 0 77.2-22.9 108.6-49.9 5.2 4.2 26.5 14.3 30.9 18.7-29.8 25-99.3 45.1-138.7 45.1-3.8 0-7.4-0.2-11-0.6v21.1h170.2v-179.7h-170.4zm0 116.9v12.8c-41.4-7.4-52.9-50.5-52.9-50.5s19.9-22 52.9-25.6v14h-0.1c-17.3-2.1-30.9 14.1-30.9 14.1s7.7 27.3 31 35.2m-73.5-39.5s24.5-36.2 73.6-40v-13.2c-54.4 4.4-101.4 50.4-101.4 50.4s26.6 77 101.3 84v-14c-54.8-6.8-73.5-67.2-73.5-67.2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,203 @@
<template>
<div class="flex flex-col gap-6 w-[600px] h-[30rem] select-none">
<!-- Installation Path Section -->
<div class="grow flex flex-col gap-4 text-neutral-300">
<h2 class="text-2xl font-semibold text-neutral-100">
{{ $t('install.gpuSelection.selectGpu') }}
</h2>
<p class="m-1 text-neutral-400">
{{ $t('install.gpuSelection.selectGpuDescription') }}:
</p>
<!-- GPU Selection buttons -->
<div
class="flex gap-2 text-center transition-opacity"
:class="{ selected: selected }"
>
<!-- NVIDIA -->
<div
v-if="platform !== 'darwin'"
class="gpu-button"
:class="{ selected: selected === 'nvidia' }"
role="button"
@click="pickGpu('nvidia')"
>
<img
class="m-12"
alt="NVIDIA logo"
width="196"
height="32"
src="/assets/images/nvidia-logo.svg"
/>
</div>
<!-- MPS -->
<div
v-if="platform === 'darwin'"
class="gpu-button"
:class="{ selected: selected === 'mps' }"
role="button"
@click="pickGpu('mps')"
>
<img
class="rounded-lg hover-brighten"
alt="Apple Metal Performance Shaders Logo"
width="292"
ratio
src="/assets/images/apple-mps-logo.png"
/>
</div>
<!-- Manual configuration -->
<div
class="gpu-button"
:class="{ selected: selected === 'unsupported' }"
role="button"
@click="pickGpu('unsupported')"
>
<img
class="m-12"
alt="Manual configuration"
width="196"
src="/assets/images/manual-configuration.svg"
/>
</div>
</div>
<!-- Details on selected GPU -->
<p v-if="selected === 'nvidia'" class="m-1">
<Tag icon="pi pi-check" severity="success" :value="'CUDA'" />
{{ $t('install.gpuSelection.nvidiaDescription') }}
</p>
<p v-if="selected === 'mps'" class="m-1">
<Tag icon="pi pi-check" severity="success" :value="'MPS'" />
{{ $t('install.gpuSelection.mpsDescription') }}
</p>
<div v-if="selected === 'unsupported'" class="text-neutral-300">
<p class="m-1">
<Tag
icon="pi pi-exclamation-triangle"
severity="warn"
:value="t('icon.exclamation-triangle')"
/>
{{ $t('install.gpuSelection.customSkipsPython') }}
</p>
<ul>
<li>
<strong>
{{ $t('install.gpuSelection.customComfyNeedsPython') }}
</strong>
</li>
<li>{{ $t('install.gpuSelection.customManualVenv') }}</li>
<li>{{ $t('install.gpuSelection.customInstallRequirements') }}</li>
<li>{{ $t('install.gpuSelection.customMayNotWork') }}</li>
</ul>
</div>
<div v-if="selected === 'cpu'">
<p class="m-1">
<Tag
icon="pi pi-exclamation-triangle"
severity="warn"
:value="t('icon.exclamation-triangle')"
></Tag>
{{ $t('install.gpuSelection.cpuModeDescription') }}
</p>
<p class="m-1">
{{ $t('install.gpuSelection.cpuModeDescription2') }}
</p>
</div>
</div>
<div
class="transition-opacity flex gap-3 h-0"
:class="{
'opacity-40': selected && selected !== 'cpu'
}"
>
<ToggleSwitch
v-model="cpuMode"
inputId="cpu-mode"
class="-translate-y-40"
/>
<label for="cpu-mode" class="select-none">
{{ $t('install.gpuSelection.enableCpuMode') }}
</label>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { electronAPI, TorchDeviceType } from '@/utils/envUtil'
import ToggleSwitch from 'primevue/toggleswitch'
import Tag from 'primevue/tag'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const cpuMode = computed({
get: () => selected.value === 'cpu',
set: (value) => {
selected.value = value ? 'cpu' : null
}
})
const selected = defineModel<TorchDeviceType>('device', {
required: true
})
const electron = electronAPI()
const platform = electron.getPlatform()
const pickGpu = (value: typeof selected.value) => {
const newValue = selected.value === value ? null : value
selected.value = newValue
}
</script>
<style lang="postcss">
:root {
--p-tag-gap: 0.5rem;
}
.hover-brighten {
@apply transition-colors;
transition-property: filter, box-shadow;
&:hover {
filter: brightness(107%) contrast(105%);
box-shadow: 0 0 0.25rem #ffffff79;
}
}
.p-accordioncontent-content {
@apply bg-neutral-900 rounded-lg transition-colors;
}
div.selected {
.gpu-button:not(.selected) {
@apply opacity-50 hover:opacity-100;
}
}
.gpu-button {
@apply w-1/2 m-0 cursor-pointer rounded-lg flex flex-col items-center justify-around bg-neutral-800 bg-opacity-50 hover:bg-opacity-75 transition-colors;
&.selected {
@apply opacity-100 bg-neutral-700 bg-opacity-50 hover:bg-opacity-60;
}
}
.disabled {
@apply pointer-events-none opacity-40;
}
.p-card-header {
@apply text-center grow;
}
.p-card-body {
@apply text-center pt-0;
}
</style>

View File

@@ -78,7 +78,8 @@
"file": "File",
"inbox": "Inbox",
"box": "Box",
"briefcase": "Briefcase"
"briefcase": "Briefcase",
"exclamation-triangle": "Warning"
},
"welcome": {
"title": "Welcome to ComfyUI",
@@ -129,6 +130,22 @@
"migrationOptional": "Migration is optional. If you don't have an existing installation, you can skip this step.",
"desktopAppSettings": "Desktop App Settings",
"desktopAppSettingsDescription": "Configure how ComfyUI behaves on your desktop. You can change these settings later.",
"gpu": "GPU",
"gpuSelection": {
"selectGpu": "Select GPU",
"selectGpuDescription": "Select the type of GPU you have",
"cpuMode": "CPU Mode",
"cpuModeDescription": "CPU mode is intended for developers and rare edge cases only.",
"cpuModeDescription2": "If you are not absolutely certain you need this, please ignore this box and select your GPU above.",
"enableCpuMode": "Enable CPU Mode",
"nvidiaDescription": "NVIDIA devices are directly supported using pytorch CUDA builds.",
"mpsDescription": "Apple Metal Performance Shaders are supported using pytorch nightly.",
"customSkipsPython": "This option skips the normal python setup.",
"customComfyNeedsPython": "ComfyUI will not work until python is setup",
"customManualVenv": "Manually configure python venv",
"customInstallRequirements": "Install all requirements and dependencies (e.g. custom torch)",
"customMayNotWork": "This is entirely unsupported, and may simply not work"
},
"settings": {
"autoUpdate": "Automatic Updates",
"allowMetrics": "Crash Reports",

View File

@@ -141,6 +141,7 @@
"bookmark": "ブックマーク",
"box": "ボックス",
"briefcase": "ブリーフケース",
"exclamation-triangle": "警告",
"file": "ファイル",
"folder": "フォルダー",
"heart": "ハート",
@@ -157,6 +158,22 @@
"desktopAppSettingsDescription": "ComfyUIのデスクトップでの動作を設定します。これらの設定は後で変更可能です。",
"desktopSettings": "デスクトップ設定",
"failedToSelectDirectory": "ディレクトリの選択に失敗しました",
"gpu": "GPU",
"gpuSelection": {
"cpuMode": "CPUモード",
"cpuModeDescription": "CPUモードは開発者やまれなエッジケースのみを対象としています。",
"cpuModeDescription2": "これが絶対に必要であることが確定していない場合は、このボックスを無視して上でGPUを選択してください。",
"customComfyNeedsPython": "ComfyUIはpythonがセットアップされるまで動作しません",
"customInstallRequirements": "すべての要件と依存関係をインストールするカスタムtorch",
"customManualVenv": "python venvを手動で設定する",
"customMayNotWork": "これは完全にサポートされておらず、単純に動作しない場合があります。",
"customSkipsPython": "このオプションは通常のpythonセットアップをスキップします。",
"enableCpuMode": "CPUモードを有効にする",
"mpsDescription": "Apple Metal Performance Shadersは、pytorch nightlyを使用してサポートされています。",
"nvidiaDescription": "NVIDIAデバイスは、pytorch CUDAビルドを使用して直接サポートされています。",
"selectGpu": "GPUを選択",
"selectGpuDescription": "所有しているGPUのタイプを選択してください"
},
"installLocation": "インストール先",
"installLocationDescription": "ComfyUIのユーザーデータを保存するディレクトリを選択してください。Python環境が選択した場所にインストールされます。選択したディスクに約15GBの空き容量が必要です。",
"installLocationTooltip": "ComfyUIのユーザーデータディレクトリ。保存内容:\n- Python環境\n- モデル\n- カスタムノード\n",

View File

@@ -141,6 +141,7 @@
"bookmark": "북마크",
"box": "상자",
"briefcase": "서류가방",
"exclamation-triangle": "경고",
"file": "파일",
"folder": "폴더",
"heart": "하트",
@@ -157,6 +158,22 @@
"desktopAppSettingsDescription": "ComfyUI가 데스크탑에서 어떻게 작동하는지 구성하세요. 이 설정은 나중에 변경할 수 있습니다.",
"desktopSettings": "데스크탑 설정",
"failedToSelectDirectory": "디렉토리 선택 실패",
"gpu": "GPU",
"gpuSelection": {
"cpuMode": "CPU 모드",
"cpuModeDescription": "CPU 모드는 개발자와 드문 경우에만 사용됩니다.",
"cpuModeDescription2": "이것이 필요한지 확실하지 않다면, 이 상자를 무시하고 위에서 GPU를 선택하세요.",
"customComfyNeedsPython": "파이썬이 설정되지 않으면 ComfyUI가 작동하지 않습니다",
"customInstallRequirements": "모든 요구 사항과 종속성 설치 (예: 사용자 정의 torch)",
"customManualVenv": "파이썬 venv를 수동으로 구성",
"customMayNotWork": "이것은 전혀 지원되지 않으며, 작동하지 않을 수 있습니다",
"customSkipsPython": "이 옵션은 일반 파이썬 설정을 건너뜁니다.",
"enableCpuMode": "CPU 모드 활성화",
"mpsDescription": "Apple Metal Performance Shaders는 pytorch nightly를 사용하여 지원됩니다.",
"nvidiaDescription": "NVIDIA 장치는 pytorch CUDA 빌드를 사용하여 직접 지원됩니다.",
"selectGpu": "GPU 선택",
"selectGpuDescription": "소유한 GPU 유형을 선택하세요"
},
"installLocation": "설치 위치",
"installLocationDescription": "ComfyUI의 사용자 데이터 디렉토리를 선택하십시오. 선택한 위치에 Python 환경이 설치됩니다. 선택한 디스크에 충분한 공간(~15GB)이 남아 있는지 확인하십시오.",
"installLocationTooltip": "ComfyUI의 사용자 데이터 디렉토리. 저장소:\n- Python 환경\n- 모델\n- 사용자 정의 노드\n",

View File

@@ -141,6 +141,7 @@
"bookmark": "Закладка",
"box": "Коробка",
"briefcase": "Портфель",
"exclamation-triangle": "Предупреждение",
"file": "Файл",
"folder": "Папка",
"heart": "Сердце",
@@ -157,6 +158,22 @@
"desktopAppSettingsDescription": "Настройте, как ComfyUI ведет себя на вашем рабочем столе. Вы можете изменить эти настройки позже.",
"desktopSettings": "Настройки рабочего стола",
"failedToSelectDirectory": "Не удалось выбрать директорию",
"gpu": "GPU",
"gpuSelection": {
"cpuMode": "Режим CPU",
"cpuModeDescription": "Режим CPU предназначен только для разработчиков и редких крайних случаев.",
"cpuModeDescription2": "Если вы не абсолютно уверены, что вам это нужно, пожалуйста, проигнорируйте эту галочку и выберите ваш GPU выше.",
"customComfyNeedsPython": "ComfyUI не будет работать, пока python не будет настроен",
"customInstallRequirements": "Установите все требования и зависимости (например, custom torch)",
"customManualVenv": "Вручную настроить python venv",
"customMayNotWork": "Это полностью не поддерживается и может просто не работать",
"customSkipsPython": "Этот вариант пропускает обычную настройку python.",
"enableCpuMode": "Включить режим CPU",
"mpsDescription": "Поддерживаются Apple Metal Performance Shaders с использованием pytorch nightly.",
"nvidiaDescription": "Устройства NVIDIA напрямую поддерживаются с использованием сборок pytorch CUDA.",
"selectGpu": "Выберите GPU",
"selectGpuDescription": "Выберите тип GPU, который у вас есть"
},
"installLocation": "Место установки",
"installLocationDescription": "Выберите директорию для пользовательских данных ComfyUI. В выбранном месте будет установлена среда Python. Пожалуйста, убедитесь, что на выбранном диске достаточно места (~15 ГБ).",
"installLocationTooltip": "Директория пользовательских данных ComfyUI. Хранит:\n- Среда Python\n- Модели\n- Пользовательские узлы\n",

View File

@@ -141,6 +141,7 @@
"bookmark": "书签",
"box": "盒子",
"briefcase": "公文包",
"exclamation-triangle": "警告",
"file": "文件",
"folder": "文件夹",
"heart": "心",
@@ -157,6 +158,22 @@
"desktopAppSettingsDescription": "配置 ComfyUI 在桌面上的行为。您可以稍后更改这些设置。",
"desktopSettings": "桌面设置",
"failedToSelectDirectory": "选择目录失败",
"gpu": "GPU",
"gpuSelection": {
"cpuMode": "CPU 模式",
"cpuModeDescription": "CPU 模式仅适用于开发者和极少数特殊情况。",
"cpuModeDescription2": "如果你不完全确定你需要这个,请忽略这个选项并在上面选择你的 GPU。",
"customComfyNeedsPython": "在 python 设置之前ComfyUI 将无法工作",
"customInstallRequirements": "安装所有需求和依赖项(例如:自定义 torch",
"customManualVenv": "手动配置 python venv",
"customMayNotWork": "这完全不受支持,可能根本无法工作",
"customSkipsPython": "此选项跳过正常的 python 设置。",
"enableCpuMode": "启用 CPU 模式",
"mpsDescription": "Apple Metal Performance Shaders 使用 pytorch nightly 支持。",
"nvidiaDescription": "NVIDIA 设备直接支持使用 pytorch CUDA 构建。",
"selectGpu": "选择 GPU",
"selectGpuDescription": "选择你拥有的 GPU 类型"
},
"installLocation": "安装位置",
"installLocationDescription": "选择 ComfyUI 用户数据的目录。将安装一个 Python 环境到所选位置。请确保所选磁盘有足够的空间(约 15GB。",
"installLocationTooltip": "ComfyUI 的用户数据目录。存储:\n- Python 环境\n- 模型\n- 自定义节点\n",

View File

@@ -1,5 +1,8 @@
import { ElectronAPI } from '@comfyorg/comfyui-electron-types'
export type InstallOptions = Parameters<ElectronAPI['installComfyUI']>[0]
export type TorchDeviceType = InstallOptions['device']
export function isElectron() {
return 'electronAPI' in window && window['electronAPI'] !== undefined
}

View File

@@ -2,25 +2,46 @@
<div
class="font-sans flex flex-col items-center h-screen m-0 text-neutral-300 bg-neutral-900 dark-theme pointer-events-auto"
>
<Stepper class="mt-[5vh] 2xl:mt-[20vh]" value="1">
<StepList>
<Step value="1" :disabled="hasError">
<Stepper class="stepper" value="0" @update:value="setHighestStep">
<StepList class="select-none">
<Step value="0">
{{ $t('install.gpu') }}
</Step>
<Step value="1" :disabled="noGpu">
{{ $t('install.installLocation') }}
</Step>
<Step value="2" :disabled="hasError">
<Step value="2" :disabled="noGpu || hasError || highestStep < 1">
{{ $t('install.migration') }}
</Step>
<Step value="3" :disabled="hasError">
<Step value="3" :disabled="noGpu || hasError || highestStep < 2">
{{ $t('install.desktopSettings') }}
</Step>
</StepList>
<StepPanels>
<StepPanel value="0" v-slot="{ activateCallback }">
<GpuPicker v-model:device="device" />
<div class="flex pt-6 justify-end">
<Button
label="Next"
icon="pi pi-arrow-right"
iconPos="right"
@click="activateCallback('1')"
:disabled="typeof device !== 'string'"
/>
</div>
</StepPanel>
<StepPanel value="1" v-slot="{ activateCallback }">
<InstallLocationPicker
v-model:installPath="installPath"
v-model:pathError="pathError"
/>
<div class="flex pt-6 justify-end">
<div class="flex pt-6 justify-between">
<Button
label="Back"
severity="secondary"
icon="pi pi-arrow-left"
@click="activateCallback('0')"
/>
<Button
label="Next"
icon="pi pi-arrow-right"
@@ -87,9 +108,16 @@ import StepPanel from 'primevue/steppanel'
import InstallLocationPicker from '@/components/install/InstallLocationPicker.vue'
import MigrationPicker from '@/components/install/MigrationPicker.vue'
import DesktopSettingsConfiguration from '@/components/install/DesktopSettingsConfiguration.vue'
import { electronAPI } from '@/utils/envUtil'
import { ref, computed, toRaw } from 'vue'
import {
electronAPI,
type InstallOptions,
type TorchDeviceType
} from '@/utils/envUtil'
import { ref, computed, toRaw, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import GpuPicker from '@/components/install/GpuPicker.vue'
const device = ref<TorchDeviceType>(null)
const installPath = ref('')
const pathError = ref('')
@@ -100,24 +128,47 @@ const migrationItemIds = ref<string[]>([])
const autoUpdate = ref(true)
const allowMetrics = ref(true)
const hasError = computed(() => pathError.value !== '')
/** Forces each install step to be visited at least once. */
const highestStep = ref(0)
const setHighestStep = (value: string | number) => {
const int = typeof value === 'number' ? value : parseInt(value, 10)
if (!isNaN(int) && int > highestStep.value) highestStep.value = int
}
const hasError = computed(() => pathError.value !== '')
const noGpu = computed(() => typeof device.value !== 'string')
const electron = electronAPI()
const router = useRouter()
const install = () => {
const options = toRaw({
const options: InstallOptions = {
installPath: installPath.value,
autoUpdate: autoUpdate.value,
allowMetrics: allowMetrics.value,
migrationSourcePath: migrationSourcePath.value,
migrationItemIds: toRaw(migrationItemIds.value)
})
electronAPI().installComfyUI(options)
migrationItemIds: toRaw(migrationItemIds.value),
device: device.value
}
electron.installComfyUI(options)
router.push('/server-start')
}
onMounted(async () => {
if (!electron) return
const detectedGpu = await electron.Config.getDetectedGpu()
if (detectedGpu === 'mps' || detectedGpu === 'nvidia')
device.value = detectedGpu
})
</script>
<style scoped>
<style lang="postcss" scoped>
:deep(.p-steppanel) {
@apply bg-transparent;
}
.stepper {
margin-top: max(1rem, max(0px, calc((100vh - 42rem) * 0.5)));
}
</style>

View File

@@ -1,58 +1,58 @@
<template>
<div
class="font-sans w-screen h-screen flex items-center m-0 text-neutral-900 bg-neutral-300 pointer-events-auto"
class="font-sans w-screen h-screen flex items-center justify-around m-0 text-neutral-900 bg-neutral-300 pointer-events-auto"
>
<div class="flex-grow flex items-center justify-center">
<div class="flex flex-col gap-8 p-8">
<!-- Header -->
<h1 class="text-4xl font-bold text-red-500">
{{ $t('notSupported.title') }}
</h1>
<!-- Message -->
<div class="space-y-4">
<p class="text-xl">
{{ $t('notSupported.message') }}
</p>
<ul class="list-disc list-inside space-y-1 text-neutral-800">
<li>{{ $t('notSupported.supportedDevices.macos') }}</li>
<li>{{ $t('notSupported.supportedDevices.windows') }}</li>
</ul>
</div>
<!-- Actions -->
<div class="flex gap-4">
<Button
:label="$t('notSupported.learnMore')"
icon="pi pi-github"
@click="openDocs"
severity="secondary"
/>
<Button
:label="$t('notSupported.reportIssue')"
icon="pi pi-flag"
@click="reportIssue"
severity="secondary"
/>
<Button
:label="$t('notSupported.continue')"
icon="pi pi-arrow-right"
iconPos="right"
@click="continueToInstall"
severity="danger"
v-tooltip="$t('notSupported.continueTooltip')"
/>
</div>
</div>
</div>
<!-- Right side image -->
<div class="h-screen flex-grow-0">
<div class="sad-container">
<!-- Right side image -->
<img
class="sad-girl"
src="/assets/images/sad_girl.png"
alt="Sad girl illustration"
class="h-full object-cover"
/>
<div class="no-drag sad-text flex items-center">
<div class="flex flex-col gap-8 p-8 min-w-110">
<!-- Header -->
<h1 class="text-4xl font-bold text-red-500">
{{ $t('notSupported.title') }}
</h1>
<!-- Message -->
<div class="space-y-4">
<p class="text-xl">
{{ $t('notSupported.message') }}
</p>
<ul class="list-disc list-inside space-y-1 text-neutral-800">
<li>{{ $t('notSupported.supportedDevices.macos') }}</li>
<li>{{ $t('notSupported.supportedDevices.windows') }}</li>
</ul>
</div>
<!-- Actions -->
<div class="flex gap-4">
<Button
:label="$t('notSupported.learnMore')"
icon="pi pi-github"
@click="openDocs"
severity="secondary"
/>
<Button
:label="$t('notSupported.reportIssue')"
icon="pi pi-flag"
@click="reportIssue"
severity="secondary"
/>
<Button
:label="$t('notSupported.continue')"
icon="pi pi-arrow-right"
iconPos="right"
@click="continueToInstall"
severity="danger"
v-tooltip="$t('notSupported.continueTooltip')"
/>
</div>
</div>
</div>
</div>
</div>
</template>
@@ -77,3 +77,23 @@ const continueToInstall = () => {
router.push('/install')
}
</script>
<style>
.sad-container {
@apply grid items-center justify-evenly;
grid-template-columns: 25rem 1fr;
& > * {
grid-row: 1;
}
}
.sad-text {
grid-column: 1/3;
}
.sad-girl {
grid-column: 2/3;
width: min(75vw, 100vh);
}
</style>