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 , watch , watchEffect } from ' vue' ;
9- import { compressFile } from ' ./functions/imageCompression' ;
10- import { compressToZip } from ' ./functions/zipCompression' ;
119import { useI18n } from ' ./hooks/useI18n' ;
1210
1311const { t } = useI18n ();
1412
1513const fileDataStore = useFileDataStore ();
1614const { files } = storeToRefs (fileDataStore );
1715
18- const getUncompressedFiles = (fileObj : FileObj ) => ! fileObj .isCompressed ;
19-
20- const isCompressing = ref (false );
21- const zipData = ref (' ' );
22- const isZipCompressing = ref (false );
23- const uncompressedFiles = computed (() => files .value .filter (getUncompressedFiles ));
24- const anyUncompressed = computed (() => Boolean (uncompressedFiles .value .length ));
25- const toCompress = ref <FileObj []>([]);
26-
27- const availableThreads = Math .max (navigator .hardwareConcurrency - 2 , 1 );
28-
29- async function editFileObj(fileObj : FileObj ) {
30- try {
31- const compressedFile = await compressFile (fileObj .file );
32- fileObj .file = compressedFile ;
33- fileObj .isCompressed = true ;
34- fileObj .isError = false ;
35- } catch {
36- fileObj .isError = true ;
37- }
38- }
39-
40- // add files to toCompress array when a thread is available
41- watchEffect (() => {
42- if (isCompressing .value ) {
43- const amountToPush = availableThreads - toCompress .value .filter (getUncompressedFiles ).length ;
44- const pool = uncompressedFiles .value .filter ((item ) => ! toCompress .value .includes (item )).slice (0 , amountToPush );
45- if (pool .length ) toCompress .value = [... toCompress .value , ... pool ];
46- }
47- });
48-
49- // compress new files that are added to the toCompress array
50- watch (toCompress , (newVal , oldVal ) => {
51- const filesToCompress = newVal .filter ((item ) => ! oldVal .includes (item ));
52- filesToCompress .forEach (editFileObj );
53- });
54-
55- // set isCompressing to false when compression finished
56- watchEffect (() => {
57- if (! uncompressedFiles .value .length && isCompressing .value ) {
58- isCompressing .value = false ;
59- toCompress .value = [];
60- }
61- });
62-
63- // zip files when everything is compressed
64- watch (isCompressing , async (newVal , oldVal ) => {
65- if (oldVal && ! newVal ) {
66- URL .revokeObjectURL (zipData .value );
67- isZipCompressing .value = true ;
68- zipData .value = await compressToZip ();
69- isZipCompressing .value = false ;
70- }
71- });
72-
73- // initiate compression
74- const compressFiles = () => (isCompressing .value = true );
75-
7616const removeItem = (file : FileObj ) => (files .value = files .value .filter ((item ) => item !== file ));
7717 </script >
7818
@@ -97,32 +37,7 @@ const removeItem = (file: FileObj) => (files.value = files.value.filter((item) =
9737 <FileUpload />
9838
9939 <h2 class =" subheading" >{{ t('translation.filelist') }}</h2 >
100- <div class =" buttons" >
101- <button
102- :aria-busy =" isCompressing"
103- :class =" { 'is-success': files.length && !anyUncompressed }"
104- :disabled =" !files.length || !anyUncompressed || isCompressing"
105- @click =" compressFiles"
106- >
107- {{ files.length && !anyUncompressed ? t('translation.allcompressed') : t('translation.compress') }}
108- </button >
109- <a
110- :aria-busy =" isZipCompressing"
111- :disabled =" !zipData || undefined"
112- :href =" zipData || undefined"
113- role =" button"
114- download
115- >
116- {{ t('translation.downloadzip') }}
117- </a >
118- <button
119- :disabled =" !files.length"
120- class =" secondary"
121- @click =" files = []"
122- >
123- {{ t('translation.clearlist') }}
124- </button >
125- </div >
40+ <ControlButtons />
12641 <div class =" file-list" >
12742 <FileItem
12843 v-for =" file in files"
@@ -168,23 +83,4 @@ const removeItem = (file: FileObj) => (files.value = files.value.filter((item) =
16883 gap : 0.25rem ;
16984 width : fit-content ;
17085}
171-
172- .is-success {
173- background-color : mediumseagreen ;
174- border : 1px solid darkseagreen ;
175- }
176-
177- .buttons {
178- display : flex ;
179- gap : 0.5rem ;
180- flex-wrap : wrap ;
181- margin-block-end : 1rem ;
182-
183- & > * {
184- flex-grow : 1 ;
185- width : fit-content ;
186- height : fit-content ;
187- margin : 0 ;
188- }
189- }
19086 </style >
0 commit comments