diff --git a/src/components/middle/message/MessageContextMenu.tsx b/src/components/middle/message/MessageContextMenu.tsx index 6163b8017..409ecacf9 100644 --- a/src/components/middle/message/MessageContextMenu.tsx +++ b/src/components/middle/message/MessageContextMenu.tsx @@ -177,7 +177,7 @@ const MessageContextMenu: FC = ({ }, [isOpen, markIsReady, unmarkIsReady]); const { - positionX, positionY, style, menuStyle, withScroll, + positionX, positionY, transformOriginX, transformOriginY, style, menuStyle, withScroll, } = useContextMenuPosition(anchor, getTriggerElement, getRootElement, getMenuElement, getLayout); useEffect(() => { @@ -192,6 +192,8 @@ const MessageContextMenu: FC = ({ ) { if (IS_ANDROID) { - if ((e.target as HTMLElement).matches('a[href]')) { + if ((e.target as HTMLElement).matches('a[href]') || isContextMenuShown) { return; } diff --git a/src/components/ui/ListItem.tsx b/src/components/ui/ListItem.tsx index 673c5019d..138a90fc0 100644 --- a/src/components/ui/ListItem.tsx +++ b/src/components/ui/ListItem.tsx @@ -91,7 +91,9 @@ const ListItem: FC = ({ [], ); - const { positionX, positionY, style: menuStyle } = useContextMenuPosition( + const { + positionX, positionY, transformOriginX, transformOriginY, style: menuStyle, + } = useContextMenuPosition( contextMenuPosition, getTriggerElement, getRootElement, @@ -195,6 +197,8 @@ const ListItem: FC = ({ {contextActions && contextMenuPosition !== undefined && ( = ({ style, bubbleStyle, children, + transformOriginX, + transformOriginY, positionX = 'left', positionY = 'top', autoClose = false, @@ -101,6 +105,9 @@ const Menu: FC = ({ transitionClassNames, ); + const transformOriginYStyle = transformOriginY !== undefined ? `${transformOriginY}px` : undefined; + const transformOriginXStyle = transformOriginX !== undefined ? `${transformOriginX}px` : undefined; + return (
= ({ ref={menuRef} className={bubbleClassName} // @ts-ignore teact feature - style={`transform-origin: ${positionY} ${positionX};${bubbleStyle || ''}`} + style={`transform-origin: ${transformOriginXStyle || positionX} ${transformOriginYStyle || positionY};${ + bubbleStyle || ''}`} onClick={autoClose ? onClose : undefined} > {children} diff --git a/src/hooks/useContextMenuPosition.ts b/src/hooks/useContextMenuPosition.ts index 7cc28c1c6..f7cc0a0a7 100644 --- a/src/hooks/useContextMenuPosition.ts +++ b/src/hooks/useContextMenuPosition.ts @@ -23,6 +23,8 @@ export default function useContextMenuPosition( ) { const [positionX, setPositionX] = useState<'right' | 'left'>('right'); const [positionY, setPositionY] = useState<'top' | 'bottom'>('bottom'); + const [transformOriginX, setTransformOriginX] = useState(); + const [transformOriginY, setTransformOriginY] = useState(); const [withScroll, setWithScroll] = useState(false); const [style, setStyle] = useState(''); const [menuStyle, setMenuStyle] = useState('opacity: 0;'); @@ -34,6 +36,8 @@ export default function useContextMenuPosition( } let { x, y } = anchor; + const anchorX = x; + const anchorY = y; const menuEl = getMenuElement(); const rootEl = getRootElement(); @@ -55,6 +59,7 @@ export default function useContextMenuPosition( const rootRect = rootEl ? rootEl.getBoundingClientRect() : EMPTY_RECT; let horizontalPosition: 'left' | 'right'; + let verticalPosition: 'top' | 'bottom'; if (x + menuRect.width + extraPaddingX < rootRect.width + rootRect.left) { x += 3; horizontalPosition = 'left'; @@ -81,14 +86,15 @@ export default function useContextMenuPosition( } if (y + menuRect.height < rootRect.height + rootRect.top) { - setPositionY('top'); + verticalPosition = 'top'; } else { - setPositionY('bottom'); + verticalPosition = 'bottom'; if (y - menuRect.height < rootRect.top + extraTopPadding) { y = rootRect.top + rootRect.height; } } + setPositionY(verticalPosition); const triggerRect = triggerEl.getBoundingClientRect(); const left = horizontalPosition === 'left' @@ -103,6 +109,10 @@ export default function useContextMenuPosition( setWithScroll(menuMaxHeight < menuRect.height); setMenuStyle(`max-height: ${menuMaxHeight}px;`); setStyle(`left: ${left}px; top: ${top}px`); + const offsetX = (anchorX - triggerRect.left) - left; + const offsetY = (anchorY - triggerRect.top) - top - (marginTop || 0); + setTransformOriginX(horizontalPosition === 'left' ? offsetX : menuRect.width + offsetX); + setTransformOriginY(verticalPosition === 'bottom' ? menuRect.height + offsetY : offsetY); }, [ anchor, getMenuElement, getRootElement, getTriggerElement, getLayout, ]); @@ -110,6 +120,8 @@ export default function useContextMenuPosition( return { positionX, positionY, + transformOriginX, + transformOriginY, style, menuStyle, withScroll,