PC项目设置里允许用户切换发送按键为Enter或Command+Enter; 因此在绑定自定义快捷键时,需先根据settingStore的值去切换,使用Draftjs前,通过onKeyDown事件去监听处理。Draftjs提供了prop属性
keyBindingFn
和handleKeyCommand
目前只有对enter
和command/ctrl + enter
这两种键盘的特殊处理。Draftjs已经提供了handleReturn
方法监听enter事件:
handleReturn(e) {
e.preventDefault();
if (this.state.isMention) return 'handled';
if (!this.props.isSendWithCommand) {
this.props.onReturn();
} else {
// 换行
const changeLine = '\r\n';
this.appendContent(changeLine);
}
return 'handled';
}
在父组件中通过监听settingStore
,获取用户设置的是否发送需要CommandOrControl+Enter
this.state.settings.sendMessage.shortcut == 'CommandOrControl+Enter'
在使用keyBindingFn自定义按键事件后,发现会与handleReturn冲突,将handleReturn里的处理逻辑并到自定义事件中:
// 键盘事件处理
keyBindingFn(e) {
const isMac = util.isMac();
if (isMac && hasCommandModifier(e) && e.keyCode === 13) {
console.log('cmd-enter');
return 'cmd-enter';
}
if (!isMac && isCtrlKeyCommand(e) && e.keyCode === 13) {
return 'cmd-enter';
}
if (isMac && !hasCommandModifier(e) && e.keyCode === 13) {
return 'just-enter';
}
if (!isMac && !isCtrlKeyCommand(e) && e.keyCode === 13) {
return 'just-enter';
}
return getDefaultKeyBinding(e);
}
handleKeyCommand(command) {
const changeLine = '\r\n';
if (command === 'cmd-enter') {
if (this.props.isSendWithCommand) {
this.props.onReturn();
} else {
this.appendContent(changeLine);
}
return 'handled';
}
if (command === 'just-enter') {
if (this.props.isSendWithCommand) {
this.appendContent(changeLine);
} else {
this.props.onReturn();
}
}
return 'not-handled';
}
完成自定义快捷键后,因为去除了handleReturn,似乎不再会与mention插件的enter选中事件冲突,去除之前用于监听mention列表是否展开的state: isMention
和相关操作;
后续开发中,发现Draftjs提供的handlePastedFiles
方法也无法满足业务需求,无法获取非图片类型..
于是,添加识别cmd+v
或ctrl+v
的自定义快捷键:
if (isMac && e.keyCode === 86 && (isCtrlKeyCommand(e) || hasCommandModifier(e))) {
return 'cmd-paste';
}
handleKeyCommand(command) {
.......
if (command === 'cmd-paste') {
console.log('cmd+v');
const image = clipboard.readImage();
if (!image.isEmpty()) {
const url = image.isEmpty()? '': image.toDataURL();
this.appendImage({
data: url,
});
} else {
const rawFilePath = clipboard.read('FileNameW');
let filePath = rawFilePath.replace(new RegExp(String.fromCharCode(0), 'g'), '');
if (util.isMac()) {
filePath = clipboard.read('public.file-url').replace('file://', '');
}
if (filePath) {
if (util.isMac() && clipboard.readText()) {
clipboard.clear();
}
console.log('filePath:', decodeURI(filePath));
// TODO, 文件组件
// this.props.sendFile({
// name: '',
// path: decodeURI(filePath),
// type: '',
// size: '',
// });
}
}
let text = clipboard.readText();
if (!!text) {
text = this.parseContentWithEmojiText(text);
this.appendContent(text, 'insert-characters');
}
return 'handled';
}
return 'not-handled';
}
目前对文件的粘贴直接做发送处理,后续添加DraftEditor中的自定义文件组件;