fix(editor): stabilize context menu selection sync
This commit is contained in:
parent
ebf89a7b79
commit
e111184acc
@ -40,6 +40,12 @@ function isPrimaryButton(e: React.PointerEvent | PointerEvent): boolean {
|
|||||||
return (e as PointerEvent).buttons === 1 || (e as PointerEvent).button === 0;
|
return (e as PointerEvent).buttons === 1 || (e as PointerEvent).button === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectionKeyOf(ids: string[]): string {
|
||||||
|
// Keep stable regardless of selection order.
|
||||||
|
// This avoids false mismatches between context-menu state and reducer state.
|
||||||
|
return [...ids].sort().join('|');
|
||||||
|
}
|
||||||
|
|
||||||
export function Canvas(props: CanvasProps) {
|
export function Canvas(props: CanvasProps) {
|
||||||
const ref = useRef<HTMLDivElement | null>(null);
|
const ref = useRef<HTMLDivElement | null>(null);
|
||||||
const [box, setBox] = useState<{ x1: number; y1: number; x2: number; y2: number } | null>(null);
|
const [box, setBox] = useState<{ x1: number; y1: number; x2: number; y2: number } | null>(null);
|
||||||
@ -148,7 +154,7 @@ export function Canvas(props: CanvasProps) {
|
|||||||
? [...props.selectionIds, targetId]
|
? [...props.selectionIds, targetId]
|
||||||
: [targetId]
|
: [targetId]
|
||||||
: props.selectionIds;
|
: props.selectionIds;
|
||||||
const selectionKey = nextSelectionIds.join('|');
|
const selectionKey = selectionKeyOf(nextSelectionIds);
|
||||||
|
|
||||||
if (targetId) {
|
if (targetId) {
|
||||||
if (!props.selectionIds.includes(targetId)) {
|
if (!props.selectionIds.includes(targetId)) {
|
||||||
|
|||||||
@ -86,6 +86,11 @@ export function EditorApp() {
|
|||||||
|
|
||||||
const closeContextMenu = useCallback(() => setCtxMenu(null), []);
|
const closeContextMenu = useCallback(() => setCtxMenu(null), []);
|
||||||
|
|
||||||
|
const selectionKeyOf = useCallback((ids: string[]) => {
|
||||||
|
// Keep stable regardless of ordering.
|
||||||
|
return [...ids].sort().join('|');
|
||||||
|
}, []);
|
||||||
|
|
||||||
const ctxMenuSyncedRef = useRef(false);
|
const ctxMenuSyncedRef = useRef(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -99,7 +104,7 @@ export function EditorApp() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ctxMenu) return;
|
if (!ctxMenu) return;
|
||||||
|
|
||||||
const currentKey = state.selection.ids.join('|');
|
const currentKey = selectionKeyOf(state.selection.ids);
|
||||||
|
|
||||||
// Wait until reducer state has caught up with the context menu's intended selection.
|
// Wait until reducer state has caught up with the context menu's intended selection.
|
||||||
if (!ctxMenuSyncedRef.current) {
|
if (!ctxMenuSyncedRef.current) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user