From 2ac751f928fc52f99d4aacf8538e1390b41a113f Mon Sep 17 00:00:00 2001 From: Speck Pratt Date: Tue, 14 Apr 2026 08:36:57 -0400 Subject: [PATCH 1/2] fix(ui): prevent duplicate history entry when clicking wall items 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) --- ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx | 8 +++++++- ui/v2.5/src/components/Scenes/SceneWallPanel.tsx | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx b/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx index 5883bbed7..1334e88c1 100644 --- a/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Form } from "react-bootstrap"; import * as GQL from "src/core/generated-graphql"; import Gallery, { @@ -243,8 +243,14 @@ const MarkerWall: React.FC = ({ }); }, [markers, erroredImgs, handleError]); + // Guard against duplicate clicks - react-photo-gallery can dispatch + // the onClick handler twice for a single click event + const lastClickTime = useRef(0); const onClick = useCallback( (event, { index }) => { + const now = Date.now(); + if (now - lastClickTime.current < 100) return; + lastClickTime.current = now; history.push(photos[index].link); }, [history, photos] diff --git a/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx b/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx index f9a42dd48..3acf25cb3 100644 --- a/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx @@ -258,8 +258,14 @@ const SceneWall: React.FC = ({ }); }, [scenes, sceneQueue, erroredImgs, handleError]); + // Guard against duplicate clicks - react-photo-gallery can dispatch + // the onClick handler twice for a single click event + const lastClickTime = useRef(0); const onClick = useCallback( (event, { index }) => { + const now = Date.now(); + if (now - lastClickTime.current < 100) return; + lastClickTime.current = now; history.push(photos[index].link); }, [history, photos] From 81df9ea9978fc941cc8485a9b80fba5430f27f19 Mon Sep 17 00:00:00 2001 From: Speck Pratt Date: Tue, 21 Apr 2026 12:57:58 -0400 Subject: [PATCH 2/2] fix(ui): use path-equality guard to prevent duplicate wall history entries 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 #6829 from @Gykes. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/components/Scenes/SceneMarkerWallPanel.tsx | 12 ++++++------ ui/v2.5/src/components/Scenes/SceneWallPanel.tsx | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx b/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx index 1334e88c1..a081baf6a 100644 --- a/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneMarkerWallPanel.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { Form } from "react-bootstrap"; import * as GQL from "src/core/generated-graphql"; import Gallery, { @@ -245,13 +245,13 @@ const MarkerWall: React.FC = ({ // Guard against duplicate clicks - react-photo-gallery can dispatch // the onClick handler twice for a single click event - const lastClickTime = useRef(0); const onClick = useCallback( (event, { index }) => { - const now = Date.now(); - if (now - lastClickTime.current < 100) return; - lastClickTime.current = now; - history.push(photos[index].link); + const link = photos[index].link; + const current = history.location.pathname + history.location.search; + if (current !== link) { + history.push(link); + } }, [history, photos] ); diff --git a/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx b/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx index 3acf25cb3..fcb095c32 100644 --- a/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneWallPanel.tsx @@ -260,13 +260,13 @@ const SceneWall: React.FC = ({ // Guard against duplicate clicks - react-photo-gallery can dispatch // the onClick handler twice for a single click event - const lastClickTime = useRef(0); const onClick = useCallback( (event, { index }) => { - const now = Date.now(); - if (now - lastClickTime.current < 100) return; - lastClickTime.current = now; - history.push(photos[index].link); + const link = photos[index].link; + const current = history.location.pathname + history.location.search; + if (current !== link) { + history.push(link); + } }, [history, photos] );