基于Draftjs实现的Electron富文本聊天输入框(四) —— 自定义快捷键

PC项目设置里允许用户切换发送按键为Enter或Command+Enter; 因此在绑定自定义快捷键时,需先根据settingStore的值去切换,使用Draftjs前,通过onKeyDown事件去监听处理。Draftjs提供了prop属性keyBindingFnhandleKeyCommand

目前只有对entercommand/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+vctrl+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中的自定义文件组件;

你可能感兴趣的:(基于Draftjs实现的Electron富文本聊天输入框(四) —— 自定义快捷键)