perf: 优化聊天输入框

This commit is contained in:
kuaifan 2024-04-16 19:02:53 +08:00 committed by Pang
parent 6823d87198
commit cc125cc292
6 changed files with 70 additions and 30 deletions

View File

@ -47,8 +47,8 @@
"openpgp_hi": "^5.7.0-1",
"photoswipe": "^5.2.8",
"postcss": "^8.4.5",
"quill": "^2.0.0-rc.5",
"quill-mention-hi": "^4.0.0-2",
"quill-hitosea": "^2.0.0-rc.5.1",
"quill-mention-hitosea": "^4.0.0-6",
"resolve-url-loader": "^4.0.0",
"sass": "^1.71.1",
"sass-loader": "^14.1.1",

View File

@ -40,7 +40,9 @@
@paste="handlePaste"></div>
<!-- 工具栏占位 -->
<div class="chat-space"></div>
<div class="chat-space">
<input class="space-input" @focus="onSpaceInputFocus"/>
</div>
<!-- 工具栏 -->
<ul class="chat-toolbar" @click.stop>
@ -211,8 +213,8 @@
<script>
import {mapState} from "vuex";
import Quill from 'quill';
import "quill-mention-hi";
import Quill from 'quill-hitosea';
import "quill-mention-hitosea";
import ChatEmoji from "./emoji";
import touchmouse from "../../../../directives/touchmouse";
import touchclick from "../../../../directives/touchclick";
@ -324,10 +326,11 @@ export default {
emojiTimer: null,
scrollTimer: null,
selectTimer: null,
textTimer: null,
fileTimer: null,
moreTimer: null,
selectTimer: null,
selectRange: null,
fullInput: false,
fullQuill: null,
@ -640,7 +643,7 @@ export default {
keyboard: {
bindings: {
'short enter': {
key: 13,
key: "Enter",
shortKey: true,
handler: _ => {
if (!this.isEnterSend) {
@ -651,7 +654,7 @@ export default {
}
},
'enter': {
key: 13,
key: "Enter",
shiftKey: false,
handler: _ => {
if (this.isEnterSend) {
@ -662,7 +665,7 @@ export default {
}
},
'esc': {
key: 27,
key: "Escape",
shiftKey: false,
handler: _ => {
if (this.emojiQuickShow) {
@ -691,15 +694,15 @@ export default {
// Mark model as touched if editor lost focus
this.quill.on('selection-change', range => {
if (!range && document.activeElement) {
//
if (['ql-editor', 'ql-clipboard'].includes(document.activeElement.className)) {
this.selectTimer && clearTimeout(this.selectTimer)
this.selectTimer = setTimeout(_ => {
this.quill.setSelection(document.activeElement.className === 'ql-editor' ? 0 : this.quill.getLength())
}, 100)
return
}
if (range) {
this.selectRange = range
} else if (this.selectRange && document.activeElement && /(ql-editor|ql-clipboard)/.test(document.activeElement.className)) {
// iOS
this.selectTimer && clearTimeout(this.selectTimer)
this.selectTimer = setTimeout(_ => {
this.quill.setSelection(this.selectRange.index, this.selectRange.length)
}, 100)
return
}
this.isFocus = !!range;
})
@ -765,8 +768,8 @@ export default {
this.$nextTick(_ => {
this.quill.root.addEventListener('keydown', e => {
if (e.key === '\r\r' && e.keyCode === 229) {
const length = this.quill.getSelection(true).index;
this.quill.insertText(length, "\r\n");
const {index} = this.quill.getSelection(true);
this.quill.insertText(index, "\r\n");
//
this.keyTimer && clearTimeout(this.keyTimer)
this.keyTimer = setTimeout(_ => {
@ -950,7 +953,7 @@ export default {
setContent(value) {
if (this.quill) {
this.quill.setContents(this.quill.clipboard.convert(value))
this.quill.setContents(this.quill.clipboard.convert({html: value}))
}
},
@ -1310,6 +1313,13 @@ export default {
})
},
onSpaceInputFocus() {
if (this.selectRange) {
// Android
this.quill?.setSelection(this.selectRange.index, this.selectRange.length)
}
},
openMenu(char) {
if (!this.quill) {
return;
@ -1330,7 +1340,10 @@ export default {
if (!this.quill) {
return;
}
this.quill.getModule("mention").insertItem(data, true);
const {index} = this.quill.getSelection(true);
this.quill.insertEmbed(index, "mention", data, Quill.sources.USER);
this.quill.insertText(index + 1, " ", Quill.sources.USER);
this.quill.setSelection(index + 2, Quill.sources.USER);
},
getProjectId() {
@ -1665,9 +1678,9 @@ export default {
array.forEach(image => {
const t = new FileReader;
t.onload = ({target}) => {
const length = this.quill.getSelection(true).index;
this.quill.insertEmbed(length, "image", target.result);
this.quill.setSelection(length + 1)
const {index} = this.quill.getSelection(true);
this.quill.insertEmbed(index, "image", target.result);
this.quill.setSelection(index + 1)
};
t.readAsDataURL(image)
})

View File

@ -501,7 +501,7 @@ export default {
recordStyle(info) {
const {duration} = info;
const width = 50 + Math.min(180, Math.floor(duration / 150));
const width = 50 + Math.min(180, Math.floor(duration / 200));
return {
width: width + 'px',
};

View File

@ -194,6 +194,12 @@ body.dark-mode-reverse {
}
}
.dialog-position {
.position-label {
color: #000000;
}
}
.dialog-scroller {
.dialog-item {
.dialog-view {
@ -541,6 +547,12 @@ body.dark-mode-reverse {
}
}
.chat-input-record-transfer {
&.cancel {
color: #000000;
}
}
.ql-mention-list-container {
.ql-mention-list-item {
.mention-item-at {

View File

@ -1,5 +1,5 @@
@import "~quill/dist/quill.bubble.css";
@import "~quill-mention-hi/dist/quill.mention.min.css";
@import "~quill-hitosea/dist/quill.bubble.css";
@import "~quill-mention-hitosea/dist/quill.mention.min.css";
.chat-input-box {
display: inline-block;
@ -224,6 +224,21 @@
float: right;
width: 170px;
height: 30px;
.space-input {
border: none;
outline: none;
box-shadow: none;
background: transparent;
height: 1px;
width: 1px;
overflow: hidden;
&:focus,
&:active {
border: none;
outline: none;
box-shadow: none;
}
}
}
.chat-toolbar {

4
vite.config.js vendored
View File

@ -49,8 +49,8 @@ export default defineConfig(({command, mode}) => {
resolve: {
alias: {
'~element-sea': resolve(__dirname, 'node_modules/element-sea'),
'~quill': resolve(__dirname, 'node_modules/quill'),
'~quill-mention-hi': resolve(__dirname, 'node_modules/quill-mention-hi'),
'~quill-hitosea': resolve(__dirname, 'node_modules/quill-hitosea'),
'~quill-mention-hitosea': resolve(__dirname, 'node_modules/quill-mention-hitosea'),
'../images': resolve(__dirname, command === 'serve' ? '/images' : 'resources/assets/statics/public/images'),
'../css': resolve(__dirname, command === 'serve' ? '/css' : 'resources/assets/statics/public/css')
},