2
2
import NavBar from ' ./components/NavBar.vue' ;
3
3
import FileUpload from ' ./components/FileUpload.vue' ;
4
4
import FileItem from ' ./components/FileItem.vue' ;
5
+ import ControlButtons from ' ./components/ControlButtons.vue' ;
5
6
import { useFileDataStore } from ' ./stores/fileData' ;
6
7
import { storeToRefs } from ' pinia' ;
7
8
import 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' ;
11
9
import { useI18n } from ' ./hooks/useI18n' ;
12
10
13
11
const { t } = useI18n ();
14
12
15
13
const fileDataStore = useFileDataStore ();
16
14
const { files } = storeToRefs (fileDataStore );
17
15
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
-
76
16
const removeItem = (file : FileObj ) => (files .value = files .value .filter ((item ) => item !== file ));
77
17
</script >
78
18
@@ -97,32 +37,7 @@ const removeItem = (file: FileObj) => (files.value = files.value.filter((item) =
97
37
<FileUpload />
98
38
99
39
<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 />
126
41
<div class =" file-list" >
127
42
<FileItem
128
43
v-for =" file in files"
@@ -168,23 +83,4 @@ const removeItem = (file: FileObj) => (files.value = files.value.filter((item) =
168
83
gap : 0.25rem ;
169
84
width : fit-content ;
170
85
}
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
- }
190
86
</style >
0 commit comments