22import NavBar from ' ./components/NavBar.vue' ;
33import FileUpload from ' ./components/FileUpload.vue' ;
44import FileItem from ' ./components/FileItem.vue' ;
5+ import ControlButtons from ' ./components/ControlButtons.vue' ;
56import { useFileDataStore } from ' ./stores/fileData' ;
67import { storeToRefs } from ' pinia' ;
78import type { FileObj } from ' ./types/file' ;
8- import { computed , ref } from ' vue' ;
9- import { compressFile } from ' ./functions/imageCompression' ;
10- import { compressToZip } from ' ./functions/zipCompression' ;
11- import { paginate } from ' ./functions/paginate' ;
129import { useI18n } from ' ./hooks/useI18n' ;
1310
1411const { t } = useI18n ();
1512
1613const fileDataStore = useFileDataStore ();
1714const { files } = storeToRefs (fileDataStore );
1815
19- const isCompressing = ref (false );
20- const zipData = ref (' ' );
21- const isZipCompressing = ref (false );
22- const anyUncompressed = computed (() => files .value .some ((file ) => ! file .isCompressed ));
23-
24- const availableThreads = Math .max (navigator .hardwareConcurrency - 2 , 1 );
25-
26- async function editFileObj(fileObj : FileObj ) {
27- try {
28- const compressedFile = await compressFile (fileObj .file );
29- fileObj .file = compressedFile ;
30- fileObj .isCompressed = true ;
31- } catch {
32- fileObj .isError = true ;
33- }
34- }
35-
36- async function compressFiles() {
37- isCompressing .value = true ;
38-
39- const uncompressedFiles = files .value .filter ((fileObj : FileObj ) => ! fileObj .isCompressed );
40-
41- // option 1 (no errors, slower)
42- const paginatedFileArray = paginate (uncompressedFiles , availableThreads );
43-
44- for (const subArray of paginatedFileArray ) {
45- const promises = subArray .map (editFileObj );
46- await Promise .all (promises );
47- }
48-
49- // option 2 (errors, faster -> better option once the errors are fixed in Firefox)
50- // const promises = uncompressedFiles.map(editFileObj);
51- // await Promise.all(promises);
52-
53- isCompressing .value = false ;
54-
55- URL .revokeObjectURL (zipData .value );
56- isZipCompressing .value = true ;
57- zipData .value = await compressToZip ();
58- isZipCompressing .value = false ;
59- }
60-
61- function removeItem(file : FileObj ) {
62- files .value = files .value .filter ((item ) => item !== file );
63- }
16+ const removeItem = (file : FileObj ) => (files .value = files .value .filter ((item ) => item !== file ));
6417 </script >
6518
6619<template >
@@ -84,32 +37,7 @@ function removeItem(file: FileObj) {
8437 <FileUpload />
8538
8639 <h2 class =" subheading" >{{ t('translation.filelist') }}</h2 >
87- <div class =" buttons" >
88- <button
89- :aria-busy =" isCompressing"
90- :class =" { 'is-success': files.length && !anyUncompressed }"
91- :disabled =" !files.length || !anyUncompressed"
92- @click =" compressFiles"
93- >
94- {{ files.length && !anyUncompressed ? t('translation.allcompressed') : t('translation.compress') }}
95- </button >
96- <a
97- :aria-busy =" isZipCompressing"
98- :disabled =" !zipData || undefined"
99- :href =" zipData || undefined"
100- role =" button"
101- download
102- >
103- {{ t('translation.downloadzip') }}
104- </a >
105- <button
106- :disabled =" !files.length"
107- class =" secondary"
108- @click =" files = []"
109- >
110- {{ t('translation.clearlist') }}
111- </button >
112- </div >
40+ <ControlButtons />
11341 <div class =" file-list" >
11442 <FileItem
11543 v-for =" file in files"
@@ -155,23 +83,4 @@ function removeItem(file: FileObj) {
15583 gap : 0.25rem ;
15684 width : fit-content ;
15785}
158-
159- .is-success {
160- background-color : mediumseagreen ;
161- border : 1px solid darkseagreen ;
162- }
163-
164- .buttons {
165- display : flex ;
166- gap : 0.5rem ;
167- flex-wrap : wrap ;
168- margin-block-end : 1rem ;
169-
170- & > * {
171- flex-grow : 1 ;
172- width : fit-content ;
173- height : fit-content ;
174- margin : 0 ;
175- }
176- }
17786 </style >
0 commit comments