feat: implement upload error handling and rate limiting improvements
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="uploadError" class="upload-error" style="display: none" role="status" aria-live="polite"></div>
|
||||
|
||||
<div class="duration-container">
|
||||
<label for="durationSlider">Duration: <span id="durationValue">5</span> min</label>
|
||||
@@ -72,6 +73,17 @@
|
||||
const linkContainer = document.getElementById("linkContainer");
|
||||
const uploadedLink = document.getElementById("uploadedLink");
|
||||
const clipboardMessage = document.getElementById("clipboardMessage");
|
||||
const uploadError = document.getElementById("uploadError");
|
||||
|
||||
function formatRetryAfter(seconds) {
|
||||
const safeSeconds = Math.max(0, Math.floor(seconds));
|
||||
const minutes = Math.floor(safeSeconds / 60);
|
||||
const remainder = safeSeconds % 60;
|
||||
if (minutes > 0) {
|
||||
return `${minutes}m ${remainder}s`;
|
||||
}
|
||||
return `${remainder}s`;
|
||||
}
|
||||
|
||||
// Update duration display
|
||||
durationSlider.addEventListener("input", function () {
|
||||
@@ -115,6 +127,8 @@
|
||||
};
|
||||
|
||||
try {
|
||||
uploadError.style.display = "none";
|
||||
uploadError.textContent = "";
|
||||
const response = await fetch("/api/upload", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -123,10 +137,33 @@
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
console.log(
|
||||
`✅ Upload received!\n${JSON.stringify(result, null, 2)}`
|
||||
);
|
||||
let result = null;
|
||||
try {
|
||||
result = await response.json();
|
||||
} catch (parseError) {
|
||||
result = null;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const retryAfterSeconds = result && Number.isFinite(Number(result.retry_after_seconds))
|
||||
? Number(result.retry_after_seconds)
|
||||
: null;
|
||||
let errorMessage =
|
||||
(result && result.error) ||
|
||||
`Upload failed (${response.status})`;
|
||||
if (retryAfterSeconds !== null) {
|
||||
errorMessage += ` Try again in ${formatRetryAfter(retryAfterSeconds)}.`;
|
||||
}
|
||||
uploadError.textContent = errorMessage;
|
||||
uploadError.style.display = "block";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result || !result.link) {
|
||||
uploadError.textContent = "Upload failed (invalid response)";
|
||||
uploadError.style.display = "block";
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide duration controls and buttons
|
||||
document.querySelector('label[for="durationSlider"]').style.display =
|
||||
@@ -175,7 +212,8 @@
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`❌ Error: ${error.message}`);
|
||||
uploadError.textContent = `Upload failed (${error.message})`;
|
||||
uploadError.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +239,8 @@
|
||||
resetBtn.style.display = "none";
|
||||
linkContainer.style.display = "none";
|
||||
clipboardMessage.style.display = "none";
|
||||
uploadError.style.display = "none";
|
||||
uploadError.textContent = "";
|
||||
uploadZone.focus();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user