Direct file download (#215)
This commit is contained in:
@@ -14,6 +14,27 @@
|
||||
</template>
|
||||
</ResponseInput>
|
||||
|
||||
<!-- Direct file URL indicator with folder selection -->
|
||||
<div v-if="isDirectFile && modelUrl" class="flex flex-col gap-2">
|
||||
<div
|
||||
class="flex items-center gap-2 rounded bg-green-50 p-2 text-sm text-green-600"
|
||||
>
|
||||
<i class="pi pi-check-circle"></i>
|
||||
<span>Direct file download detected</span>
|
||||
</div>
|
||||
|
||||
<!-- Model Type/Folder Selection for direct downloads -->
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="text-sm font-medium">{{ $t('modelType') }}:</label>
|
||||
<ResponseSelect
|
||||
v-model="selectedModelType"
|
||||
:items="modelTypeOptions"
|
||||
:type="'drop'"
|
||||
class="flex-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="data.length > 0">
|
||||
<ResponseSelect
|
||||
v-model="current"
|
||||
@@ -79,8 +100,13 @@ import { request } from 'hooks/request'
|
||||
import { useToast } from 'hooks/toast'
|
||||
import Button from 'primevue/button'
|
||||
import { VersionModel, WithResolved } from 'types/typings'
|
||||
import { previewUrlToFile } from 'utils/common'
|
||||
import { ref } from 'vue'
|
||||
import {
|
||||
getFilenameFromUrl,
|
||||
getModelTypeFromFilename,
|
||||
isDirectFileUrl,
|
||||
previewUrlToFile,
|
||||
} from 'utils/common'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
|
||||
const { isMobile } = useConfig()
|
||||
const { toast } = useToast()
|
||||
@@ -89,14 +115,153 @@ const dialog = useDialog()
|
||||
|
||||
const modelUrl = ref<string>()
|
||||
|
||||
// Model type selection for direct downloads
|
||||
const selectedModelType = ref<string>('checkpoints')
|
||||
|
||||
const modelTypeOptions = computed(() => [
|
||||
{
|
||||
label: 'Checkpoints',
|
||||
value: 'checkpoints',
|
||||
command: () => {
|
||||
selectedModelType.value = 'checkpoints'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'LoRA',
|
||||
value: 'loras',
|
||||
command: () => {
|
||||
selectedModelType.value = 'loras'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'ControlNet',
|
||||
value: 'controlnet',
|
||||
command: () => {
|
||||
selectedModelType.value = 'controlnet'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'VAE',
|
||||
value: 'vae',
|
||||
command: () => {
|
||||
selectedModelType.value = 'vae'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Embeddings',
|
||||
value: 'embeddings',
|
||||
command: () => {
|
||||
selectedModelType.value = 'embeddings'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Upscale Models',
|
||||
value: 'upscale_models',
|
||||
command: () => {
|
||||
selectedModelType.value = 'upscale_models'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Diffusers',
|
||||
value: 'diffusers',
|
||||
command: () => {
|
||||
selectedModelType.value = 'diffusers'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'CLIP',
|
||||
value: 'clip',
|
||||
command: () => {
|
||||
selectedModelType.value = 'clip'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'CLIP Vision',
|
||||
value: 'clip_vision',
|
||||
command: () => {
|
||||
selectedModelType.value = 'clip_vision'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'UNet/Diffusion Models',
|
||||
value: 'diffusion_models',
|
||||
command: () => {
|
||||
selectedModelType.value = 'diffusion_models'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Style Models',
|
||||
value: 'style_models',
|
||||
command: () => {
|
||||
selectedModelType.value = 'style_models'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Hypernetworks',
|
||||
value: 'hypernetworks',
|
||||
command: () => {
|
||||
selectedModelType.value = 'hypernetworks'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'GLIGEN',
|
||||
value: 'gligen',
|
||||
command: () => {
|
||||
selectedModelType.value = 'gligen'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'PhotoMaker',
|
||||
value: 'photomaker',
|
||||
command: () => {
|
||||
selectedModelType.value = 'photomaker'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'VAE Approx',
|
||||
value: 'vae_approx',
|
||||
command: () => {
|
||||
selectedModelType.value = 'vae_approx'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Classifiers',
|
||||
value: 'classifiers',
|
||||
command: () => {
|
||||
selectedModelType.value = 'classifiers'
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const isDirectFile = computed(() =>
|
||||
modelUrl.value ? isDirectFileUrl(modelUrl.value) : false,
|
||||
)
|
||||
|
||||
const { current, currentModel, data, search } = useModelSearch()
|
||||
|
||||
const searchModelsByUrl = async () => {
|
||||
if (modelUrl.value) {
|
||||
await search(modelUrl.value)
|
||||
const modelType = isDirectFile.value ? selectedModelType.value : undefined
|
||||
await search(modelUrl.value, modelType)
|
||||
}
|
||||
}
|
||||
|
||||
// Watch for direct file URL changes and set intelligent default
|
||||
watch(modelUrl, (newUrl) => {
|
||||
if (newUrl && isDirectFileUrl(newUrl)) {
|
||||
const filename = getFilenameFromUrl(newUrl)
|
||||
const suggestedType = getModelTypeFromFilename(filename)
|
||||
selectedModelType.value = suggestedType
|
||||
}
|
||||
})
|
||||
|
||||
// Watch for model type changes on direct files and refresh the model
|
||||
watch(selectedModelType, async () => {
|
||||
if (isDirectFile.value && modelUrl.value) {
|
||||
await search(modelUrl.value, selectedModelType.value)
|
||||
}
|
||||
})
|
||||
|
||||
const createDownTask = async (data: WithResolved<VersionModel>) => {
|
||||
loading.show()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user