refactor: expose download phase from composable, fix library-select gate

- Add `phase` (none/active/stopped) to useElectronDownload so consumers
  don't have to duplicate the DownloadStatus taxonomy. The classification
  now lives with the rest of the electronDownload domain.
- MissingModelRow: replace activeElectronDownload/stoppedElectronDownload
  computeds with the phase discriminator.
- Fix the library-select gate: previously `!electronDownload` left the
  combo permanently hidden for any URL that had ever started a download
  (including completed, cancelled, and errored states that still hold a
  store entry). Tighten to `phase === 'none'` so the combo reappears when
  the Download button does — matching the intended mutual-exclusivity with
  progress/stopped notice.
This commit is contained in:
jaeone94
2026-04-22 17:08:45 +09:00
parent f12853ec74
commit 611ec191fb
2 changed files with 34 additions and 21 deletions

View File

@@ -1,8 +1,22 @@
import { DownloadStatus } from '@comfyorg/comfyui-electron-types'
import { computed, toValue } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
import { useElectronDownloadStore } from '@/platform/electronDownload/electronDownloadStore'
/**
* Classification of the download's current status from a UI-slot perspective:
* - `none` — no entry exists for this URL; render the Download action.
* - `active` — download is live (pending/in-progress/paused/completed);
* render the progress UI.
* - `stopped` — download finished in a non-success terminal state
* (cancelled/error); render the stopped notice.
*
* Exposed from the composable so consumers don't have to duplicate the
* DownloadStatus taxonomy.
*/
export type ElectronDownloadPhase = 'none' | 'active' | 'stopped'
export function useElectronDownload(url: MaybeRefOrGetter<string | undefined>) {
const store = useElectronDownloadStore()
@@ -11,6 +25,18 @@ export function useElectronDownload(url: MaybeRefOrGetter<string | undefined>) {
return value ? store.findByUrl(value) : undefined
})
const phase = computed<ElectronDownloadPhase>(() => {
const dl = download.value
if (!dl) return 'none'
if (
dl.status === DownloadStatus.CANCELLED ||
dl.status === DownloadStatus.ERROR
) {
return 'stopped'
}
return 'active'
})
const withUrl = (action: (url: string) => unknown) => () => {
const value = toValue(url)
if (value) action(value)
@@ -18,6 +44,7 @@ export function useElectronDownload(url: MaybeRefOrGetter<string | undefined>) {
return {
download,
phase,
pause: withUrl(store.pause),
resume: withUrl(store.resume),
cancel: withUrl(store.cancel),

View File

@@ -152,13 +152,13 @@
class="flex w-full items-start py-1"
>
<ElectronDownloadProgress
v-if="activeElectronDownload"
:download="activeElectronDownload"
v-if="electronDownloadPhase === 'active' && electronDownload"
:download="electronDownload"
class="w-full"
/>
<ElectronDownloadStoppedNotice
v-else-if="stoppedElectronDownload"
:download="stoppedElectronDownload"
v-else-if="electronDownloadPhase === 'stopped' && electronDownload"
:download="electronDownload"
@retry="handleDownload"
/>
<Button
@@ -182,7 +182,7 @@
<TransitionCollapse>
<MissingModelLibrarySelect
v-if="!urlInputs[modelKey] && !electronDownload"
v-if="!urlInputs[modelKey] && electronDownloadPhase === 'none'"
:model-value="getComboValue(model.representative)"
:options="comboOptions"
:show-divider="isAssetSupported || downloadable"
@@ -244,22 +244,8 @@ const modelKey = computed(() =>
getModelStateKey(model.name, directory, isAssetSupported)
)
const { download: electronDownload } = useElectronDownload(
() => model.representative.url
)
const activeElectronDownload = computed(() => {
const dl = electronDownload.value
if (!dl) return undefined
if (dl.status === 'cancelled' || dl.status === 'error') return undefined
return dl
})
const stoppedElectronDownload = computed(() => {
const dl = electronDownload.value
if (dl?.status === 'cancelled' || dl?.status === 'error') return dl
return undefined
})
const { download: electronDownload, phase: electronDownloadPhase } =
useElectronDownload(() => model.representative.url)
const downloadStatus = computed(() => getDownloadStatus(modelKey.value))
const comboOptions = computed(() => getComboOptions(model.representative))