修复长按消息气泡弹出自定义菜单时,浏览器/系统原生右键菜单跟着一起弹出的问题
chat-message.jsx 新增 suppressNativeContextMenu,在气泡上监听 contextmenu 事件并 preventDefault, 避免长按(或桌面端右键/触屏模拟长按)触发的原生上下文菜单和应用自己的长按菜单重叠显示。 css/base.css 给 .bubble 补了 -webkit-touch-callout:none,同时覆盖 iOS Safari 那条独立于 contextmenu 事件之外的长按呼出菜单(复制/查询/分享...),不影响 user-select,桌面端正常的 点击拖拽选字复制不受影响。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
4ce666042e
commit
48baeceaa8
@@ -4586,6 +4586,11 @@ video {
|
|||||||
transition: ease-out background-color 0.5s;
|
transition: ease-out background-color 0.5s;
|
||||||
transition-delay: 0.3s;
|
transition-delay: 0.3s;
|
||||||
filter: drop-shadow(0.5px 0.5px 0.7px var(--clr-shadow-bubble-drop));
|
filter: drop-shadow(0.5px 0.5px 0.7px var(--clr-shadow-bubble-drop));
|
||||||
|
/* iOS Safari's press-and-hold callout (Copy/Look Up/Share...) is a separate mechanism from the
|
||||||
|
`contextmenu` DOM event suppressed in chat-message.jsx -- needs its own opt-out so it doesn't
|
||||||
|
stack with our own long-press menu. Doesn't touch user-select, so normal click-drag text
|
||||||
|
selection on desktop is untouched. */
|
||||||
|
-webkit-touch-callout: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-box li.single {
|
.chat-box li.single {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -65,6 +65,7 @@ class BaseChatMessage extends React.PureComponent {
|
|||||||
this.handleTouchStart = this.handleTouchStart.bind(this);
|
this.handleTouchStart = this.handleTouchStart.bind(this);
|
||||||
this.handleTouchMove = this.handleTouchMove.bind(this);
|
this.handleTouchMove = this.handleTouchMove.bind(this);
|
||||||
this.handleTouchEnd = this.handleTouchEnd.bind(this);
|
this.handleTouchEnd = this.handleTouchEnd.bind(this);
|
||||||
|
this.suppressNativeContextMenu = this.suppressNativeContextMenu.bind(this);
|
||||||
this.handleCancelUpload = this.handleCancelUpload.bind(this);
|
this.handleCancelUpload = this.handleCancelUpload.bind(this);
|
||||||
this.handleDraftyClick = this.handleDraftyClick.bind(this);
|
this.handleDraftyClick = this.handleDraftyClick.bind(this);
|
||||||
this.handleVoicePlayed = this.handleVoicePlayed.bind(this);
|
this.handleVoicePlayed = this.handleVoicePlayed.bind(this);
|
||||||
@@ -208,6 +209,14 @@ class BaseChatMessage extends React.PureComponent {
|
|||||||
this.longPressOrigin = null;
|
this.longPressOrigin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The press-and-hold gesture above is our own timer-based approximation of "long press" -- it
|
||||||
|
// doesn't stop the browser's own native context menu (right-click on desktop, or the OS-level
|
||||||
|
// long-press menu some browsers still fire as a real `contextmenu` event even for a touch/mouse
|
||||||
|
// hold). Left alone, both menus show up stacked on top of each other.
|
||||||
|
suppressNativeContextMenu(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.cancelLongPress();
|
this.cancelLongPress();
|
||||||
}
|
}
|
||||||
@@ -472,7 +481,8 @@ class BaseChatMessage extends React.PureComponent {
|
|||||||
<i className="material-icons red message-fail-icon">error</i> : null}
|
<i className="material-icons red message-fail-icon">error</i> : null}
|
||||||
<div>
|
<div>
|
||||||
<div className={bubbleClass}
|
<div className={bubbleClass}
|
||||||
onTouchStart={this.handleTouchStart} onTouchMove={this.handleTouchMove} onTouchEnd={this.handleTouchEnd}>
|
onTouchStart={this.handleTouchStart} onTouchMove={this.handleTouchMove} onTouchEnd={this.handleTouchEnd}
|
||||||
|
onContextMenu={this.suppressNativeContextMenu}>
|
||||||
{showVoiceUnreadDot ? <i className="voice-unread-dot" /> : null}
|
{showVoiceUnreadDot ? <i className="voice-unread-dot" /> : null}
|
||||||
<div className="content-meta">
|
<div className="content-meta">
|
||||||
<div className={textSizeClass}>
|
<div className={textSizeClass}>
|
||||||
|
|||||||
@@ -2718,6 +2718,7 @@ class BaseChatMessage extends (react__WEBPACK_IMPORTED_MODULE_0___default().Pure
|
|||||||
this.handleTouchStart = this.handleTouchStart.bind(this);
|
this.handleTouchStart = this.handleTouchStart.bind(this);
|
||||||
this.handleTouchMove = this.handleTouchMove.bind(this);
|
this.handleTouchMove = this.handleTouchMove.bind(this);
|
||||||
this.handleTouchEnd = this.handleTouchEnd.bind(this);
|
this.handleTouchEnd = this.handleTouchEnd.bind(this);
|
||||||
|
this.suppressNativeContextMenu = this.suppressNativeContextMenu.bind(this);
|
||||||
this.handleCancelUpload = this.handleCancelUpload.bind(this);
|
this.handleCancelUpload = this.handleCancelUpload.bind(this);
|
||||||
this.handleDraftyClick = this.handleDraftyClick.bind(this);
|
this.handleDraftyClick = this.handleDraftyClick.bind(this);
|
||||||
this.handleVoicePlayed = this.handleVoicePlayed.bind(this);
|
this.handleVoicePlayed = this.handleVoicePlayed.bind(this);
|
||||||
@@ -2841,6 +2842,9 @@ class BaseChatMessage extends (react__WEBPACK_IMPORTED_MODULE_0___default().Pure
|
|||||||
}
|
}
|
||||||
this.longPressOrigin = null;
|
this.longPressOrigin = null;
|
||||||
}
|
}
|
||||||
|
suppressNativeContextMenu(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.cancelLongPress();
|
this.cancelLongPress();
|
||||||
}
|
}
|
||||||
@@ -3098,6 +3102,7 @@ class BaseChatMessage extends (react__WEBPACK_IMPORTED_MODULE_0___default().Pure
|
|||||||
onTouchStart: this.handleTouchStart,
|
onTouchStart: this.handleTouchStart,
|
||||||
onTouchMove: this.handleTouchMove,
|
onTouchMove: this.handleTouchMove,
|
||||||
onTouchEnd: this.handleTouchEnd,
|
onTouchEnd: this.handleTouchEnd,
|
||||||
|
onContextMenu: this.suppressNativeContextMenu,
|
||||||
children: [showVoiceUnreadDot ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_10__.jsxDEV)("i", {
|
children: [showVoiceUnreadDot ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_10__.jsxDEV)("i", {
|
||||||
className: "voice-unread-dot"
|
className: "voice-unread-dot"
|
||||||
}, void 0, false) : null, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_10__.jsxDEV)("div", {
|
}, void 0, false) : null, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_10__.jsxDEV)("div", {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user