mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Merge pull request #31981 from overleaf/mg-context-mobile
[web] Add stricter mobile detection for context menu GitOrigin-RevId: 9c9e75a14c1f9841b5125cb4fb4ef8c2f3b8a33f
This commit is contained in:
@@ -17,6 +17,9 @@ import {
|
||||
} from '@codemirror/state'
|
||||
import { closeAllContextMenusEffect } from '../utils/close-all-context-menus-effect'
|
||||
import { isContextMenuMouseEvent } from '../utils/context-menu-mouse-event'
|
||||
import { isMobileDevice } from '../utils/isMobileDevice'
|
||||
|
||||
const isMobile = isMobileDevice()
|
||||
|
||||
export const openContextMenuEffect = StateEffect.define<{
|
||||
pos: number
|
||||
@@ -28,11 +31,6 @@ export const closeContextMenuEffect = StateEffect.define()
|
||||
|
||||
export const openContextMenuAnnotation = Annotation.define<boolean>()
|
||||
|
||||
const isTouchOnlyInput =
|
||||
typeof window.matchMedia === 'function' &&
|
||||
window.matchMedia('(pointer: coarse)').matches &&
|
||||
window.matchMedia('(hover: none)').matches
|
||||
|
||||
type ContextMenuState = {
|
||||
tooltip: Tooltip | null
|
||||
mousePosition: { x: number; y: number } | null
|
||||
@@ -236,7 +234,7 @@ function isClickOnGutter(target: HTMLElement): boolean {
|
||||
// Gutter context menu plugin
|
||||
const gutterContextMenuPlugin = (): Extension =>
|
||||
EditorView.updateListener.of(update => {
|
||||
if (isTouchOnlyInput || !update.view.dom.parentElement) {
|
||||
if (!update.view.dom.parentElement) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -275,12 +273,8 @@ const gutterContextMenuPlugin = (): Extension =>
|
||||
|
||||
// Handle right-click on ol-cm-filler (empty line widget)
|
||||
// domEventHandlers doesn't fire for contenteditable="false" elements, so we use a direct DOM listener
|
||||
const emptyLineFillerContextMenuPlugin = (): Extension => {
|
||||
if (isTouchOnlyInput) {
|
||||
return []
|
||||
}
|
||||
|
||||
return ViewPlugin.define(view => {
|
||||
const emptyLineFillerContextMenuPlugin = (): Extension =>
|
||||
ViewPlugin.define(view => {
|
||||
const contentDOM = view.contentDOM
|
||||
|
||||
const handleContextMenu = (event: Event) => {
|
||||
@@ -313,16 +307,11 @@ const emptyLineFillerContextMenuPlugin = (): Extension => {
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Editor view context menu handlers
|
||||
const editorContextMenuHandlers = (): Extension =>
|
||||
EditorView.domEventHandlers({
|
||||
contextmenu(event: MouseEvent, view: EditorView) {
|
||||
if (isTouchOnlyInput) {
|
||||
return false
|
||||
}
|
||||
|
||||
const pos = view.posAtCoords({ x: event.clientX, y: event.clientY })
|
||||
if (pos === null) {
|
||||
return false
|
||||
@@ -361,8 +350,7 @@ const editorContextMenuHandlers = (): Extension =>
|
||||
}
|
||||
|
||||
// Prevent default on right-click to preserve selection
|
||||
// But not on touch devices - they need native selection behavior
|
||||
if (isRightClick && !isTouchOnlyInput) {
|
||||
if (isRightClick) {
|
||||
event.preventDefault()
|
||||
return true
|
||||
}
|
||||
@@ -394,7 +382,7 @@ const contextMenuKeymap = (): Extension =>
|
||||
)
|
||||
|
||||
export const contextMenu = (enabled: boolean): Extension =>
|
||||
enabled
|
||||
enabled && !isMobile
|
||||
? [
|
||||
contextMenuContainerTheme,
|
||||
contextMenuStateField,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import browser from '../extensions/browser'
|
||||
|
||||
export function isMobileDevice(): boolean {
|
||||
const ua = typeof navigator !== 'undefined' ? navigator.userAgent : ''
|
||||
const isMobileUserAgent = /Android|iPhone|iPad|Mobile/i.test(ua)
|
||||
|
||||
// Input-capability fallback.
|
||||
const isTouchOnlyInput =
|
||||
typeof window !== 'undefined' &&
|
||||
typeof window.matchMedia === 'function' &&
|
||||
window.matchMedia('(pointer: coarse)').matches &&
|
||||
window.matchMedia('(hover: none)').matches
|
||||
|
||||
return browser.ios || browser.android || isMobileUserAgent || isTouchOnlyInput
|
||||
}
|
||||
Reference in New Issue
Block a user