|
4 | 4 | button
|
5 | 5 | v-bind="{ ...props, theme: fileInputTheme.themeValues }"
|
6 | 6 | >
|
7 |
| - <div |
8 |
| - v-if="minAmount !== maxAmount && thumbnails.length" |
9 |
| - class="flx --flxRow --flx-start-center --gap-10" |
10 |
| - > |
| 7 | + <div v-if="thumbnails.length" class="flx --flxRow --flx-start-center --gap-10"> |
11 | 8 | <ul class="flx --flxRow-wrap --flx-start-center --gap-10">
|
12 | 9 | <li
|
13 | 10 | v-for="(thumb, thumb_index) in thumbnails"
|
|
18 | 15 | class="avatar --index --bdr flx --flx-center"
|
19 | 16 | :tooltip="t('file_delete_files', 1)"
|
20 | 17 | tooltip-position="bottom"
|
21 |
| - @click.prevent="removeFile(thumb_index)" |
| 18 | + @click.prevent="(e: Event) => removeFile(thumb_index, e)" |
22 | 19 | >
|
23 | 20 | <div class="back">
|
24 | 21 | <BaseImg :src="thumb" :alt="t('file_thumb')" />
|
|
123 | 120 | </template>
|
124 | 121 |
|
125 | 122 | <script setup lang="ts">
|
126 |
| - import { ref, computed } from "vue"; |
| 123 | + import { ref, computed, watch } from "vue"; |
127 | 124 | import debounce from "lodash-es/debounce";
|
128 | 125 | import omit from "lodash-es/omit";
|
129 | 126 |
|
|
216 | 213 | const isAdvancedUpload = ref(false);
|
217 | 214 | const isLoading = ref(false);
|
218 | 215 | const isDragover = ref(false);
|
219 |
| - const minAmount = computed(() => props.min ?? 1); |
220 | 216 | const maxAmount = computed(() => props.max ?? 100);
|
221 | 217 | const maxFileSize = computed(() => props.maxSize ?? 1e7);
|
222 | 218 |
|
223 | 219 | /**
|
224 | 220 | * setFiles
|
225 | 221 | */
|
226 |
| - function setFiles(files: File[] = [], thumbs: string[] = []) { |
227 |
| - thumbnails.value = thumbs; |
228 |
| - emit("update:model-value", files); |
| 222 | + function setFiles(files: File[] = [], event?: Event) { |
| 223 | + if (event) emit("update:model-value", files); |
229 | 224 | }
|
230 | 225 | /**
|
231 | 226 | * check support for drag and drop
|
|
242 | 237 | /**
|
243 | 238 | * stores the files
|
244 | 239 | */
|
245 |
| - async function storeFiles(files: FileList, target: Event) { |
| 240 | + async function storeFiles(files: FileList | File[], event?: Event) { |
246 | 241 | isLoading.value = true;
|
247 | 242 |
|
248 | 243 | // copy the files
|
249 | 244 | const filesArr = Array.from(files); // FileList is unstable
|
250 | 245 | const savedFiles = [...props.modelValue].filter((v) => v instanceof File);
|
251 |
| - const savedThumbs = [...thumbnails.value]; |
252 | 246 |
|
253 | 247 | try {
|
254 | 248 | for (let i = 0; i < filesArr.length; i++) {
|
|
261 | 255 | amount: maxAmount.value,
|
262 | 256 | }),
|
263 | 257 | icon: "warning",
|
264 |
| - target, |
| 258 | + target: event, |
265 | 259 | });
|
266 | 260 |
|
267 | 261 | break;
|
|
278 | 272 | title: t("swal.file_wrong_format_image"),
|
279 | 273 | text: t("swal.file_wrong_format_image_text"),
|
280 | 274 | icon: "warning",
|
281 |
| - target, |
| 275 | + target: event, |
282 | 276 | });
|
283 | 277 | } else {
|
284 | 278 | // is image file
|
285 | 279 | if (filesArr[i].size < maxFileSize.value) {
|
286 | 280 | const fileName = `${props.filePrefix ?? "image"}_${i}`;
|
287 | 281 |
|
288 | 282 | savedFiles.push(renameFile(filesArr[i], fileName));
|
289 |
| - savedThumbs.push(await getBase64FromImageFile(filesArr[i])); |
290 | 283 | } else {
|
291 | 284 | // file too big
|
292 | 285 | Swal.fire({
|
293 | 286 | title: t("swal.file_too_big"),
|
294 | 287 | text: t("swal.file_too_big_text"),
|
295 | 288 | icon: "warning",
|
296 |
| - target, |
| 289 | + target: event, |
297 | 290 | });
|
298 | 291 | }
|
299 | 292 | }
|
300 | 293 | }
|
301 | 294 |
|
302 | 295 | // last one, save all.
|
303 |
| - setFiles(savedFiles, savedThumbs); |
| 296 | + setFiles(savedFiles, event); |
304 | 297 | } catch (err) {
|
305 | 298 | logger("InputFile:storeFiles", err);
|
306 | 299 | Swal.fire({
|
|
309 | 302 | icon: "error",
|
310 | 303 | timer: undefined,
|
311 | 304 | showConfirmButton: true,
|
312 |
| - target, |
| 305 | + target: event, |
313 | 306 | });
|
314 | 307 | }
|
315 | 308 |
|
|
319 | 312 | /**
|
320 | 313 | * remove the given file in the given key
|
321 | 314 | */
|
322 |
| - const removeFile = debounce((index: number) => { |
| 315 | + const removeFile = debounce((index: number, event?: Event) => { |
323 | 316 | // modify and set again
|
324 |
| - setFiles(props.modelValue.toSpliced(index, 1), thumbnails.value.toSpliced(index, 1)); |
| 317 | + setFiles(props.modelValue.toSpliced(index, 1), event); |
325 | 318 | });
|
326 | 319 |
|
327 | 320 | /**
|
|
381 | 374 |
|
382 | 375 | // lifecycle
|
383 | 376 | if (isBrowser) isAdvancedUpload.value = checkAdvancedUploadSupport();
|
| 377 | +
|
| 378 | + watch( |
| 379 | + () => props.modelValue, |
| 380 | + async (newFiles) => { |
| 381 | + // TODO: optimize thumbnails generation for larger filesets |
| 382 | + thumbnails.value = await Promise.all( |
| 383 | + newFiles.map((file) => getBase64FromImageFile(file)) |
| 384 | + ); |
| 385 | + }, |
| 386 | + { immediate: true } |
| 387 | + ); |
384 | 388 | </script>
|
0 commit comments