diff --git a/resources/assets/js/pages/manage/components/ChatInput/emoji.vue b/resources/assets/js/pages/manage/components/ChatInput/emoji.vue
index 789ff7f0c..2a36eb49c 100644
--- a/resources/assets/js/pages/manage/components/ChatInput/emoji.vue
+++ b/resources/assets/js/pages/manage/components/ChatInput/emoji.vue
@@ -16,13 +16,26 @@
+
-
+
@@ -414,6 +419,7 @@ export default {
quill: null,
isFocus: false,
rangeIndex: 0,
+ rangeLength: 0,
_content: '',
_options: {},
@@ -868,9 +874,13 @@ export default {
if (this.quill) {
const range = this.quill.selection.savedRange;
this.rangeIndex = range ? range.index : 0
+ this.rangeLength = range ? range.length : 0
+ }
+ } else {
+ this.rangeLength = 0;
+ if (this.rangeIndex > 0) {
+ this.quill.setSelection(this.rangeIndex)
}
- } else if (this.rangeIndex > 0) {
- this.quill.setSelection(this.rangeIndex)
}
},
@@ -1741,6 +1751,8 @@ export default {
if (item.type === 'emoji') {
this.quill.insertText(this.rangeIndex, item.text);
this.rangeIndex += item.text.length
+ this.rangeLength = 0;
+ this.quill.setSelection(this.rangeIndex, 0, 'silent');
if (this.windowLandscape && !this.isModKey) {
this.showEmoji = false;
}
@@ -1755,6 +1767,58 @@ export default {
}
},
+ onEmojiDelete() {
+ if (!this.quill) {
+ return;
+ }
+ const savedRange = this.quill.selection?.savedRange || this.quill.getSelection();
+ if (savedRange && typeof savedRange.index === 'number') {
+ this.rangeIndex = savedRange.index;
+ this.rangeLength = savedRange.length || 0;
+ }
+ if (this.rangeLength > 0) {
+ this.quill.deleteText(this.rangeIndex, this.rangeLength);
+ this.rangeLength = 0;
+ } else if (this.rangeIndex > 0) {
+ const deleteLength = this.getPreviousGraphemeLength(this.rangeIndex);
+ if (deleteLength > 0) {
+ this.quill.deleteText(this.rangeIndex - deleteLength, deleteLength);
+ this.rangeIndex -= deleteLength;
+ }
+ }
+ this.quill.setSelection(this.rangeIndex, 0, 'silent');
+ },
+
+ getPreviousGraphemeLength(index) {
+ if (!this.quill || index <= 0) {
+ return 0;
+ }
+ const textBeforeCursor = this.quill.getText(0, index);
+ if (!textBeforeCursor) {
+ return 0;
+ }
+ if (typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function') {
+ if (!this.graphemeSegmenter) {
+ this.graphemeSegmenter = new Intl.Segmenter(undefined, {granularity: 'grapheme'});
+ }
+ let lastSegment;
+ for (const segment of this.graphemeSegmenter.segment(textBeforeCursor)) {
+ lastSegment = segment;
+ }
+ if (lastSegment && lastSegment.segment) {
+ return lastSegment.segment.length;
+ }
+ }
+ const fallbackWindow = Math.min(index, 8);
+ const fallbackText = this.quill.getText(index - fallbackWindow, fallbackWindow);
+ if (!fallbackText) {
+ return 0;
+ }
+ const fallbackGraphemes = Array.from(fallbackText);
+ const lastGrapheme = fallbackGraphemes.pop();
+ return lastGrapheme ? lastGrapheme.length : 0;
+ },
+
onToolbar(action) {
this.hidePopover();
switch (action) {
diff --git a/resources/assets/sass/pages/components/chat-input.scss b/resources/assets/sass/pages/components/chat-input.scss
index d1634221b..3535f5307 100755
--- a/resources/assets/sass/pages/components/chat-input.scss
+++ b/resources/assets/sass/pages/components/chat-input.scss
@@ -511,6 +511,28 @@
flex-direction: column;
position: relative;
+ .chat-emoji-delete-btn {
+ position: absolute;
+ right: 12px;
+ bottom: 60px;
+ border: none;
+ padding: 10px 14px;
+ border-radius: 8px;
+ background: #eee;
+ color: #666;
+ font-size: 20px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ outline: none;
+
+ > svg {
+ width: 24px;
+ height: 24px;
+ }
+ }
+
.chat-emoji-emosearch {
flex-shrink: 0;
padding: 8px 8px 0;
@@ -1298,6 +1320,10 @@ body.window-portrait {
height: 50px;
line-height: 50px;
font-size: 28px;
+
+ &.delete-placeholder {
+ height: 60px;
+ }
}
&.emosearch,
&.emoticon {