ChatGPT 界面优化

隐藏侧边栏快捷键、输入框大小、窗口宽度自定义调整

当前为 2023-06-03 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                ChatGPT 界面优化
// @version             2023-6-3
// @description         隐藏侧边栏快捷键、输入框大小、窗口宽度自定义调整
// @match               https://chat.openai.com/*
// @grant               GM_addStyle
// @grant               GM_setValue
// @grant               GM_getValue
// @grant               GM_registerMenuCommand
// @grant               GM_unregisterMenuCommand
// @namespace           your-unique-namespace
// @license             MIT
// ==/UserScript==



(async () => {
  // #region >>>>>- 页面设置 -<<<<<
  let height = GM_getValue('height', 0); // 文本框高度
  let width = GM_getValue('width', 0); // 输入框宽度
  let windowWidth = GM_getValue('windowWidth', 0); // 对话窗口宽度
  let HideTheBottomSisclaimer = GM_getValue('HideTheBottomSisclaimer', true); // 隐藏底部免责声明
  let ThumbsUpFeedback = GM_getValue('ThumbsUpFeedback', true); // 隐藏赞、踩反馈按钮
  // 快捷键
  let keyModifier = GM_getValue('keyModifier', 'ctrl'); // 键修饰符
  let keyLetter = GM_getValue('keyLetter', 'b'); // 键字母


  function openDialog() {
    let dialog = document.createElement('div');
    dialog.id = 'Tampermonkey_setting_Box'
    dialog.innerHTML = `
  <div id="qwerSettingBox">
    <h2 id="qwerSettingBox_title">设置</h2>
    <h6 id="qwerSettingBox_hint">注意: 0 为官方默认宽度, 100 宽度将占满整个浏览器视口(以全屏为基准), 具体显示效果会因设备的屏幕大小和分辨率而有所差异</h6>
    <label class="qwerSettingBox_label">
      文本框高度(0-100):
      <input class="input" min="0" max="100" id="dialogHeight" type="number" value="${height}">
    </label>
    <label class="qwerSettingBox_label">
      输入框宽度(0-100):
      <input class="input" min="0" max="100" id="dialogWidth" type="number" value="${width}">
    </label>
    <label class="qwerSettingBox_label">
      对话窗口宽(0-100):
      <input class="input" min="0" max="100" id="dialogWindowWidth" type="number" value="${windowWidth}">
    </label>
    <label id="shortcutSetting" class="qwerSettingBox_label">
      隐藏侧边栏快捷键(a-z):
      <div class="FullScreenModeShortcutKeys">
        <select id="keyModifier">
          <option value="ctrl" ${keyModifier === 'ctrl' ? 'selected' : ''}>ctrl</option>
          <option value="alt" ${keyModifier === 'alt' ? 'selected' : ''}>alt</option>
          <option value="shift" ${keyModifier === 'shift' ? 'selected' : ''}>shift</option>
          <option value="null" ${keyModifier === 'null' ? 'selected' : ''}>关闭</option>
        </select>
        +
        <input class="input" id="keyLetter" type="text" value="${keyLetter}">
      </div>
    </label>
    <label class="qwerSettingBox_label">
      隐藏底部免责声明:
      <input id="HideTheBottomSisclaimer" type="checkbox" ${HideTheBottomSisclaimer ? 'checked' : ''}>
    </label>
    <label class="qwerSettingBox_label">
      隐藏赞、踩反馈按钮:
      <input id="ThumbsUpFeedback" type="checkbox" ${ThumbsUpFeedback ? 'checked' : ''}>
    </label>
    <div id="qwerSettingBox_button">
      <button id="dialogCancel" style="background-color: #EA4335;">取消</button>
      <button id="dialogOK" style="background-color: #4285F4;">确定</button>
    </div>
  </div>`;
    document.body.appendChild(dialog); // 添加到页面中

    // 点击确定按钮
    document.getElementById('dialogOK').onclick = function () {
      let newHeight = document.getElementById('dialogHeight').value;
      let newWidth = document.getElementById('dialogWidth').value;
      let newWindowWidth = document.getElementById('dialogWindowWidth').value;
      let newHideTheBottomSisclaimer = document.getElementById('HideTheBottomSisclaimer').checked;
      let newThumbsUpFeedback = document.getElementById('ThumbsUpFeedback').checked;
      let newKeyModifier = document.getElementById('keyModifier').value;
      let newKeyLetter = document.getElementById('keyLetter').value;

      GM_setValue('height', Number(newHeight));
      GM_setValue('width', Number(newWidth));
      GM_setValue('windowWidth', Number(newWindowWidth));
      GM_setValue('HideTheBottomSisclaimer', newHideTheBottomSisclaimer);
      GM_setValue('ThumbsUpFeedback', newThumbsUpFeedback);
      GM_setValue('keyModifier', newKeyModifier);
      GM_setValue('keyLetter', newKeyLetter);
      location.reload();
    };
    // 点击取消按钮
    document.getElementById('dialogCancel').onclick = function () {
      document.body.removeChild(dialog);
    };
  }
  GM_registerMenuCommand('设置', openDialog);
  // #endregion


  // >>>>>- 隐藏侧边栏快捷键 -<<<<<
  if (keyModifier) {
    const DOMSidebarButtons = 'a[class="flex p-3 gap-3 transition-colors duration-200 text-white cursor-pointer text-sm rounded-md border border-white/20 hover:bg-gray-500/10 h-11 w-11 flex-shrink-0 items-center justify-center"]';

    // 等待 chatgpt 加载完毕
    await isLoaded();
    function isLoaded() {
      return new Promise(resolve => {
        var intervalId = setInterval(() => {
          if (document.querySelector(DOMSidebarButtons)) {
            clearInterval(intervalId);
            resolve();
          }
        }, 100);
      });
    }

    // 侧边栏按钮
    let sidebarButtons = document.querySelector(DOMSidebarButtons);

    // 监听页面的 DOM 变化,当新元素添加到页面时,重新插入全屏按钮
    var navObserver = new MutationObserver(([{ addedNodes, type }]) => {
      if (type === 'childList' && addedNodes.length) {
        setTimeout(() => {
          sidebarButtons = document.querySelector(DOMSidebarButtons); // 重新获取侧边栏按钮
        }, 20);
      }
    })

    // 开始监听整个页面的 DOM 变化
    navObserver.observe(document.documentElement, { childList: true, subtree: true })

    // 快捷键
    window.addEventListener('keydown', (event) => {
      if (event[`${keyModifier}Key`] && event.key.toLowerCase() === keyLetter.toLowerCase()) {
        sidebarButtons.click();
      }
    });
  }


  // >>>>>- 邮箱地址隐私保护 -<<<<<
  const observer = new MutationObserver(function (mutationsList, observer) {
    for (let mutation of mutationsList) {
      // 如果是目标元素变更,执行操作
      if (mutation.type === 'childList') {
        let _aB1cD2eF3 = document.querySelector('div[class="grow overflow-hidden text-ellipsis whitespace-nowrap text-left text-white"]');
        if (_aB1cD2eF3) {
          let Gh4iJ5kL6m = _aB1cD2eF3.textContent;
          let n7oP8qR9sT = Gh4iJ5kL6m.split("@");
          let uV0wX1yZ2A = n7oP8qR9sT[0];
          let B3C4D5E6F7 = n7oP8qR9sT[1];
          let G8H9I0J1K2 = uV0wX1yZ2A.substring(0, 2) + '***';
          let V3W4X5Y6Z7 = G8H9I0J1K2 + `@${B3C4D5E6F7}`;
          _aB1cD2eF3.textContent = V3W4X5Y6Z7;
        }
      }
    }
  });
  // 选择目标节点
  const targetNode = document.body;
  // 观察器的配置(需要观察什么变动)
  const config = { childList: true, subtree: true };
  // 传入目标节点和观察选项
  observer.observe(targetNode, config);




  // >>>>>- style -<<<<<
  GM_addStyle(`
  /* 文本框高度 */
  #prompt-textarea {
    max-height: ${20.6 + (0.659 * Number(height))}vh !important;
  }

  /* 输入宽度 */
  .stretch {
    max-width: ${48 + (0.72 * Number(width))}rem !important;
  }

  /* 对话框宽度 */
  .text-base {
    max-width: ${48 + (0.72 * Number(windowWidth))}rem !important
  }

  /* 全屏按钮样式 */
  #fullWindow-button {
    right: 3rem !important;
    cursor: pointer !important;
    transition: 0.2s all !important;
  }
  #fullWindow-button:hover {
    background-color: #ECECF1 !important;
  }

  /* Tampermonkey 设置 Box */
  #Tampermonkey_setting_Box {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    z-index: 9999;
  }

  /* 设置 */
  #qwerSettingBox {
    padding: 20px;
    border-radius: 5px;
    width: 367px;
    height: 490px;
    background: rgba(255, 255, 255, 0.93);
    backdrop-filter: blur(25px);
    margin-top: 100px;
  }

  /* 设置标题 */
  #qwerSettingBox_title {
    margin-top: 0;
    color: #5F6368;
    text-align: center;
    margin-bottom: 20px;
  }

  /* 设置提示内容 */
  #qwerSettingBox_hint {
    margin-top: 0;
    color: #ff9916;
    text-align: center;
    margin-bottom: 10px;
    font-size: 14px;
  }

  /* label */
  .qwerSettingBox_label {
    display: block;
    margin-bottom: 10px;
    color: #5F6368;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .qwerSettingBox_label .input {
    width: 118px;
    height: 31px;
    border-radius: 8px;
  }

  /* 按钮开关 */
  .qwerSettingBox_label #fullScreenMode,
  .qwerSettingBox_label #HideTheBottomSisclaimer,
  .qwerSettingBox_label #ThumbsUpFeedback,
  .qwerSettingBox_label #HoverDisplay_ {
    margin-right: 76px;
    border-radius: 20px;
    width: 40px;
    height: 20px;
    cursor: pointer;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    outline: none;
  }

  /* 快捷键 */
  .qwerSettingBox_label #keyLetter {
    width: 25px;
    height: 31px;
    border-radius: 8px;
    padding: 0px 5px;
  }
  .qwerSettingBox_label #keyModifier {
    width: 69px;
    height: 31px;
    border-radius: 8px;
    padding: 0px 5px;
  }
  .qwerSettingBox_label .FullScreenModeShortcutKeys {
    display: flex;
    align-items: center;
    width: 118px;
    justify-content: space-between;
  }

  /* 按钮 */
  #qwerSettingBox_button {
    margin-top: 30px;
    display: flex;
    justify-content: space-evenly;
  }

  #qwerSettingBox_button button {
    transition: all 0.2s;
    color: white;
    border: none;
    width: 67px;
    height: 38px;
    cursor: pointer;
    border-radius: 4px;
  }

  /* 隐藏底部免责声明 */
  ${HideTheBottomSisclaimer ? `div[class="px-3 pb-3 pt-2 text-center text-xs text-gray-600 dark:text-gray-300 md:px-4 md:pb-6 md:pt-3"] {
 display: none !important;
  }
  div[class="relative flex h-full flex-1 items-stretch md:flex-col"] {
    margin-bottom: 45px !important;
  }
  ` : ''
    }

  /* 隐藏点赞反馈按钮 */
  ${ThumbsUpFeedback ? `div [class='flex gap-1'] {
 display: none !important;
  }
  ` : ''
    }

  @media (min-width: 1280px) {
    .text-base {
      padding-left: 1rem !important;
      padding-right: 1rem !important;
    }
  }

  @media (min-width: 1024px) {
    .text-base {
      padding-left: 1rem !important;
      padding-right: 1rem !important;
    }
  }

  @media (min-width: 1280px) {
    .stretch {
      padding-left: 1rem !important;
      padding-right: 1rem !important;
    }
  }

  @media (min-width: 1024px) {
    .stretch {
      padding-left: 1rem !important;
      padding-right: 1rem !important;
    }
  }

  #dialogCancel:hover {
    box-shadow: 0px 0px 20px 0px rgb(0 0 0 / 28%);
    transform: translateY(-2px);
  }

  #dialogOK:hover {
    box-shadow: 0px 0px 20px 0px rgb(0 0 0 / 28%);
    transform: translateY(-2px);
  }`)

})()