@@ -45,7 +45,21 @@ export const SectionExampleCaptures = ({
45
45
} : {
46
46
deployment : DeploymentDetails
47
47
} ) => {
48
- const [ files , setFiles ] = useState < File [ ] > ( [ ] )
48
+ const [ addQueue , setAddQueue ] = useState <
49
+ { file : File ; id : string | undefined ; uploaded ?: boolean } [ ]
50
+ > ( [ ] )
51
+
52
+ useEffect ( ( ) => {
53
+ // Remove items from queue when deployment capture data is updated to free memory
54
+ setAddQueue ( ( prev ) =>
55
+ prev . filter ( ( { id } ) => {
56
+ const deploymentHasCapture = deployment . exampleCaptures . some (
57
+ ( exampleCapture ) => exampleCapture . id === id
58
+ )
59
+ return ! deploymentHasCapture
60
+ } )
61
+ )
62
+ } , [ deployment . exampleCaptures ] )
49
63
50
64
if ( ! deployment . createdAt ) {
51
65
return (
@@ -57,7 +71,7 @@ export const SectionExampleCaptures = ({
57
71
}
58
72
59
73
const canUpload =
60
- deployment . exampleCaptures . length + files . length <
74
+ deployment . exampleCaptures . length + addQueue . length <
61
75
CAPTURE_CONFIG . NUM_CAPTURES
62
76
63
77
return (
@@ -74,15 +88,38 @@ export const SectionExampleCaptures = ({
74
88
/>
75
89
) ) }
76
90
77
- { files . map ( ( file , index ) => (
78
- < AddedExampleCapture
79
- key = { index }
80
- deploymentId = { deployment . id }
81
- file = { file }
82
- index = { deployment . exampleCaptures . length + index }
83
- onUploaded = { ( ) => setFiles ( files . filter ( ( f ) => f !== file ) ) }
84
- />
85
- ) ) }
91
+ { addQueue
92
+ . filter ( ( { id } ) => {
93
+ // Only render queue items that are not yet part of deployment captures
94
+ const deploymentHasCapture = deployment . exampleCaptures . some (
95
+ ( exampleCapture ) => exampleCapture . id === id
96
+ )
97
+ return ! deploymentHasCapture
98
+ } )
99
+ . map ( ( { file } , index ) => (
100
+ < AddedExampleCapture
101
+ key = { file . name }
102
+ deploymentId = { deployment . id }
103
+ file = { file }
104
+ index = { deployment . exampleCaptures . length + index }
105
+ onCancel = { ( ) => {
106
+ // Remove item from queue
107
+ setAddQueue ( ( prev ) => prev . filter ( ( { file } ) => file !== file ) )
108
+ } }
109
+ onSuccess = { ( id : string ) => {
110
+ // Update queue item with upload status
111
+ setAddQueue ( ( prev ) =>
112
+ prev . map ( ( item ) => {
113
+ if ( item . file === file ) {
114
+ item . id = id
115
+ item . uploaded = true
116
+ }
117
+ return item
118
+ } )
119
+ )
120
+ } }
121
+ />
122
+ ) ) }
86
123
87
124
{ canUpload && (
88
125
< Card >
@@ -98,9 +135,19 @@ export const SectionExampleCaptures = ({
98
135
theme = { IconButtonTheme . Success }
99
136
/>
100
137
) }
101
- onChange = { ( newFiles ) =>
102
- setFiles ( [ ...files , ...Array . from ( newFiles ?? [ ] ) ] )
103
- }
138
+ onChange = { ( newFiles ) => {
139
+ if ( ! newFiles ) {
140
+ return
141
+ }
142
+
143
+ setAddQueue ( ( prev ) => [
144
+ ...prev ,
145
+ ...Array . from ( newFiles ) . map ( ( file ) => ( {
146
+ file,
147
+ id : undefined ,
148
+ } ) ) ,
149
+ ] )
150
+ } }
104
151
/>
105
152
</ Card >
106
153
) }
@@ -135,44 +182,40 @@ const ExampleCapture = ({ id, src }: { id: string; src: string }) => (
135
182
136
183
const AddedExampleCapture = ( {
137
184
deploymentId,
138
- index,
139
185
file,
140
- onUploaded,
186
+ index,
187
+ onCancel,
188
+ onSuccess,
141
189
} : {
142
190
deploymentId : string
143
- file : File
144
191
index : number
145
- onUploaded : ( ) => void
192
+ file : File
193
+ onCancel : ( ) => void
194
+ onSuccess : ( id : string ) => void
146
195
} ) => {
147
- const { uploadCapture, isLoading, isSuccess, error } =
148
- useUploadCapture ( onUploaded )
149
-
196
+ const { uploadCapture, error } = useUploadCapture ( onSuccess )
150
197
const { isValid, errorMessage, allowRetry } = useCaptureError ( {
151
198
error,
152
199
file,
153
200
index,
154
201
} )
155
202
156
203
useEffect ( ( ) => {
157
- if ( ! isValid || isSuccess ) {
204
+ if ( ! isValid ) {
158
205
return
159
206
}
160
207
208
+ // Trigger capture upload on component mount
161
209
uploadCapture ( { deploymentId, file } )
162
210
} , [ ] )
163
211
164
- if ( isSuccess ) {
165
- return null
166
- }
167
-
168
212
return (
169
213
< Card >
170
214
< div className = { styles . cardContent } >
171
215
< img src = { URL . createObjectURL ( file ) } />
172
216
</ div >
173
217
< div className = { styles . cardContent } >
174
- { isLoading ? < LoadingSpinner size = { 32 } /> : null }
175
- { errorMessage && (
218
+ { errorMessage ? (
176
219
< >
177
220
< Tooltip content = { errorMessage } >
178
221
{ allowRetry ? (
@@ -194,10 +237,12 @@ const AddedExampleCapture = ({
194
237
< IconButton
195
238
icon = { IconType . Cross }
196
239
shape = { IconButtonShape . Round }
197
- onClick = { onUploaded }
240
+ onClick = { onCancel }
198
241
/>
199
242
</ div >
200
243
</ >
244
+ ) : (
245
+ < LoadingSpinner size = { 32 } />
201
246
) }
202
247
</ div >
203
248
</ Card >
0 commit comments