fix(crop): persist on unmount + handle image-load failure
Two follow-up fixes flagged by the post-merge review: - persist() on `onUnmounted` so a mid-drag navigation (Back button, hot-reload) doesn't lose the in-progress crop. The local refs already hold the latest coords; we just need to flush them through to the store + cache before the component goes away. - Add `el.onerror` to the image load and a small fallback UI offering Back-to-Deskew. Without it, a corrupt deskew blob would leave the canvas permanently blank with no way to recover short of refresh.
This commit is contained in:
parent
565baddfbf
commit
9f54bc62bd
@ -32,6 +32,11 @@ const overlayRef = ref<HTMLCanvasElement | null>(null)
|
||||
|
||||
const img = ref<HTMLImageElement | null>(null)
|
||||
const imgUrl = ref<string | null>(null)
|
||||
// Set when the deskew blob fails to decode — corrupt result, OOM in the
|
||||
// decoder, or unsupported format. We surface a small fallback UI so the
|
||||
// user can navigate back to step 4 and retry instead of staring at a
|
||||
// permanently blank canvas.
|
||||
const loadError = ref(false)
|
||||
|
||||
// Rotation in degrees. Crop fractions of the rotated bbox.
|
||||
const rotationDeg = ref(0)
|
||||
@ -73,10 +78,14 @@ function persist() {
|
||||
function loadImage(url: string) {
|
||||
const el = new Image()
|
||||
el.onload = () => {
|
||||
loadError.value = false
|
||||
img.value = el
|
||||
fitToContainer()
|
||||
redraw()
|
||||
}
|
||||
el.onerror = () => {
|
||||
loadError.value = true
|
||||
}
|
||||
el.src = url
|
||||
}
|
||||
|
||||
@ -392,6 +401,11 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
// If the user navigated away mid-drag (e.g. tapped Back during a corner
|
||||
// pull), the local refs hold the latest crop coords but `persist()` only
|
||||
// fires on `pointerup`. Flush here so cache + store match what was on
|
||||
// screen.
|
||||
persist()
|
||||
resizeObs?.disconnect()
|
||||
if (imgUrl.value) URL.revokeObjectURL(imgUrl.value)
|
||||
})
|
||||
@ -500,6 +514,24 @@ function next() {
|
||||
@pointerup="onPointerUp"
|
||||
@pointercancel="onPointerUp"
|
||||
/>
|
||||
<div
|
||||
v-if="loadError"
|
||||
class="absolute inset-0 flex flex-col items-center justify-center gap-3 bg-background/90 p-6 text-center"
|
||||
>
|
||||
<p class="text-sm font-medium text-destructive">
|
||||
Failed to load the deskew result.
|
||||
</p>
|
||||
<p class="text-xs text-muted-foreground">
|
||||
The image blob couldn't be decoded. Re-run the
|
||||
perspective correction in the previous step.
|
||||
</p>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@click="store.goToStep(4)"
|
||||
>Back to Deskew</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user