Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f920fd82fb | ||
|
|
ccbafdb147 | ||
|
|
60c0b9ad30 | ||
|
|
1873285371 |
Generated
+4
-4
@@ -81,7 +81,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "4.13.0",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.27",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.28",
|
||||
"@playwright/test": "1.63.0",
|
||||
"@rollup/plugin-inject": "5.0.5",
|
||||
"@rollup/plugin-wasm": "6.2.2",
|
||||
@@ -2695,9 +2695,9 @@
|
||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||
},
|
||||
"node_modules/@lotusguild/element-call-embedded": {
|
||||
"version": "0.25.0-lotus.27",
|
||||
"resolved": "https://code.lotusguild.org/api/packages/LotusGuild/npm/%40lotusguild%2Felement-call-embedded/-/0.25.0-lotus.27/element-call-embedded-0.25.0-lotus.27.tgz",
|
||||
"integrity": "sha512-24ZAvGR/t0C6LWFygZkvtk7HalPUvjERDWWkxpJJf4AZCDOJGuhoOuBrjmO+tUGwIrgLOTN6EFAWSaPpTU9rlQ==",
|
||||
"version": "0.25.0-lotus.28",
|
||||
"resolved": "https://code.lotusguild.org/api/packages/LotusGuild/npm/%40lotusguild%2Felement-call-embedded/-/0.25.0-lotus.28/element-call-embedded-0.25.0-lotus.28.tgz",
|
||||
"integrity": "sha512-IFBHHSVw0CzrrLgx3oIIcJmBB4YMb8at4oVuSKXifZ7MmyHydxg9U3sTlZGgLUjMVrrAXj4gFzCksGHet4LSQw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@matrix-org/matrix-sdk-crypto-wasm": {
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "4.13.0",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.27",
|
||||
"@lotusguild/element-call-embedded": "0.25.0-lotus.28",
|
||||
"@playwright/test": "1.63.0",
|
||||
"@rollup/plugin-inject": "5.0.5",
|
||||
"@rollup/plugin-wasm": "6.2.2",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
import { globalStyle, style } from '@vanilla-extract/css';
|
||||
import { DefaultReset, FocusOutline, color, config, toRem } from 'folds';
|
||||
|
||||
export const MessageBase = style({
|
||||
@@ -77,3 +77,14 @@ export const ReactionsMore = style([
|
||||
export const ReactionsTooltipText = style({
|
||||
wordBreak: 'break-word',
|
||||
});
|
||||
|
||||
// [Gitea #199] Long-press opens the message action sheet on touch screens. On
|
||||
// iOS a long-press otherwise belongs to the system: a link/image callout, or
|
||||
// the text-selection loupe, both of which race (and win against) the 450 ms
|
||||
// press. No callout on message rows, and no selection while a finger is
|
||||
// down; copying text is in the sheet.
|
||||
globalStyle('[data-touch-actions]', { WebkitTouchCallout: 'none' });
|
||||
globalStyle('[data-touch-actions][data-pressing], [data-touch-actions][data-pressing] *', {
|
||||
userSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
});
|
||||
|
||||
@@ -17,22 +17,37 @@ export function useLongPress(onLongPress: (x: number, y: number) => void) {
|
||||
const timer = useRef<number | undefined>(undefined);
|
||||
const start = useRef<{ x: number; y: number } | null>(null);
|
||||
const fired = useRef(false);
|
||||
// [Gitea #199] The element being pressed carries `data-pressing` (set on the
|
||||
// DOM directly, no re-render) so iOS can't start a text selection under
|
||||
// the finger; see `[data-touch-actions]` in room/message/styles.css.ts.
|
||||
const pressed = useRef<HTMLElement | null>(null);
|
||||
|
||||
const clear = useCallback(() => {
|
||||
const stopTimer = useCallback(() => {
|
||||
if (timer.current !== undefined) window.clearTimeout(timer.current);
|
||||
timer.current = undefined;
|
||||
start.current = null;
|
||||
}, []);
|
||||
|
||||
// The finger is up (or the gesture was cancelled): only now drop
|
||||
// `data-pressing`, so the system selection can't start under a finger that
|
||||
// is still down after the sheet opened.
|
||||
const clear = useCallback(() => {
|
||||
stopTimer();
|
||||
pressed.current?.removeAttribute('data-pressing');
|
||||
pressed.current = null;
|
||||
}, [stopTimer]);
|
||||
|
||||
const onTouchStart = useCallback(
|
||||
(evt: React.TouchEvent) => {
|
||||
if (!coarse || evt.touches.length !== 1) return;
|
||||
const t = evt.touches[0];
|
||||
start.current = { x: t.clientX, y: t.clientY };
|
||||
fired.current = false;
|
||||
pressed.current = evt.currentTarget as HTMLElement;
|
||||
pressed.current.setAttribute('data-pressing', '');
|
||||
timer.current = window.setTimeout(() => {
|
||||
const s = start.current;
|
||||
clear();
|
||||
stopTimer();
|
||||
if (!s) return;
|
||||
fired.current = true;
|
||||
window.setTimeout(() => {
|
||||
@@ -41,7 +56,7 @@ export function useLongPress(onLongPress: (x: number, y: number) => void) {
|
||||
onLongPress(s.x, s.y);
|
||||
}, LONG_PRESS_MS);
|
||||
},
|
||||
[coarse, clear, onLongPress],
|
||||
[coarse, stopTimer, onLongPress],
|
||||
);
|
||||
|
||||
const onTouchMove = useCallback(
|
||||
@@ -72,7 +87,16 @@ export function useLongPress(onLongPress: (x: number, y: number) => void) {
|
||||
|
||||
return {
|
||||
coarse,
|
||||
handlers: coarse ? { onTouchStart, onTouchMove, onTouchEnd, onTouchCancel: clear } : {},
|
||||
handlers: coarse
|
||||
? {
|
||||
// [Gitea #199] Marks the element for the iOS hardening CSS.
|
||||
'data-touch-actions': '',
|
||||
onTouchStart,
|
||||
onTouchMove,
|
||||
onTouchEnd,
|
||||
onTouchCancel: clear,
|
||||
}
|
||||
: {},
|
||||
/** True for ~1 s after a long-press fired (drop the Android contextmenu echo). */
|
||||
suppressContextMenu: fired,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user