From 0bdfd100e878cb888ccb40c0c60500228c9c7935 Mon Sep 17 00:00:00 2001 From: Thom Lamb Date: Fri, 4 Sep 2026 14:06:32 -0500 Subject: [PATCH] fix(admin): re-request a rotated photo even when the turn failed (#301) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The turn handler only bumped the cache-busting version on the success path, so a failure between the backend's two writes (displayed file rotated, then pristine original rotated) left the admin looking at an error toast next to a photo whose src string had not changed and whose bytes the browser still served from cache — even though the displayed file on disk had already turned. The design's stated mitigation for this failure, that the admin can see the photo moved and press back once, depended on the browser re-requesting the file regardless of outcome. Moving setVersion(Date.now()) into the finally block, alongside setTurning(false), makes that re-request happen on both the success and failure paths, so the failure is now visible and recoverable the way the design intends. Co-Authored-By: Claude Opus 5 --- frontend/src/admin/DraftQueue.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/admin/DraftQueue.tsx b/frontend/src/admin/DraftQueue.tsx index 9afc1e6..29403ee 100644 --- a/frontend/src/admin/DraftQueue.tsx +++ b/frontend/src/admin/DraftQueue.tsx @@ -86,6 +86,15 @@ function DraftPhoto({ // session asks it to. This is what makes the button visibly do something. No // column and no server change: the file's identity has not changed, only this // page's need to see it again. + // + // Bumped in `finally`, not on success, and that is the whole point of it + // rather than a tidy-up. The server turns the displayed file first and the + // pristine original second, so a failure between them answers 500 with the + // photo already rotated on disk. Bumping only on success would show that + // admin an error beside a picture that had not visibly moved, and the + // obvious response — press it again — turns it a second time. Re-requesting + // the file either way is what makes the design's remedy, one press back, + // actually available. The cost is one wasted request when nothing changed. const [version, setVersion] = useState(0); const src = version === 0 ? image.image_path : `${image.image_path}?v=${version}`; @@ -107,10 +116,10 @@ function DraftPhoto({ setTurning(true); try { await rotateImage(itemId, image.id, direction); - setVersion(Date.now()); } catch (err) { message.error(err instanceof Error ? err.message : 'that did not work'); } finally { + setVersion(Date.now()); setTurning(false); } };