fix(ui): reopen a popout clicked while it is closing (#3318)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-08 20:33:04 +02:00
1 parent a6a9789091
commit acc1392a53
4 files changed
+19 -6

No files matched your search

+1 -3
View File
@@ -94,9 +94,7 @@ export const AppWrapper = observer(({children}: AppWrapperProps) => {
() => ({variant: layoutVariant, setVariant: setLayoutVariant}), () => ({variant: layoutVariant, setVariant: setLayoutVariant}),
[layoutVariant], [layoutVariant],
); );
const popouts = Popout.getPopouts(); const topPopoutRequiresBackdrop = Popout.requiresBackdrop();
const topPopout = popouts.length ? popouts[popouts.length - 1] : null;
const topPopoutRequiresBackdrop = Boolean(topPopout && !topPopout.disableBackdrop);
const hasBlockingModal = Modal.hasModalOpen(); const hasBlockingModal = Modal.hasModalOpen();
const room = MediaEngine.room; const room = MediaEngine.room;
const ringsContainerRef = useRef<HTMLDivElement>(null); const ringsContainerRef = useRef<HTMLDivElement>(null);
@@ -309,7 +309,7 @@ export const Popout = React.forwardRef<HTMLElement, PopoutProps>((props, ref) =>
); );
const toggle = useCallback( const toggle = useCallback(
(clickPos?: number) => { (clickPos?: number) => {
if (PopoutState.isOpen(state.id)) { if (PopoutState.isOpen(state.id) && !PopoutState.isClosing(state.id)) {
if (props.hoverDelay != null && openModeRef.current === 'hover') { if (props.hoverDelay != null && openModeRef.current === 'hover') {
clearTimers(); clearTimers();
open(clickPos, 'click'); open(clickPos, 'click');
@@ -240,11 +240,21 @@ const PopoutItem: React.FC<PopoutItemProps> = observer(
setTargetInDOM(true); setTargetInDOM(true);
} }
}, [target, ownerDocument, keepOpenOnTargetUnmount, beginClose]); }, [target, ownerDocument, keepOpenOnTargetUnmount, beginClose]);
const wasClosingRequestedRef = useRef(isClosingRequested);
useEffect(() => { useEffect(() => {
const wasClosingRequested = wasClosingRequestedRef.current;
wasClosingRequestedRef.current = isClosingRequested;
if (isClosingRequested) { if (isClosingRequested) {
beginClose(); beginClose();
return;
} }
}, [isClosingRequested, beginClose]); if (!wasClosingRequested) return;
if (closeTimerRef.current != null && ownerWindow != null) {
ownerWindow.clearTimeout(closeTimerRef.current);
closeTimerRef.current = null;
}
setIsVisible(true);
}, [isClosingRequested, beginClose, ownerWindow]);
useEffect(() => { useEffect(() => {
return () => { return () => {
if (closeTimerRef.current != null && ownerWindow != null) { if (closeTimerRef.current != null && ownerWindow != null) {
@@ -460,7 +470,7 @@ export const Popouts: React.FC<PopoutsProps> = observer(({ownerDocument}) => {
const portalHost = scopePortalHostToDocument(activePortalHost, scopeDocument); const portalHost = scopePortalHostToDocument(activePortalHost, scopeDocument);
const popouts = PopoutState.getPopouts(scopeDocument); const popouts = PopoutState.getPopouts(scopeDocument);
const topPopout = popouts.length ? popouts[popouts.length - 1] : null; const topPopout = popouts.length ? popouts[popouts.length - 1] : null;
const needsBackdrop = Boolean(topPopout && !topPopout.disableBackdrop); const needsBackdrop = PopoutState.requiresBackdrop(scopeDocument);
useEffect(() => { useEffect(() => {
const currentKeys = new Set(popouts.map((popout) => popout.key.toString())); const currentKeys = new Set(popouts.map((popout) => popout.key.toString()));
const prevKeys = prevPopoutKeysRef.current; const prevKeys = prevPopoutKeysRef.current;
@@ -218,6 +218,11 @@ class Popout {
); );
} }
requiresBackdrop(ownerDocument: Document = document): boolean {
const owner = this.getPopouts(ownerDocument).findLast((popout) => !this.isClosing(popout.key));
return owner != null && !owner.disableBackdrop;
}
private getParentPopoutChain(dependsOnKey: string): Record<string, PopoutDefinition> { private getParentPopoutChain(dependsOnKey: string): Record<string, PopoutDefinition> {
const result: Record<string, PopoutDefinition> = {}; const result: Record<string, PopoutDefinition> = {};
let currentKey: string | undefined = dependsOnKey; let currentKey: string | undefined = dependsOnKey;