チャットの送信をEnterキーから変更する方法



# はじめに

近年，生成AIが注目されてきたことからチャット形式を使う機械が増えてきました．

その中で，ChatGPTやNotebookLMを使っているときに，日本語の変換を確定するためのEnterキーでチャットが送信されてしまうことがよくあります．

この記事では，その問題を解決する方法を紹介します．

:::note info
この記事ではArcのboostという機能を使っています．
対象はNotebookLMです．
:::

# 解決方法

## 1. Arcのboostを開く

まずコマンドパレットを開いて，`Tab`キーを押して`boost`と入力すると，`New: Boost`が表示されるので選択します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/23fa5383-ce41-bc70-f86b-210d640d696b.png)

:::note warn
一度そのサイトでboostを作っていると，`edit boost`が表示されるので，それを選択してください．
:::

## 2. コードを書く

以下のような画面が出てくるので，`code`を選択します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/0c970ce9-9541-d92e-80d3-dd8922ba65f8.png)

そして，`js`タブで以下のコードを入力します．
アルゴリズムの説明は後述します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/b096877a-80a0-fd3d-ee0e-3e43c91d0b5c.png)

```js
// 日本語入力確定のEnterでチャットを送信しないようにする
document.addEventListener('DOMContentLoaded', () => {
  console.log("running boost...");

  // クラス名で要素を取得する関数
  function getElementByClassName(className) {
    return document.querySelector(`.${className}`);
  }

  // 質問するテキストエリアをクラス名で指定
  const className = 'query-box-input';
  let cmdEnter = false;

  function handleKeydown(e) {
    // console.log("Keydown event detected:", e);

    // 押されたキーがCmd + Enterだった場合のみ
    if (e.key === 'Enter' && e.metaKey) {
      // console.log("Cmd + Enter detected");
      cmdEnter = true;
      // プログラム的に Enter キーの押下イベントを発生させる
      const enterEvent = new KeyboardEvent('keydown', {
        key: 'Enter',
        code: 'Enter',
        keyCode: 13,
        which: 13,
        bubbles: true,
        cancelable: true
      });
      e.target.dispatchEvent(enterEvent);
      cmdEnter = false;
      return;
    }

    // それ以外の場合はイベントの伝播を中止する(日本語の確定は行われる)
    if (e.key === 'Enter' && !cmdEnter) {
      // console.log("Stopping immediate propagation");
      e.preventDefault();
      e.stopImmediatePropagation();
    }
  }

  function checkForTextarea() {
    const textarea = getElementByClassName(className);
    if (textarea) {
      // console.log("Textarea found:", textarea);
      // console.log("Textarea content:", textarea.value);

      // そのエリア内でのキーダウン(キーの入力)のイベントを検知
      textarea.addEventListener('keydown', handleKeydown, true); // capture フェーズでイベントリスナーを設定
    } else {
      console.error("Textarea not found. ClassName:", className);
      setTimeout(checkForTextarea, 1000); // 1秒後に再チェック
    }
  }

  checkForTextarea();
});
```

## 3. boostを閉じる

`save`ボタンなどはないため，`Refresh to run`ボタンを押すか，boostを閉じることで保存されます．

## 簡単な解説

簡単な解説をします．

基本的には，`Enter`キーが押されたときに，`Cmd`キーが押されているかどうかを判定しています．
同時に押されていない場合は，`Enter`キーのイベントを発生させずに，日本語の確定を行います．

そして，`Cmd`キーが押されている場合は，`Enter`キーのイベントを発生させます．

:::note warn
notebookLMでは，本来`cmd+Enter`というショートカットはありませんが，このショートカットをここで新たに作成しています．
:::


# 2回連続でEnterを押すと送信されるようにする


## コード

```js
// 日本語入力確定のEnterでチャットを送信しないようにする
document.addEventListener('DOMContentLoaded', () => {
  console.log("running boost...");

  // クラス名で要素を取得する関数
  function getElementByClassName(className) {
    return document.querySelector(`.${className}`);
  }

  // 質問するテキストエリアをクラス名で指定
  const className = 'query-box-input';
  let doubleEnter = false;

  function handleKeydown(e) {
    console.log("Keydown event detected:", e);

    // 押されたキーがCmd + Enterだった場合のみ
    if (e.key === 'Enter') {
      console.log("Enter detected");
      if (doubleEnter === true) {
        console.log("double Enter detected")
        doubleEnter = false;
        return;
      } else {
        console.log("Stopping immediate propagation");
        doubleEnter = true;
        e.preventDefault();
        e.stopImmediatePropagation();
      }
    } else {
      doubleEnter = false;
    }
  }

  function checkForTextarea() {
    const textarea = getElementByClassName(className);
    if (textarea) {
      console.log("Textarea found:", textarea);
      console.log("Textarea content:", textarea.value);

      // そのエリア内でのキーダウン(キーの入力)のイベントを検知
      textarea.addEventListener('keydown', handleKeydown, true); // capture フェーズでイベントリスナーを設定
    } else {
      console.error("Textarea not found. ClassName:", className);
      console.log("text")
      setTimeout(checkForTextarea, 1000); // 1秒後に再チェック
    }
  }

  checkForTextarea();
});
```

## 簡単な解説

2回連続`Enter`キーを押すと送信されるようになります．

# まとめ

今回はNotebookLMでのチャットの送信を`Enter`キーから変更する方法を紹介しました．
ChatGPTなどでも同様の方法で実装できると思います．


# 参考

https://note.com/8amanami/n/ne456443cb36f