mirror of
https://github.com/danog/telegram-tt.git
synced 2025-01-22 05:11:55 +01:00
Message Context Menu: Better animation anchor (#1676)
This commit is contained in:
parent
f3b0b75e4e
commit
eb261e9abe
@ -177,7 +177,7 @@ const MessageContextMenu: FC<OwnProps> = ({
|
||||
}, [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<OwnProps> = ({
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
isOpen={isOpen}
|
||||
transformOriginX={transformOriginX}
|
||||
transformOriginY={transformOriginY}
|
||||
positionX={positionX}
|
||||
positionY={positionY}
|
||||
style={style}
|
||||
|
@ -123,7 +123,7 @@ export default function useOuterHandlers(
|
||||
|
||||
function handleContextMenu(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
|
||||
if (IS_ANDROID) {
|
||||
if ((e.target as HTMLElement).matches('a[href]')) {
|
||||
if ((e.target as HTMLElement).matches('a[href]') || isContextMenuShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,9 @@ const ListItem: FC<OwnProps> = ({
|
||||
[],
|
||||
);
|
||||
|
||||
const { positionX, positionY, style: menuStyle } = useContextMenuPosition(
|
||||
const {
|
||||
positionX, positionY, transformOriginX, transformOriginY, style: menuStyle,
|
||||
} = useContextMenuPosition(
|
||||
contextMenuPosition,
|
||||
getTriggerElement,
|
||||
getRootElement,
|
||||
@ -195,6 +197,8 @@ const ListItem: FC<OwnProps> = ({
|
||||
{contextActions && contextMenuPosition !== undefined && (
|
||||
<Menu
|
||||
isOpen={isContextMenuOpen}
|
||||
transformOriginX={transformOriginX}
|
||||
transformOriginY={transformOriginY}
|
||||
positionX={positionX}
|
||||
positionY={positionY}
|
||||
style={menuStyle}
|
||||
|
@ -20,6 +20,8 @@ type OwnProps = {
|
||||
className?: string;
|
||||
style?: string;
|
||||
bubbleStyle?: string;
|
||||
transformOriginX?: number;
|
||||
transformOriginY?: number;
|
||||
positionX?: 'left' | 'right';
|
||||
positionY?: 'top' | 'bottom';
|
||||
autoClose?: boolean;
|
||||
@ -44,6 +46,8 @@ const Menu: FC<OwnProps> = ({
|
||||
style,
|
||||
bubbleStyle,
|
||||
children,
|
||||
transformOriginX,
|
||||
transformOriginY,
|
||||
positionX = 'left',
|
||||
positionY = 'top',
|
||||
autoClose = false,
|
||||
@ -101,6 +105,9 @@ const Menu: FC<OwnProps> = ({
|
||||
transitionClassNames,
|
||||
);
|
||||
|
||||
const transformOriginYStyle = transformOriginY !== undefined ? `${transformOriginY}px` : undefined;
|
||||
const transformOriginXStyle = transformOriginX !== undefined ? `${transformOriginX}px` : undefined;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={buildClassName('Menu no-selection', className)}
|
||||
@ -118,7 +125,8 @@ const Menu: FC<OwnProps> = ({
|
||||
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}
|
||||
|
@ -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<number>();
|
||||
const [transformOriginY, setTransformOriginY] = useState<number>();
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user