Merge branch 'touch-media-query' into 'main'

Use media query to detect touchscreens

See merge request soapbox-pub/soapbox!2929
environments/review-main-yi2y9f/deployments/4393
marcin mikołajczak 2024-02-07 18:22:19 +00:00
commit 83ac44cfe1
5 zmienionych plików z 12 dodań i 29 usunięć

Wyświetl plik

@ -7,7 +7,7 @@ import { useHistory } from 'react-router-dom';
import { closeDropdownMenu as closeDropdownMenuRedux, openDropdownMenu } from 'soapbox/actions/dropdown-menu';
import { closeModal, openModal } from 'soapbox/actions/modals';
import { useAppDispatch } from 'soapbox/hooks';
import { isUserTouching } from 'soapbox/is-mobile';
import { userTouching } from 'soapbox/is-mobile';
import { IconButton, Portal } from '../ui';
@ -53,8 +53,6 @@ const DropdownMenu = (props: IDropdownMenu) => {
const arrowRef = useRef<HTMLDivElement>(null);
const isOnMobile = isUserTouching();
const { x, y, strategy, refs, middlewareData, placement } = useFloating<HTMLButtonElement>({
placement: initialPlacement,
middleware: [
@ -92,7 +90,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
* On mobile screens, let's replace the Popper dropdown with a Modal.
*/
const handleOpen = () => {
if (isOnMobile) {
if (userTouching.matches) {
dispatch(
openModal('ACTIONS', {
status: filteredProps.status,
@ -113,7 +111,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
const handleClose = () => {
(refs.reference.current as HTMLButtonElement)?.focus();
if (isOnMobile) {
if (userTouching.matches) {
dispatch(closeModal('ACTIONS'));
} else {
closeDropdownMenu();

Wyświetl plik

@ -4,7 +4,7 @@ import { simpleEmojiReact } from 'soapbox/actions/emoji-reacts';
import { openModal } from 'soapbox/actions/modals';
import { EmojiSelector, Portal } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector, useOwnAccount, useSoapboxConfig } from 'soapbox/hooks';
import { isUserTouching } from 'soapbox/is-mobile';
import { userTouching } from 'soapbox/is-mobile';
import { getReactForStatus } from 'soapbox/utils/emoji-reacts';
interface IStatusReactionWrapper {
@ -39,7 +39,7 @@ const StatusReactionWrapper: React.FC<IStatusReactionWrapper> = ({ statusId, chi
clearTimeout(timeout.current);
}
if (!isUserTouching()) {
if (!userTouching.matches) {
setVisible(true);
}
};
@ -51,7 +51,7 @@ const StatusReactionWrapper: React.FC<IStatusReactionWrapper> = ({ statusId, chi
// Unless the user is touching, delay closing the emoji selector briefly
// so the user can move the mouse diagonally to make a selection.
if (isUserTouching()) {
if (userTouching.matches) {
setVisible(false);
} else {
timeout.current = setTimeout(() => {
@ -73,7 +73,7 @@ const StatusReactionWrapper: React.FC<IStatusReactionWrapper> = ({ statusId, chi
const handleClick: React.EventHandler<React.MouseEvent> = e => {
const meEmojiReact = getReactForStatus(status, soapboxConfig.allowedEmoji)?.name || '👍';
if (isUserTouching()) {
if (userTouching.matches) {
if (ownAccount) {
if (visible) {
handleReact(meEmojiReact);

Wyświetl plik

@ -11,7 +11,7 @@ import { closeModal, openModal } from 'soapbox/actions/modals';
import Icon from 'soapbox/components/icon';
import { IconButton } from 'soapbox/components/ui';
import { useAppDispatch, useCompose } from 'soapbox/hooks';
import { isUserTouching } from 'soapbox/is-mobile';
import { userTouching } from 'soapbox/is-mobile';
import Motion from '../../ui/util/optional-motion';
@ -173,7 +173,7 @@ const PrivacyDropdown: React.FC<IPrivacyDropdown> = ({
const onModalClose = () => dispatch(closeModal('ACTIONS'));
const handleToggle: React.MouseEventHandler<HTMLButtonElement> = (e) => {
if (isUserTouching()) {
if (userTouching.matches) {
if (open) {
onModalClose();
} else {

Wyświetl plik

@ -15,7 +15,7 @@ import PlaceholderStatus from 'soapbox/features/placeholder/components/placehold
import Thread from 'soapbox/features/status/components/thread';
import Video from 'soapbox/features/video';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { isUserTouching } from 'soapbox/is-mobile';
import { userTouching } from 'soapbox/is-mobile';
import { makeGetStatus } from 'soapbox/selectors';
import ImageLoader from '../image-loader';
@ -104,7 +104,7 @@ const MediaModal: React.FC<IMediaModal> = (props) => {
const getIndex = () => index !== null ? index : props.index;
const toggleNavigation = () => {
setNavigationHidden(value => !value && isUserTouching());
setNavigationHidden(value => !value && userTouching.matches);
};
const handleStatusClick: React.MouseEventHandler = e => {

Wyświetl plik

@ -1,5 +1,3 @@
import { supportsPassiveEvents } from 'detect-passive-events';
/** Breakpoint at which the application is considered "mobile". */
const LAYOUT_BREAKPOINT = 630;
@ -11,20 +9,7 @@ export function isMobile(width: number) {
/** Whether the device is iOS (best guess). */
const iOS: boolean = /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream;
let userTouching = false;
const listenerOptions = supportsPassiveEvents ? { passive: true } as EventListenerOptions : false;
function touchListener(): void {
userTouching = true;
window.removeEventListener('touchstart', touchListener, listenerOptions);
}
window.addEventListener('touchstart', touchListener, listenerOptions);
/** Whether the user has touched the screen since the page loaded. */
export function isUserTouching(): boolean {
return userTouching;
}
export const userTouching = window.matchMedia('(pointer: coarse)');
/** Whether the device is iOS (best guess). */
export function isIOS(): boolean {