fix: prevent native text selection on mobile long-press
iOS triggered both the app context menu and native text selection overlay on long-press. Three-layer fix: CSS user-select:none on buttons/[role=button]/ [data-context-menu] elements; non-passive touchstart listener with conditional preventDefault on context-menu targets; removeAllRanges() at timer fire to clear any residual selection. Added data-context-menu to all mobile surfaces that use onContextMenu handlers.
This commit is contained in:
@@ -224,6 +224,7 @@ export function Message({ message, isCompact, isFirstInGroup, previousMessageId
|
||||
const ownerId = spaces.find(s => s.id === currentSpaceId)?.ownerId;
|
||||
|
||||
const getMemberDisplayColor = (userId: string) => {
|
||||
if (isDmMessage) return { color: '#d8d8de' };
|
||||
const member = members.find(m => m.userId === userId);
|
||||
if (member?.roles && member.roles.length > 0) {
|
||||
const sorted = [...member.roles].sort((a, b) => b.position - a.position);
|
||||
@@ -524,7 +525,7 @@ export function Message({ message, isCompact, isFirstInGroup, previousMessageId
|
||||
);
|
||||
|
||||
return (
|
||||
<div onContextMenu={handleContextMenu}>
|
||||
<div data-context-menu onContextMenu={handleContextMenu}>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -165,6 +165,7 @@ export function MobileDmsScreen() {
|
||||
return (
|
||||
<button
|
||||
key={dm.id}
|
||||
data-context-menu
|
||||
onClick={() => handleDmTap(dm.id)}
|
||||
onContextMenu={(e) => handleDmContextMenu(e, dm.id, isGroup)}
|
||||
className="w-full flex items-center gap-3 px-4 py-3 hover:bg-interactive-hover text-left transition-colors"
|
||||
|
||||
@@ -94,7 +94,7 @@ export function MobileFolderSheet({ folder, onClose, onSelectSpace, onUpdateFold
|
||||
<div className="w-10 h-1 bg-txt-tertiary/30 rounded-full mx-auto mt-2 mb-1 shrink-0" />
|
||||
|
||||
{/* Folder header */}
|
||||
<div className="px-4 py-2 flex items-center gap-2 shrink-0" onContextMenu={handleFolderContextMenu}>
|
||||
<div className="px-4 py-2 flex items-center gap-2 shrink-0" data-context-menu onContextMenu={handleFolderContextMenu}>
|
||||
<div
|
||||
className="w-5 h-5 rounded"
|
||||
style={{ background: folder.color || 'rgb(var(--text-tertiary))' }}
|
||||
|
||||
@@ -669,6 +669,7 @@ export function MobileSpacesScreen() {
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
data-context-menu
|
||||
onClick={() => handleSpaceSelect(space.id)}
|
||||
onContextMenu={(e) => handleSpaceContextMenu(e, space.id)}
|
||||
className={`w-10 h-10 rounded-2xl overflow-hidden flex items-center justify-center transition-all ${
|
||||
@@ -765,6 +766,7 @@ export function MobileSpacesScreen() {
|
||||
return (
|
||||
<div key={category.id} className="mt-3">
|
||||
<button
|
||||
data-context-menu
|
||||
onClick={() => toggleCategory(category.id)}
|
||||
onContextMenu={(e) => handleCategoryContextMenu(e, category.id)}
|
||||
className="flex items-center gap-1 px-1 py-1 w-full text-left"
|
||||
|
||||
@@ -198,6 +198,7 @@ export function MobileVoiceFullScreen() {
|
||||
return (
|
||||
<div
|
||||
key={userId}
|
||||
data-context-menu
|
||||
className={`rounded-xl bg-surface-channel p-4 flex flex-col items-center gap-3 ${
|
||||
participantIds.length <= 2 ? 'py-8' : 'py-4'
|
||||
}`}
|
||||
|
||||
@@ -550,6 +550,10 @@ function useGlobalLongPress(isMobile: boolean) {
|
||||
};
|
||||
|
||||
const onTouchStart = (e: TouchEvent) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.closest('[data-context-menu]')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (e.touches.length !== 1) { cancel(); return; }
|
||||
const touch = e.touches[0]!;
|
||||
originX = touch.clientX;
|
||||
@@ -600,7 +604,7 @@ function useGlobalLongPress(isMobile: boolean) {
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('touchstart', onTouchStart, { passive: true });
|
||||
document.addEventListener('touchstart', onTouchStart, { passive: false });
|
||||
document.addEventListener('touchmove', onTouchMove, { passive: true });
|
||||
document.addEventListener('touchend', onTouchEnd, { passive: true });
|
||||
document.addEventListener('touchcancel', onTouchEnd, { passive: true });
|
||||
|
||||
Reference in New Issue
Block a user