From cf96a043647d916cda5008919bce65ee30219ecc Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 23 Jul 2021 17:01:45 +0300 Subject: [PATCH] Message: Various fixes for context menu on mobile (#1311) --- src/components/middle/MessageList.scss | 7 +++-- src/components/middle/message/Message.scss | 16 ++++++++++- src/components/middle/message/Message.tsx | 31 +++++++++++++++------- src/hooks/useContextMenuHandlers.ts | 5 ++-- src/util/windowSize.ts | 2 ++ 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/components/middle/MessageList.scss b/src/components/middle/MessageList.scss index 80c9dd0a..d3bff43d 100644 --- a/src/components/middle/MessageList.scss +++ b/src/components/middle/MessageList.scss @@ -12,10 +12,13 @@ } @media (pointer: coarse) { - -webkit-user-select: none; - -webkit-touch-callout: none; user-select: none; touch-callout: none; + + &.select-mode-active { + user-select: auto; + touch-callout: default; + } } &.no-avatars .Message > .Avatar { diff --git a/src/components/middle/message/Message.scss b/src/components/middle/message/Message.scss index 0ffe36a2..e6464047 100644 --- a/src/components/middle/message/Message.scss +++ b/src/components/middle/message/Message.scss @@ -56,6 +56,17 @@ border: 1px var(--select-background-color) solid; background-color: var(--select-background-color); } + + body.is-android & { + .can-select-text { + z-index: var(--z-message-select-control); + } + + // Prevent media viewer from opening + .media-inner { + pointer-events: none; + } + } } &.has-inline-buttons { @@ -126,7 +137,10 @@ .select-mode-active & { cursor: pointer; - user-select: none; + + @media (min-width: 600px) { + user-select: none; + } &:not(.own) { > .Avatar, diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index 461e8f01..05c551c5 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -22,7 +22,7 @@ import { FocusDirection, IAlbum, ISettings, MediaViewerOrigin, } from '../../../types'; -import { IS_ANDROID } from '../../../util/environment'; +import { IS_ANDROID, IS_TOUCH_ENV } from '../../../util/environment'; import { pick } from '../../../util/iteratees'; import { selectChat, @@ -59,6 +59,7 @@ import { getUserColorKey, } from '../../../modules/helpers'; import buildClassName from '../../../util/buildClassName'; +import windowSize from '../../../util/windowSize'; import useEnsureMessage from '../../../hooks/useEnsureMessage'; import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers'; import { renderMessageText } from '../../common/helpers/renderMessageText'; @@ -168,7 +169,7 @@ const APPENDIX_OWN = ''; const APPEARANCE_DELAY = 10; const NO_MEDIA_CORNERS_THRESHOLD = 18; -const ANDROID_KEYBOARD_HIDE_DELAY_MS = 150; +const ANDROID_KEYBOARD_HIDE_DELAY_MS = 350; const Message: FC = ({ message, @@ -243,9 +244,9 @@ const Message: FC = ({ const { isContextMenuOpen, contextMenuPosition, - handleBeforeContextMenu, handleContextMenu, + handleBeforeContextMenu, handleContextMenu: onContextMenu, handleContextMenuClose, handleContextMenuHide, - } = useContextMenuHandlers(ref, false, true); + } = useContextMenuHandlers(ref, IS_TOUCH_ENV && isInSelectMode, true, IS_ANDROID); useEffect(() => { if (isContextMenuOpen) { @@ -452,13 +453,23 @@ const Message: FC = ({ } if (IS_ANDROID) { - setTimeout(() => { - handleContextMenu(e); - }, ANDROID_KEYBOARD_HIDE_DELAY_MS); + if (windowSize.getIsKeyboardVisible()) { + setTimeout(() => { onContextMenu(e); }, ANDROID_KEYBOARD_HIDE_DELAY_MS); + } else { + onContextMenu(e); + } } else { - handleContextMenu(e); + onContextMenu(e); } - }, [handleContextMenu]); + }, [onContextMenu]); + + const handleContextMenu = useCallback((e: React.MouseEvent) => { + if (IS_ANDROID) { + handleMessageSelect(e); + } else { + onContextMenu(e); + } + }, [onContextMenu, handleMessageSelect]); const handleReadMedia = useCallback((): void => { markMessagesRead({ messageIds: [messageId] }); @@ -801,7 +812,7 @@ const Message: FC = ({ )} {withAvatar && renderAvatar()}
, isMenuDisabled?: boolean, shouldDisableOnLink?: boolean, + shouldDisableOnLongTap?: boolean, ) => { const [isContextMenuOpen, setIsContextMenuOpen] = useState(false); const [contextMenuPosition, setContextMenuPosition] = useState(undefined); @@ -67,7 +68,7 @@ export default ( // Support context menu on touch-devices useEffect(() => { - if (isMenuDisabled || !IS_TOUCH_ENV) { + if (isMenuDisabled || !IS_TOUCH_ENV || shouldDisableOnLongTap) { return undefined; } @@ -129,7 +130,7 @@ export default ( element.removeEventListener('touchend', clearLongPressTimer, true); element.removeEventListener('touchmove', clearLongPressTimer); }; - }, [contextMenuPosition, isMenuDisabled, elementRef]); + }, [contextMenuPosition, isMenuDisabled, shouldDisableOnLongTap, elementRef]); return { isContextMenuOpen, diff --git a/src/util/windowSize.ts b/src/util/windowSize.ts index d8083886..ff07d97a 100644 --- a/src/util/windowSize.ts +++ b/src/util/windowSize.ts @@ -13,6 +13,7 @@ type IDimensions = { const IS_LANDSCAPE = IS_SINGLE_COLUMN_LAYOUT && isLandscape(); +const initialHeight = window.innerHeight; let windowSize = updateSizes(); let isRefreshDisabled = false; @@ -69,6 +70,7 @@ function isLandscape() { export default { get: () => windowSize, + getIsKeyboardVisible: () => initialHeight > windowSize.height, disableRefresh, enableRefresh, };