mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-20 23:04:06 +00:00
[backport cloud/1.38] feat: remove obsolete model asset feature flags (#8568)
Backport of #8566 to `cloud/1.38` Automatically created by backport workflow. Co-authored-by: Luke Mino-Altherr <luke@comfy.org> Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -15,13 +15,10 @@ export enum ServerFeatureFlag {
|
||||
MAX_UPLOAD_SIZE = 'max_upload_size',
|
||||
MANAGER_SUPPORTS_V4 = 'extension.manager.supports_v4',
|
||||
MODEL_UPLOAD_BUTTON_ENABLED = 'model_upload_button_enabled',
|
||||
ASSET_DELETION_ENABLED = 'asset_deletion_enabled',
|
||||
ASSET_RENAME_ENABLED = 'asset_rename_enabled',
|
||||
PRIVATE_MODELS_ENABLED = 'private_models_enabled',
|
||||
ONBOARDING_SURVEY_ENABLED = 'onboarding_survey_enabled',
|
||||
HUGGINGFACE_MODEL_IMPORT_ENABLED = 'huggingface_model_import_enabled',
|
||||
LINEAR_TOGGLE_ENABLED = 'linear_toggle_enabled',
|
||||
ASYNC_MODEL_UPLOAD_ENABLED = 'async_model_upload_enabled',
|
||||
TEAM_WORKSPACES_ENABLED = 'team_workspaces_enabled',
|
||||
USER_SECRETS_ENABLED = 'user_secrets_enabled'
|
||||
}
|
||||
@@ -41,7 +38,6 @@ export function useFeatureFlags() {
|
||||
return api.getServerFeature(ServerFeatureFlag.MANAGER_SUPPORTS_V4)
|
||||
},
|
||||
get modelUploadButtonEnabled() {
|
||||
// Check remote config first (from /api/features), fall back to websocket feature flags
|
||||
return (
|
||||
remoteConfig.value.model_upload_button_enabled ??
|
||||
api.getServerFeature(
|
||||
@@ -50,12 +46,6 @@ export function useFeatureFlags() {
|
||||
)
|
||||
)
|
||||
},
|
||||
get assetDeletionEnabled() {
|
||||
return (
|
||||
remoteConfig.value.asset_deletion_enabled ??
|
||||
api.getServerFeature(ServerFeatureFlag.ASSET_DELETION_ENABLED, false)
|
||||
)
|
||||
},
|
||||
get assetRenameEnabled() {
|
||||
return (
|
||||
remoteConfig.value.asset_rename_enabled ??
|
||||
@@ -63,7 +53,6 @@ export function useFeatureFlags() {
|
||||
)
|
||||
},
|
||||
get privateModelsEnabled() {
|
||||
// Check remote config first (from /api/features), fall back to websocket feature flags
|
||||
return (
|
||||
remoteConfig.value.private_models_enabled ??
|
||||
api.getServerFeature(ServerFeatureFlag.PRIVATE_MODELS_ENABLED, false)
|
||||
@@ -75,30 +64,12 @@ export function useFeatureFlags() {
|
||||
api.getServerFeature(ServerFeatureFlag.ONBOARDING_SURVEY_ENABLED, true)
|
||||
)
|
||||
},
|
||||
get huggingfaceModelImportEnabled() {
|
||||
return (
|
||||
remoteConfig.value.huggingface_model_import_enabled ??
|
||||
api.getServerFeature(
|
||||
ServerFeatureFlag.HUGGINGFACE_MODEL_IMPORT_ENABLED,
|
||||
false
|
||||
)
|
||||
)
|
||||
},
|
||||
get linearToggleEnabled() {
|
||||
return (
|
||||
remoteConfig.value.linear_toggle_enabled ??
|
||||
api.getServerFeature(ServerFeatureFlag.LINEAR_TOGGLE_ENABLED, false)
|
||||
)
|
||||
},
|
||||
get asyncModelUploadEnabled() {
|
||||
return (
|
||||
remoteConfig.value.async_model_upload_enabled ??
|
||||
api.getServerFeature(
|
||||
ServerFeatureFlag.ASYNC_MODEL_UPLOAD_ENABLED,
|
||||
false
|
||||
)
|
||||
)
|
||||
},
|
||||
/**
|
||||
* Whether team workspaces feature is enabled.
|
||||
* IMPORTANT: Returns false until authenticated remote config is loaded.
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
>
|
||||
<template #default>
|
||||
<Button
|
||||
v-if="flags.assetDeletionEnabled"
|
||||
variant="secondary"
|
||||
size="md"
|
||||
class="justify-start"
|
||||
@@ -141,7 +140,6 @@ import MoreButton from '@/components/button/MoreButton.vue'
|
||||
import StatusBadge from '@/components/common/StatusBadge.vue'
|
||||
import { showConfirmDialog } from '@/components/dialog/confirm/confirmDialog'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import AssetBadgeGroup from '@/platform/assets/components/AssetBadgeGroup.vue'
|
||||
import type { AssetDisplayItem } from '@/platform/assets/composables/useAssetBrowser'
|
||||
import { assetService } from '@/platform/assets/services/assetService'
|
||||
@@ -167,7 +165,6 @@ const emit = defineEmits<{
|
||||
const { t } = useI18n()
|
||||
const settingStore = useSettingStore()
|
||||
const { closeDialog } = useDialogStore()
|
||||
const { flags } = useFeatureFlags()
|
||||
const { isDownloadedThisSession, acknowledgeAsset } = useAssetDownloadStore()
|
||||
|
||||
const dropdownMenuButton = useTemplateRef<InstanceType<typeof MoreButton>>(
|
||||
@@ -181,11 +178,7 @@ const displayName = computed(() => getAssetDisplayName(asset))
|
||||
|
||||
const isNewlyImported = computed(() => isDownloadedThisSession(asset.id))
|
||||
|
||||
const showAssetOptions = computed(
|
||||
() =>
|
||||
(flags.assetDeletionEnabled || flags.assetRenameEnabled) &&
|
||||
!(asset.is_immutable ?? true)
|
||||
)
|
||||
const showAssetOptions = computed(() => !(asset.is_immutable ?? true))
|
||||
|
||||
const tooltipDelay = computed<number>(() =>
|
||||
settingStore.get('LiteGraph.Node.TooltipDelay')
|
||||
|
||||
@@ -6,12 +6,7 @@
|
||||
<div class="min-h-0 flex-auto basis-0 overflow-y-auto">
|
||||
<!-- Step 1: Enter URL -->
|
||||
<UploadModelUrlInput
|
||||
v-if="currentStep === 1 && flags.huggingfaceModelImportEnabled"
|
||||
v-model="wizardData.url"
|
||||
:error="uploadError"
|
||||
/>
|
||||
<UploadModelUrlInputCivitai
|
||||
v-else-if="currentStep === 1"
|
||||
v-if="currentStep === 1"
|
||||
v-model="wizardData.url"
|
||||
:error="uploadError"
|
||||
/>
|
||||
@@ -56,17 +51,14 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import UploadModelConfirmation from '@/platform/assets/components/UploadModelConfirmation.vue'
|
||||
import UploadModelFooter from '@/platform/assets/components/UploadModelFooter.vue'
|
||||
import UploadModelProgress from '@/platform/assets/components/UploadModelProgress.vue'
|
||||
import UploadModelUrlInput from '@/platform/assets/components/UploadModelUrlInput.vue'
|
||||
import UploadModelUrlInputCivitai from '@/platform/assets/components/UploadModelUrlInputCivitai.vue'
|
||||
import { useModelTypes } from '@/platform/assets/composables/useModelTypes'
|
||||
import { useUploadModelWizard } from '@/platform/assets/composables/useUploadModelWizard'
|
||||
import { useDialogStore } from '@/stores/dialogStore'
|
||||
|
||||
const { flags } = useFeatureFlags()
|
||||
const dialogStore = useDialogStore()
|
||||
const { modelTypes, fetchModelTypes } = useModelTypes()
|
||||
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<template>
|
||||
<div class="flex items-center gap-2 p-4 font-bold">
|
||||
<img
|
||||
v-if="!flags.huggingfaceModelImportEnabled"
|
||||
src="/assets/images/civitai.svg"
|
||||
class="size-4"
|
||||
/>
|
||||
<span>{{ $t(titleKey) }}</span>
|
||||
<span>{{ $t('assetBrowser.uploadModelGeneric') }}</span>
|
||||
<span
|
||||
class="rounded-full bg-white px-1.5 py-0 text-xxs font-inter font-semibold uppercase text-black"
|
||||
>
|
||||
@@ -13,17 +8,3 @@
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
|
||||
const { flags } = useFeatureFlags()
|
||||
|
||||
const titleKey = computed(() => {
|
||||
return flags.huggingfaceModelImportEnabled
|
||||
? 'assetBrowser.uploadModelGeneric'
|
||||
: 'assetBrowser.uploadModelFromCivitai'
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<template>
|
||||
<div class="flex justify-end gap-2 w-full">
|
||||
<div
|
||||
v-if="currentStep === 1 && flags.huggingfaceModelImportEnabled"
|
||||
class="mr-auto flex items-center gap-2"
|
||||
>
|
||||
<div v-if="currentStep === 1" class="mr-auto flex items-center gap-2">
|
||||
<i class="icon-[lucide--circle-question-mark] text-muted-foreground" />
|
||||
<Button
|
||||
variant="muted-textonly"
|
||||
@@ -22,17 +19,6 @@
|
||||
{{ $t('assetBrowser.providerHuggingFace') }}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
v-else-if="currentStep === 1"
|
||||
variant="muted-textonly"
|
||||
size="lg"
|
||||
class="mr-auto underline"
|
||||
data-attr="upload-model-step1-help-link"
|
||||
@click="showCivitaiHelp = true"
|
||||
>
|
||||
<i class="icon-[lucide--circle-question-mark]" />
|
||||
<span>{{ $t('assetBrowser.uploadModelHowDoIFindThis') }}</span>
|
||||
</Button>
|
||||
<Button
|
||||
v-if="currentStep === 1"
|
||||
variant="muted-textonly"
|
||||
@@ -124,11 +110,8 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import VideoHelpDialog from '@/platform/assets/components/VideoHelpDialog.vue'
|
||||
|
||||
const { flags } = useFeatureFlags()
|
||||
|
||||
const showCivitaiHelp = ref(false)
|
||||
const showHuggingFaceHelp = ref(false)
|
||||
|
||||
|
||||
@@ -55,15 +55,6 @@
|
||||
<p v-if="error" class="text-sm text-error">
|
||||
{{ error }}
|
||||
</p>
|
||||
<p v-else-if="!flags.asyncModelUploadEnabled" class="text-foreground">
|
||||
<i18n-t keypath="assetBrowser.maxFileSize" tag="span">
|
||||
<template #size>
|
||||
<span class="font-bold italic">{{
|
||||
$t('assetBrowser.maxFileSizeValue')
|
||||
}}</span>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-6 text-sm text-muted-foreground">
|
||||
<div class="flex flex-col gap-2">
|
||||
<p class="m-0">
|
||||
{{ $t('assetBrowser.uploadModelDescription1') }}
|
||||
</p>
|
||||
<ul class="list-disc space-y-1 pl-5 mt-0">
|
||||
<li>
|
||||
<i18n-t keypath="assetBrowser.uploadModelDescription2" tag="span">
|
||||
<template #link>
|
||||
<a
|
||||
href="https://civitai.com/models"
|
||||
target="_blank"
|
||||
class="text-muted-foreground underline"
|
||||
>
|
||||
{{ $t('assetBrowser.uploadModelDescription2Link') }}
|
||||
</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</li>
|
||||
<li v-if="!flags.asyncModelUploadEnabled">
|
||||
<i18n-t keypath="assetBrowser.uploadModelDescription3" tag="span">
|
||||
<template #size>
|
||||
<span class="font-bold italic">{{
|
||||
$t('assetBrowser.maxFileSizeValue')
|
||||
}}</span>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<i18n-t keypath="assetBrowser.civitaiLinkLabel" tag="label" class="mb-0">
|
||||
<template #download>
|
||||
<span class="font-bold italic">{{
|
||||
$t('assetBrowser.civitaiLinkLabelDownload')
|
||||
}}</span>
|
||||
</template>
|
||||
</i18n-t>
|
||||
<InputText
|
||||
v-model="url"
|
||||
autofocus
|
||||
:placeholder="$t('assetBrowser.civitaiLinkPlaceholder')"
|
||||
class="w-full border-0 bg-secondary-background p-4"
|
||||
data-attr="upload-model-step1-url-input"
|
||||
/>
|
||||
<p v-if="error" class="text-sm text-error">
|
||||
{{ error }}
|
||||
</p>
|
||||
<i18n-t
|
||||
v-else
|
||||
keypath="assetBrowser.civitaiLinkExample"
|
||||
tag="p"
|
||||
class="text-sm"
|
||||
>
|
||||
<template #example>
|
||||
<strong>{{ $t('assetBrowser.civitaiLinkExampleStrong') }}</strong>
|
||||
</template>
|
||||
<template #link>
|
||||
<a
|
||||
href="https://civitai.com/models/10706/luisap-z-image-and-qwen-pixel-art-refiner?modelVersionId=2225295"
|
||||
target="_blank"
|
||||
class="text-muted-foreground underline"
|
||||
>
|
||||
{{ $t('assetBrowser.civitaiLinkExampleUrl') }}
|
||||
</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
|
||||
<div v-if="showSecretsHint" class="text-sm text-muted">
|
||||
<i18n-t keypath="assetBrowser.apiKeyHint" tag="span">
|
||||
<template #link>
|
||||
<Button
|
||||
variant="textonly"
|
||||
size="unset"
|
||||
class="text-muted underline p-0"
|
||||
@click="openSecretsSettings"
|
||||
>
|
||||
{{ $t('assetBrowser.apiKeyHintLink') }}
|
||||
</Button>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import InputText from 'primevue/inputtext'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
|
||||
const { flags } = useFeatureFlags()
|
||||
const dialogService = useDialogService()
|
||||
|
||||
const showSecretsHint = computed(() => flags.userSecretsEnabled)
|
||||
|
||||
function openSecretsSettings() {
|
||||
dialogService.showSettingsDialog('secrets')
|
||||
}
|
||||
|
||||
defineProps<{
|
||||
error?: string
|
||||
}>()
|
||||
|
||||
const url = defineModel<string>({ required: true })
|
||||
</script>
|
||||
@@ -1,10 +1,11 @@
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import UploadModelDialog from '@/platform/assets/components/UploadModelDialog.vue'
|
||||
import UploadModelDialogHeader from '@/platform/assets/components/UploadModelDialogHeader.vue'
|
||||
import UploadModelUpgradeModal from '@/platform/assets/components/UploadModelUpgradeModal.vue'
|
||||
import UploadModelUpgradeModalHeader from '@/platform/assets/components/UploadModelUpgradeModalHeader.vue'
|
||||
import { useDialogStore } from '@/stores/dialogStore'
|
||||
import { computed } from 'vue'
|
||||
|
||||
export function useModelUpload(
|
||||
onUploadSuccess?: () => Promise<unknown> | void
|
||||
@@ -15,7 +16,6 @@ export function useModelUpload(
|
||||
|
||||
function showUploadDialog() {
|
||||
if (!flags.privateModelsEnabled) {
|
||||
// Show upgrade modal if private models are disabled
|
||||
dialogStore.showDialog({
|
||||
key: 'upload-model-upgrade',
|
||||
headerComponent: UploadModelUpgradeModalHeader,
|
||||
@@ -28,7 +28,6 @@ export function useModelUpload(
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// Show regular upload modal
|
||||
dialogStore.showDialog({
|
||||
key: 'upload-model',
|
||||
headerComponent: UploadModelDialogHeader,
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Ref } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||
import { st } from '@/i18n'
|
||||
import { civitaiImportSource } from '@/platform/assets/importSources/civitaiImportSource'
|
||||
import { huggingfaceImportSource } from '@/platform/assets/importSources/huggingfaceImportSource'
|
||||
@@ -32,7 +31,6 @@ export function useUploadModelWizard(modelTypes: Ref<ModelTypeOption[]>) {
|
||||
const assetsStore = useAssetsStore()
|
||||
const assetDownloadStore = useAssetDownloadStore()
|
||||
const modelToNodeStore = useModelToNodeStore()
|
||||
const { flags } = useFeatureFlags()
|
||||
const currentStep = ref(1)
|
||||
const isFetchingMetadata = ref(false)
|
||||
const isUploading = ref(false)
|
||||
@@ -47,10 +45,10 @@ export function useUploadModelWizard(modelTypes: Ref<ModelTypeOption[]>) {
|
||||
|
||||
const selectedModelType = ref<string>()
|
||||
|
||||
// Available import sources
|
||||
const importSources: ImportSource[] = flags.huggingfaceModelImportEnabled
|
||||
? [civitaiImportSource, huggingfaceImportSource]
|
||||
: [civitaiImportSource]
|
||||
const importSources: ImportSource[] = [
|
||||
civitaiImportSource,
|
||||
huggingfaceImportSource
|
||||
]
|
||||
|
||||
// Detected import source based on URL
|
||||
const detectedSource = computed(() => {
|
||||
@@ -233,40 +231,27 @@ export function useUploadModelWizard(modelTypes: Ref<ModelTypeOption[]>) {
|
||||
model_type: selectedModelType.value
|
||||
}
|
||||
|
||||
if (flags.asyncModelUploadEnabled) {
|
||||
const result = await assetService.uploadAssetAsync({
|
||||
source_url: wizardData.value.url,
|
||||
tags,
|
||||
user_metadata: userMetadata,
|
||||
preview_id: previewId
|
||||
})
|
||||
const result = await assetService.uploadAssetAsync({
|
||||
source_url: wizardData.value.url,
|
||||
tags,
|
||||
user_metadata: userMetadata,
|
||||
preview_id: previewId
|
||||
})
|
||||
|
||||
if (result.type === 'async' && result.task.status !== 'completed') {
|
||||
if (selectedModelType.value) {
|
||||
assetDownloadStore.trackDownload(
|
||||
result.task.task_id,
|
||||
selectedModelType.value,
|
||||
filename
|
||||
)
|
||||
}
|
||||
uploadStatus.value = 'processing'
|
||||
} else {
|
||||
uploadStatus.value = 'success'
|
||||
await refreshModelCaches()
|
||||
if (result.type === 'async' && result.task.status !== 'completed') {
|
||||
if (selectedModelType.value) {
|
||||
assetDownloadStore.trackDownload(
|
||||
result.task.task_id,
|
||||
selectedModelType.value,
|
||||
filename
|
||||
)
|
||||
}
|
||||
currentStep.value = 3
|
||||
uploadStatus.value = 'processing'
|
||||
} else {
|
||||
await assetService.uploadAssetFromUrl({
|
||||
url: wizardData.value.url,
|
||||
name: filename,
|
||||
tags,
|
||||
user_metadata: userMetadata,
|
||||
preview_id: previewId
|
||||
})
|
||||
uploadStatus.value = 'success'
|
||||
await refreshModelCaches()
|
||||
currentStep.value = 3
|
||||
}
|
||||
currentStep.value = 3
|
||||
} catch (error) {
|
||||
console.error('Failed to upload asset:', error)
|
||||
uploadStatus.value = 'error'
|
||||
|
||||
@@ -35,13 +35,10 @@ export type RemoteConfig = {
|
||||
firebase_config?: FirebaseRuntimeConfig
|
||||
telemetry_disabled_events?: TelemetryEventName[]
|
||||
model_upload_button_enabled?: boolean
|
||||
asset_deletion_enabled?: boolean
|
||||
asset_rename_enabled?: boolean
|
||||
private_models_enabled?: boolean
|
||||
onboarding_survey_enabled?: boolean
|
||||
huggingface_model_import_enabled?: boolean
|
||||
linear_toggle_enabled?: boolean
|
||||
async_model_upload_enabled?: boolean
|
||||
team_workspaces_enabled?: boolean
|
||||
user_secrets_enabled?: boolean
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user