Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(comp:upload): controlled update should trigger upload and abort #1715

Merged
merged 1 commit into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions packages/components/upload/demo/Controlled.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title:
zh: 受控使用
en: Controlled usage
order: 0
---

## zh

`files` 支持受控,添加文件到 `files` 中可自动上传文件,删除则可以自动终止上传。

## en

`files` supports controlled usage, file is auto uploaded after added to `files`, and aborts after removed.
45 changes: 45 additions & 0 deletions packages/components/upload/demo/Controlled.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<IxUpload v-model:files="files" action="https://run.mocky.io/v3/7564bc4f-780e-43f7-bc58-467959ae3354">
<IxButton>Upload</IxButton>
<template #list>
<IxUploadFiles type="text" />
</template>
</IxUpload>
<IxButton @click="addFile">addFile</IxButton>
<IxButton @click="clearFiles">clearFiles</IxButton>
</template>

<script setup lang="ts">
import type { UploadFile } from '@idux/components/upload'

import { ref } from 'vue'

const files = ref<UploadFile[]>([])
let keySeed = 0

const addFile = () => {
const newFile = new File(
[
new Blob([
Array.from(new Array(100))
.map(() => 'file content')
.join('\n'),
]),
],
'new_File',
{
type: 'text/plain',
},
)

files.value.push({
key: `newFile-${keySeed++}`,
raw: newFile,
name: newFile.name,
status: 'selected',
})
}
const clearFiles = () => {
files.value = []
}
</script>
5 changes: 3 additions & 2 deletions packages/components/upload/src/composables/useFilesData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import type { UploadFile, UploadProps } from '../types'
import type { ComputedRef } from 'vue'

import { type ComputedRef, toRaw } from 'vue'

import { callEmit, useControlledProp } from '@idux/cdk/utils'

Expand Down Expand Up @@ -47,7 +48,7 @@ export function useFilesData(props: UploadProps): FilesDataContext {
}
})

setFileList(newFileList)
setFileList(toRaw(newFileList))

statusChangeFiles.forEach(file => {
callEmit(props.onFileStatusChange, file)
Expand Down
20 changes: 10 additions & 10 deletions packages/components/upload/src/composables/useRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,20 @@ export function useRequest(props: UploadProps, filesDataContext: FilesDataContex
}

function abort(file: UploadFile): void {
const curFile = getTargetFile(file, fileList.value)
if (!curFile) {
return
}
const curAbort = aborts.get(curFile.key)
curAbort?.()
updateFileStatus(curFile, 'abort')
fileUploading.value.splice(getTargetFileIndex(curFile, fileUploading.value), 1)
aborts.delete(curFile.key)
aborts.get(file.key)?.()

props.onRequestChange &&
callEmit(props.onRequestChange, {
status: 'abort',
file: { ...curFile },
file: { ...file },
})
fileUploading.value.splice(getTargetFileIndex(file, fileUploading.value), 1)
aborts.delete(file.key)

const curFile = getTargetFile(file, fileList.value)
if (curFile) {
updateFileStatus(curFile, 'abort')
}
}

async function startUpload(file: UploadFile): Promise<void> {
Expand Down
50 changes: 36 additions & 14 deletions packages/components/upload/src/composables/useUploadControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,48 @@ import type { UploadFile } from '../types'

import { type ComputedRef, watch } from 'vue'

import { useState } from '@idux/cdk/utils'

import { getTargetFile } from '../utils/files'

export function useUploadControl(fileList: ComputedRef<UploadFile[]>, uploadRequest: UploadRequest): void {
const { startUpload, abort } = uploadRequest

watch(fileList, (currentFileList, preFileList) => {
currentFileList.forEach(file => {
const preFile = getTargetFile(file, preFileList)

if (!preFile && file.status === 'selected') {
startUpload(file)
const [proxyedFileList, setProxyedFileList] = useState<UploadFile[]>([...fileList.value])

watch(
fileList,
_fileList => {
setProxyedFileList([..._fileList])
},
{
deep: true,
},
)

watch(
[proxyedFileList, () => proxyedFileList.value.length],
([currentFileList, currentLength], [preFileList, preLength]) => {
if (currentLength === preLength) {
return
}
})

preFileList.forEach(file => {
const currentFile = getTargetFile(file, currentFileList)
currentFileList.forEach(file => {
const preFile = getTargetFile(file, preFileList)
console.log(preFile, file, currentFileList === preFileList)

if (!currentFile && file.status === 'uploading') {
abort(file)
}
})
})
if (!preFile && file.status === 'selected') {
startUpload(file)
}
})

preFileList.forEach(file => {
const currentFile = getTargetFile(file, currentFileList)

if (!currentFile && file.status === 'uploading') {
abort(file)
}
})
},
)
}
2 changes: 1 addition & 1 deletion packages/components/upload/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export interface UploadRequestChangeOption<K = VKey> {
export const uploadProps = {
files: {
type: Array as PropType<UploadFile[]>,
default: [],
default: () => [],
},
accept: String,
action: {
Expand Down