diff --git a/sound_picture_app/Web_Server.cpp b/sound_picture_app/Web_Server.cpp index 2cdb8b0..b7f9bf2 100644 --- a/sound_picture_app/Web_Server.cpp +++ b/sound_picture_app/Web_Server.cpp @@ -132,7 +132,7 @@ input[type=range]{width:100%;accent-color:var(--accent)}
📷

Tap to choose a photo
from your camera roll

- + preview
@@ -344,19 +344,105 @@ function uploadFile(fileInput, endpoint, progressWrap, fill, txt, onDone) { } function uploadPhoto() { - document.getElementById('nextStep1').disabled=true; - uploadFile( - document.getElementById('photoFile'), - '/api/upload/photo', - document.getElementById('progress1'), - document.getElementById('fill1'), - document.getElementById('txt1'), - function(filename){ - if(filename){ uploadedPhoto=filename; goStep(2); } - else showToast('Photo upload failed. Try again.', false); - document.getElementById('nextStep1').disabled=false; - } - ); + var fileInput = document.getElementById('photoFile'); + var file = fileInput.files[0]; + if (!file) return; + + document.getElementById('nextStep1').disabled = true; + var progressWrap = document.getElementById('progress1'); + var fill = document.getElementById('fill1'); + var txt = document.getElementById('txt1'); + + progressWrap.style.display = 'block'; + txt.textContent = 'Preparing photo...'; + fill.style.width = '10%'; + + var reader = new FileReader(); + reader.onload = function(e) { + var img = new Image(); + img.onload = function() { + var canvas = document.createElement('canvas'); + canvas.width = 172; + canvas.height = 320; + var ctx = canvas.getContext('2d'); + + // Center crop cover math + var srcWidth = img.width; + var srcHeight = img.height; + var ratio = Math.max(172 / srcWidth, 320 / srcHeight); + var newWidth = srcWidth * ratio; + var newHeight = srcHeight * ratio; + var x = (172 - newWidth) / 2; + var y = (320 - newHeight) / 2; + + ctx.fillStyle = '#000000'; + ctx.fillRect(0, 0, 172, 320); + ctx.drawImage(img, x, y, newWidth, newHeight); + + canvas.toBlob(function(blob) { + if (!blob) { + showToast('Photo preparation failed.', false); + document.getElementById('nextStep1').disabled = false; + progressWrap.style.display = 'none'; + return; + } + + var origName = file.name; + var lastDot = origName.lastIndexOf('.'); + var baseName = lastDot >= 0 ? origName.substring(0, lastDot) : 'photo'; + var newFilename = baseName + '.png'; + + var fd = new FormData(); + fd.append('file', blob, newFilename); + + var xhr = new XMLHttpRequest(); + xhr.open('POST', '/api/upload/photo'); + xhr.upload.onprogress = function(progressEvt) { + if (progressEvt.lengthComputable) { + var pct = Math.round(progressEvt.loaded / progressEvt.total * 100); + fill.style.width = pct + '%'; + txt.textContent = 'Uploading photo... ' + pct + '%'; + } + }; + + xhr.onload = function() { + progressWrap.style.display = 'none'; + try { + var res = JSON.parse(xhr.responseText); + if (res.ok && res.filename) { + uploadedPhoto = res.filename; + goStep(2); + } else { + showToast('Photo upload failed: ' + (res.error || 'unknown error'), false); + } + } catch(err) { + showToast('Photo upload failed.', false); + } + document.getElementById('nextStep1').disabled = false; + }; + + xhr.onerror = function() { + progressWrap.style.display = 'none'; + showToast('Photo upload failed.', false); + document.getElementById('nextStep1').disabled = false; + }; + + xhr.send(fd); + }, 'image/png'); + }; + img.onerror = function() { + showToast('Invalid image file.', false); + document.getElementById('nextStep1').disabled = false; + progressWrap.style.display = 'none'; + }; + img.src = e.target.result; + }; + reader.onerror = function() { + showToast('Failed to read file.', false); + document.getElementById('nextStep1').disabled = false; + progressWrap.style.display = 'none'; + }; + reader.readAsDataURL(file); } function uploadAudio() {