minor fixes

This commit is contained in:
2026-04-09 08:50:36 +02:00
parent 23d363a50c
commit a2457f4e49
75 changed files with 3848 additions and 387 deletions

View File

@@ -5,6 +5,8 @@ import { mapUploadErrorNotice, mapUploadResultNotice } from '../../lib/uploadNot
// ─── Constants ──────────────────────────────────────────────────────────────
const DEFAULT_CHUNK_SIZE_BYTES = 5 * 1024 * 1024
const DEFAULT_CHUNK_REQUEST_TIMEOUT_MS = 45000
const MIN_CHUNK_SIZE_BYTES = 256 * 1024
const POLL_INTERVAL_MS = 2000
// ─── State machine ───────────────────────────────────────────────────────────
@@ -76,6 +78,16 @@ function toPercent(loaded, total) {
return Math.max(0, Math.min(100, Math.round((loaded / total) * 100)))
}
function formatChunkSize(bytes) {
if (!Number.isFinite(bytes) || bytes <= 0) return '0 KB'
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(bytes % (1024 * 1024) === 0 ? 0 : 1)} MB`
return `${Math.max(1, Math.round(bytes / 1024))} KB`
}
function isRequestTooLarge(error) {
return Number(error?.response?.status || 0) === 413
}
function getProcessingValue(payload) {
const direct = String(payload?.processing_state || payload?.status || '').toLowerCase()
return direct || 'processing'
@@ -114,6 +126,7 @@ export default function useUploadMachine({
initialDraftId = null,
metadata,
chunkSize = DEFAULT_CHUNK_SIZE_BYTES,
chunkRequestTimeoutMs = DEFAULT_CHUNK_REQUEST_TIMEOUT_MS,
onArtworkCreated,
onNotice,
}) {
@@ -137,6 +150,11 @@ export default function useUploadMachine({
const parsed = Number(chunkSize)
return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : DEFAULT_CHUNK_SIZE_BYTES
})()
const effectiveChunkRequestTimeoutMs = (() => {
const parsed = Number(chunkRequestTimeoutMs)
return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : DEFAULT_CHUNK_REQUEST_TIMEOUT_MS
})()
const adaptiveChunkSizeRef = useRef(effectiveChunkSize)
// ── Controller registry ────────────────────────────────────────────────────
const registerController = useCallback(() => {
@@ -251,7 +269,8 @@ export default function useUploadMachine({
const totalSize = file.size
while (uploadedForFile < totalSize) {
const nextOffset = Math.min(uploadedForFile + effectiveChunkSize, totalSize)
const activeChunkSize = Math.max(MIN_CHUNK_SIZE_BYTES, Number(adaptiveChunkSizeRef.current || effectiveChunkSize))
const nextOffset = Math.min(uploadedForFile + activeChunkSize, totalSize)
const blob = file.slice(uploadedForFile, nextOffset)
const payload = new FormData()
@@ -266,8 +285,22 @@ export default function useUploadMachine({
try {
await window.axios.post(uploadEndpoints.chunk(), payload, {
signal: chunkController.signal,
timeout: effectiveChunkRequestTimeoutMs,
headers: { 'X-Upload-Token': uploadToken },
})
} catch (error) {
if (isRequestTooLarge(error) && activeChunkSize > MIN_CHUNK_SIZE_BYTES) {
const nextChunkSize = Math.max(MIN_CHUNK_SIZE_BYTES, Math.floor(activeChunkSize / 2))
if (nextChunkSize < activeChunkSize) {
adaptiveChunkSizeRef.current = nextChunkSize
onNotice?.({
type: 'warning',
message: `Server rejected ${formatChunkSize(activeChunkSize)} chunks. Retrying with ${formatChunkSize(nextChunkSize)} chunks.`,
})
continue
}
}
throw error
} finally {
unregisterController(chunkController)
}
@@ -279,7 +312,7 @@ export default function useUploadMachine({
}
return uploadedBaseBytes + totalSize
}, [effectiveChunkSize, registerController, unregisterController])
}, [effectiveChunkRequestTimeoutMs, effectiveChunkSize, onNotice, registerController, unregisterController])
const cancelUploadSession = useCallback(async (sessionId, uploadToken) => {
if (!sessionId) return