fix(ui): prevent duplicate history entry when clicking wall items#6829
fix(ui): prevent duplicate history entry when clicking wall items#6829speckofthecosmos wants to merge 2 commits intostashapp:developfrom
Conversation
Clicking a scene or marker in the wall view pushes two identical history entries, requiring the user to press back twice to return to the wall. This is caused by react-photo-gallery dispatching the onClick handler twice for a single click event. Add a timestamp-based guard to deduplicate clicks within 100ms. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Reproducibility note: This was consistently reproduced on The fix is defensive and low-risk regardless — a 100ms click dedup via |
|
why not use a debounce instead of storing the last click time in the element? |
|
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#reduced_time_precision This will also break on firefox where the Date.now() precision is 2ms for default reduction and 100 for strict |
|
I think the problem is correctly determined however the solution is not optimal. Hardcoding a delay, which is 100ms, doesn't feel natural or correct to me. |
|
Yeah, fair. The hardcoded 100ms bugged me too, and No strong opinions on the shape though. If you've got a pattern you'd rather see (event-identity dedup, debounce, a fix higher up in the Gallery wrapper, whatever), point me at it and I'll rework. |
There was a problem hiding this comment.
So, I agree this is more of a bandaid than a fix. Since it's pushing the URL twice a path check may be the best bet and solves all the issues that people have brought up.
Here's a general example. It's untested and from a general look at the page so take it and run with it.
const onClick = useCallback(
(event, { index }) => {
const link = photos[index].link;
const current = history.location.pathname + history.location.search;
if (current !== link) {
history.push(link);
}
},
[history, photos]
);
@feederbox826 is better with TS than me so perhaps he can have a gander and correct anything there. I can't remember the exact urls that get used either for current so that may need to be changed up too.
…tries Replace the 100ms timestamp-based dedup with a path-equality check against history.location. The previous approach relied on Date.now() precision, which varies by browser (Firefox reduces precision to 2ms default / 100ms strict per the spec) and introduced an arbitrary threshold. Since react-router's history.push updates location synchronously, the second dispatch from react-photo-gallery sees the post-push URL and the guard correctly no-ops. Per review feedback on stashapp#6829 from @Gykes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks @Gykes — path-equality is the right shape. The timestamp was arbitrary and @feederbox826's Firefox precision note made it a dead end anyway. Pushed the rework to this branch. Since react-router's |
Summary
Clicking a scene or marker in the wall view pushes two identical history entries, requiring users to press back twice to return to the wall. This affects both desktop and mobile browsers.
Root Cause
react-photo-gallerydispatches theonClickhandler twice for a single click event when using a customrenderImagecomponent. The existing codebase already documents this behavior atSceneWallPanel.tsx:99:The
onClickhandler was previously removed from the<img>/<video>elements to avoid this, but theSceneWallandSceneMarkerWallcomponents'onClickcallbacks (which callhistory.push) still receive duplicate dispatches from the Gallery component.Evidence
Instrumented
history.pushStateon a running development instance and confirmed:PUSHcalls to the identical URL within 1ms of each otherVIDEOelement (not the footer<Link>)SceneWallItem.handleClick → Gallery.handleClick → SceneWall.onClick → history.pushFix
Adds a timestamp-based guard (
useRef) toSceneWallPanelandSceneMarkerWallPanelthat deduplicateshistory.pushcalls within 100ms. The double dispatch occurs within 1ms, so this threshold is safe for legitimate rapid navigation while preventing the duplicate entry.Files Changed
ui/v2.5/src/components/Scenes/SceneWallPanel.tsx— add click dedup guardui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx— same fix + adduseRefimportTest plan
🤖 Generated with Claude Code