Skip to content

Commit be6b07b

Browse files
authored
Merge branch 'dev' into fix-white-screen-ios
2 parents 53b8223 + dba53eb commit be6b07b

File tree

1 file changed

+78
-6
lines changed

1 file changed

+78
-6
lines changed

src/lib/components/ui/ContextMenu.svelte

+78-6
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,24 @@
1010
import { clickoutside } from "@svelte-put/clickoutside"
1111
import { Appearance } from "$lib/enums"
1212
import type { ContextItem } from "$lib/types"
13-
import { createEventDispatcher, onMount, tick } from "svelte"
13+
import { createEventDispatcher, onDestroy, onMount, tick } from "svelte"
1414
import { log } from "$lib/utils/Logger"
1515
import type { PluginListenerHandle } from "@capacitor/core"
1616
import { isAndroidOriOS } from "$lib/utils/Mobile"
1717
1818
let visible: boolean = false
1919
let coords: [number, number] = [0, 0]
2020
let context: HTMLElement
21+
let slotContainer: HTMLElement
2122
export let items: ContextItem[] = []
2223
export let hook: string = ""
2324
2425
const dispatch = createEventDispatcher()
2526
2627
function onClose(event: CustomEvent<MouseEvent> | MouseEvent) {
28+
if (isLongPress) {
29+
return
30+
}
2731
visible = false
2832
dispatch("close", event)
2933
close_context = undefined
@@ -34,9 +38,9 @@
3438
const { width, height } = context.getBoundingClientRect()
3539
3640
const offsetX = evt.pageX
37-
const offsetY = evt.pageY - keyboardHeight / 2.5
41+
const offsetY = evt.pageY
3842
const screenWidth = evt.view!.innerWidth
39-
const screenHeight = evt.view!.innerHeight
43+
const screenHeight = evt.view!.innerHeight - keyboardHeight
4044
4145
const overFlowX = screenWidth < width + offsetX
4246
const overFlowY = screenHeight < height + offsetY
@@ -54,13 +58,18 @@
5458
if (close_context !== undefined) {
5559
close_context()
5660
}
57-
close_context = () => (visible = false)
61+
close_context = () => {
62+
if (!isLongPress) {
63+
visible = false
64+
}
65+
}
5866
evt.preventDefault()
59-
visible = true
6067
coords = [evt.clientX, evt.clientY]
68+
visible = true
6169
await tick()
6270
coords = calculatePos(evt)
6371
}
72+
6473
let keyboardHeight = 0
6574
onMount(() => {
6675
let mobileKeyboardListener01: PluginListenerHandle | undefined
@@ -85,6 +94,46 @@
8594
}
8695
})
8796
97+
let touchTimer: number | undefined
98+
let isLongPress: boolean = false
99+
100+
function handleTouchStart(evt: TouchEvent) {
101+
if (evt.touches.length === 1) {
102+
isLongPress = false
103+
let longPressElement = evt.target as HTMLElement
104+
longPressElement.style.pointerEvents = "none"
105+
touchTimer = window.setTimeout(() => {
106+
const touch = evt.touches[0]
107+
const mouseEvent = new MouseEvent("contextmenu", {
108+
bubbles: true,
109+
cancelable: true,
110+
view: window,
111+
clientX: touch.clientX,
112+
clientY: touch.clientY,
113+
})
114+
isLongPress = true
115+
openContext(mouseEvent)
116+
}, 500)
117+
}
118+
}
119+
120+
function handleTouchEnd(evt: TouchEvent) {
121+
clearTimeout(touchTimer)
122+
let longPressElement = evt.target as HTMLElement
123+
longPressElement.style.pointerEvents = ""
124+
if (isLongPress) {
125+
evt.preventDefault()
126+
}
127+
setTimeout(() => {
128+
isLongPress = false
129+
}, 100)
130+
}
131+
132+
function handleTouchMove(evt: TouchEvent) {
133+
clearTimeout(touchTimer)
134+
isLongPress = false
135+
}
136+
88137
function handleItemClick(e: MouseEvent, item: ContextItem) {
89138
e.stopPropagation()
90139
log.info(`Clicked ${item.text}`)
@@ -94,9 +143,23 @@
94143
})
95144
onClose(customEvent)
96145
}
146+
147+
onMount(() => {
148+
slotContainer.addEventListener("touchstart", handleTouchStart)
149+
slotContainer.addEventListener("touchend", handleTouchEnd)
150+
slotContainer.addEventListener("touchmove", handleTouchMove)
151+
})
152+
153+
onDestroy(() => {
154+
slotContainer.removeEventListener("touchstart", handleTouchStart)
155+
slotContainer.removeEventListener("touchend", handleTouchEnd)
156+
slotContainer.removeEventListener("touchmove", handleTouchMove)
157+
})
97158
</script>
98159

99-
<slot name="content" open={openContext} />
160+
<div class="long-press-div-container" bind:this={slotContainer}>
161+
<slot name="content" open={openContext} />
162+
</div>
100163
{#if visible}
101164
<div id="context-menu" data-cy={hook} bind:this={context} use:clickoutside on:clickoutside={onClose} style={`position: fixed; left: ${coords[0]}px; top: ${coords[1]}px;`}>
102165
<slot name="items" close={onClose}></slot>
@@ -115,6 +178,15 @@
115178
{/if}
116179

117180
<style lang="scss">
181+
.long-press-div-container {
182+
all: unset;
183+
display: contents;
184+
-webkit-touch-callout: none !important;
185+
-webkit-user-select: none !important;
186+
user-select: none;
187+
touch-action: none;
188+
}
189+
118190
#context-menu {
119191
z-index: 1000;
120192
position: fixed;

0 commit comments

Comments
 (0)