()
| 224 | } |
| 225 | |
| 226 | export function initImageUpload() { |
| 227 | $('btn-image').addEventListener('click', () => { |
| 228 | if (S.waiting) return; |
| 229 | $('image-file-input').click(); |
| 230 | }); |
| 231 | |
| 232 | $('image-file-input').addEventListener('change', async (e) => { |
| 233 | const file = e.target.files[0]; |
| 234 | if (!file) return; |
| 235 | e.target.value = ''; |
| 236 | |
| 237 | if (!file.type.startsWith('image/')) { |
| 238 | showToast('Please select an image file'); |
| 239 | return; |
| 240 | } |
| 241 | |
| 242 | if (file.size > MAX_IMAGE_BYTES) { |
| 243 | showToast('Image too large (max 4MB)'); |
| 244 | return; |
| 245 | } |
| 246 | if (!S.ws || S.ws.readyState !== WebSocket.OPEN || !S.authenticated) { |
| 247 | showToast('Connection unavailable'); |
| 248 | return; |
| 249 | } |
| 250 | |
| 251 | clearPendingImage(); |
| 252 | const previewUrl = await fileToDataUrl(file); |
| 253 | const newImage = { |
| 254 | file, |
| 255 | mediaType: file.type || 'image/png', |
| 256 | name: file.name, |
| 257 | previewUrl, |
| 258 | uploadId: makeUploadId(), |
| 259 | status: 'uploading', |
| 260 | progress: 0, |
| 261 | uploadedBytes: 0, |
| 262 | totalBytes: file.size, |
| 263 | submitQueued: false, |
| 264 | queuedText: '', |
| 265 | }; |
| 266 | setPendingImage(newImage); |
| 267 | updateImagePreviewUi(); |
| 268 | updateSendBtn(); |
| 269 | |
| 270 | try { |
| 271 | await startImageUpload(newImage); |
| 272 | } catch (err) { |
| 273 | const currentImage = pendingImage; |
| 274 | if (currentImage) { |
| 275 | const wasQueued = currentImage.submitQueued; |
| 276 | currentImage.status = 'failed'; |
| 277 | updateImagePreviewUi(); |
| 278 | if (wasQueued && S.waiting) setWaiting(false, 'image_upload_failed'); |
| 279 | } |
| 280 | showToast(err.message || 'Image upload failed'); |
| 281 | } |
| 282 | }); |
| 283 |
nothing calls this directly
no test coverage detected