ChatGPT 界面优化

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

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

  1. // ==UserScript==
  2. // @name ChatGPT 界面优化
  3. // @version 2023-6-3
  4. // @description 隐藏侧边栏快捷键、输入框大小、窗口宽度自定义调整
  5. // @match https://chat.openai.com/*
  6. // @grant GM_addStyle
  7. // @grant GM_setValue
  8. // @grant GM_getValue
  9. // @grant GM_registerMenuCommand
  10. // @grant GM_unregisterMenuCommand
  11. // @namespace your-unique-namespace
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15.  
  16.  
  17. (async () => {
  18. // #region >>>>>- 页面设置 -<<<<<
  19. let height = GM_getValue('height', 0); // 文本框高度
  20. let width = GM_getValue('width', 0); // 输入框宽度
  21. let windowWidth = GM_getValue('windowWidth', 0); // 对话窗口宽度
  22. let HideTheBottomSisclaimer = GM_getValue('HideTheBottomSisclaimer', true); // 隐藏底部免责声明
  23. let ThumbsUpFeedback = GM_getValue('ThumbsUpFeedback', true); // 隐藏赞、踩反馈按钮
  24. // 快捷键
  25. let keyModifier = GM_getValue('keyModifier', 'ctrl'); // 键修饰符
  26. let keyLetter = GM_getValue('keyLetter', 'b'); // 键字母
  27.  
  28.  
  29. function openDialog() {
  30. let dialog = document.createElement('div');
  31. dialog.id = 'Tampermonkey_setting_Box'
  32. dialog.innerHTML = `
  33. <div id="qwerSettingBox">
  34. <h2 id="qwerSettingBox_title">设置</h2>
  35. <h6 id="qwerSettingBox_hint">注意: 0 为官方默认宽度, 100 宽度将占满整个浏览器视口(以全屏为基准), 具体显示效果会因设备的屏幕大小和分辨率而有所差异</h6>
  36. <label class="qwerSettingBox_label">
  37. 文本框高度(0-100):
  38. <input class="input" min="0" max="100" id="dialogHeight" type="number" value="${height}">
  39. </label>
  40. <label class="qwerSettingBox_label">
  41. 输入框宽度(0-100):
  42. <input class="input" min="0" max="100" id="dialogWidth" type="number" value="${width}">
  43. </label>
  44. <label class="qwerSettingBox_label">
  45. 对话窗口宽(0-100):
  46. <input class="input" min="0" max="100" id="dialogWindowWidth" type="number" value="${windowWidth}">
  47. </label>
  48. <label id="shortcutSetting" class="qwerSettingBox_label">
  49. 隐藏侧边栏快捷键(a-z):
  50. <div class="FullScreenModeShortcutKeys">
  51. <select id="keyModifier">
  52. <option value="ctrl" ${keyModifier === 'ctrl' ? 'selected' : ''}>ctrl</option>
  53. <option value="alt" ${keyModifier === 'alt' ? 'selected' : ''}>alt</option>
  54. <option value="shift" ${keyModifier === 'shift' ? 'selected' : ''}>shift</option>
  55. <option value="null" ${keyModifier === 'null' ? 'selected' : ''}>关闭</option>
  56. </select>
  57. +
  58. <input class="input" id="keyLetter" type="text" value="${keyLetter}">
  59. </div>
  60. </label>
  61. <label class="qwerSettingBox_label">
  62. 隐藏底部免责声明:
  63. <input id="HideTheBottomSisclaimer" type="checkbox" ${HideTheBottomSisclaimer ? 'checked' : ''}>
  64. </label>
  65. <label class="qwerSettingBox_label">
  66. 隐藏赞、踩反馈按钮:
  67. <input id="ThumbsUpFeedback" type="checkbox" ${ThumbsUpFeedback ? 'checked' : ''}>
  68. </label>
  69. <div id="qwerSettingBox_button">
  70. <button id="dialogCancel" style="background-color: #EA4335;">取消</button>
  71. <button id="dialogOK" style="background-color: #4285F4;">确定</button>
  72. </div>
  73. </div>`;
  74. document.body.appendChild(dialog); // 添加到页面中
  75.  
  76. // 点击确定按钮
  77. document.getElementById('dialogOK').onclick = function () {
  78. let newHeight = document.getElementById('dialogHeight').value;
  79. let newWidth = document.getElementById('dialogWidth').value;
  80. let newWindowWidth = document.getElementById('dialogWindowWidth').value;
  81. let newHideTheBottomSisclaimer = document.getElementById('HideTheBottomSisclaimer').checked;
  82. let newThumbsUpFeedback = document.getElementById('ThumbsUpFeedback').checked;
  83. let newKeyModifier = document.getElementById('keyModifier').value;
  84. let newKeyLetter = document.getElementById('keyLetter').value;
  85.  
  86. GM_setValue('height', Number(newHeight));
  87. GM_setValue('width', Number(newWidth));
  88. GM_setValue('windowWidth', Number(newWindowWidth));
  89. GM_setValue('HideTheBottomSisclaimer', newHideTheBottomSisclaimer);
  90. GM_setValue('ThumbsUpFeedback', newThumbsUpFeedback);
  91. GM_setValue('keyModifier', newKeyModifier);
  92. GM_setValue('keyLetter', newKeyLetter);
  93. location.reload();
  94. };
  95. // 点击取消按钮
  96. document.getElementById('dialogCancel').onclick = function () {
  97. document.body.removeChild(dialog);
  98. };
  99. }
  100. GM_registerMenuCommand('设置', openDialog);
  101. // #endregion
  102.  
  103.  
  104. // >>>>>- 隐藏侧边栏快捷键 -<<<<<
  105. if (keyModifier) {
  106. 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"]';
  107.  
  108. // 等待 chatgpt 加载完毕
  109. await isLoaded();
  110. function isLoaded() {
  111. return new Promise(resolve => {
  112. var intervalId = setInterval(() => {
  113. if (document.querySelector(DOMSidebarButtons)) {
  114. clearInterval(intervalId);
  115. resolve();
  116. }
  117. }, 100);
  118. });
  119. }
  120.  
  121. // 侧边栏按钮
  122. let sidebarButtons = document.querySelector(DOMSidebarButtons);
  123.  
  124. // 监听页面的 DOM 变化,当新元素添加到页面时,重新插入全屏按钮
  125. var navObserver = new MutationObserver(([{ addedNodes, type }]) => {
  126. if (type === 'childList' && addedNodes.length) {
  127. setTimeout(() => {
  128. sidebarButtons = document.querySelector(DOMSidebarButtons); // 重新获取侧边栏按钮
  129. }, 20);
  130. }
  131. })
  132.  
  133. // 开始监听整个页面的 DOM 变化
  134. navObserver.observe(document.documentElement, { childList: true, subtree: true })
  135.  
  136. // 快捷键
  137. window.addEventListener('keydown', (event) => {
  138. if (event[`${keyModifier}Key`] && event.key.toLowerCase() === keyLetter.toLowerCase()) {
  139. sidebarButtons.click();
  140. }
  141. });
  142. }
  143.  
  144.  
  145. // >>>>>- 邮箱地址隐私保护 -<<<<<
  146. const observer = new MutationObserver(function (mutationsList, observer) {
  147. for (let mutation of mutationsList) {
  148. // 如果是目标元素变更,执行操作
  149. if (mutation.type === 'childList') {
  150. let _aB1cD2eF3 = document.querySelector('div[class="grow overflow-hidden text-ellipsis whitespace-nowrap text-left text-white"]');
  151. if (_aB1cD2eF3) {
  152. let Gh4iJ5kL6m = _aB1cD2eF3.textContent;
  153. let n7oP8qR9sT = Gh4iJ5kL6m.split("@");
  154. let uV0wX1yZ2A = n7oP8qR9sT[0];
  155. let B3C4D5E6F7 = n7oP8qR9sT[1];
  156. let G8H9I0J1K2 = uV0wX1yZ2A.substring(0, 2) + '***';
  157. let V3W4X5Y6Z7 = G8H9I0J1K2 + `@${B3C4D5E6F7}`;
  158. _aB1cD2eF3.textContent = V3W4X5Y6Z7;
  159. }
  160. }
  161. }
  162. });
  163. // 选择目标节点
  164. const targetNode = document.body;
  165. // 观察器的配置(需要观察什么变动)
  166. const config = { childList: true, subtree: true };
  167. // 传入目标节点和观察选项
  168. observer.observe(targetNode, config);
  169.  
  170.  
  171.  
  172.  
  173. // >>>>>- style -<<<<<
  174. GM_addStyle(`
  175. /* 文本框高度 */
  176. #prompt-textarea {
  177. max-height: ${20.6 + (0.659 * Number(height))}vh !important;
  178. }
  179.  
  180. /* 输入宽度 */
  181. .stretch {
  182. max-width: ${48 + (0.72 * Number(width))}rem !important;
  183. }
  184.  
  185. /* 对话框宽度 */
  186. .text-base {
  187. max-width: ${48 + (0.72 * Number(windowWidth))}rem !important
  188. }
  189.  
  190. /* 全屏按钮样式 */
  191. #fullWindow-button {
  192. right: 3rem !important;
  193. cursor: pointer !important;
  194. transition: 0.2s all !important;
  195. }
  196. #fullWindow-button:hover {
  197. background-color: #ECECF1 !important;
  198. }
  199.  
  200. /* Tampermonkey 设置 Box */
  201. #Tampermonkey_setting_Box {
  202. position: fixed;
  203. top: 0;
  204. left: 0;
  205. width: 100%;
  206. height: 100%;
  207. background: rgba(0, 0, 0, 0.5);
  208. display: flex;
  209. justify-content: center;
  210. z-index: 9999;
  211. }
  212.  
  213. /* 设置 */
  214. #qwerSettingBox {
  215. padding: 20px;
  216. border-radius: 5px;
  217. width: 367px;
  218. height: 490px;
  219. background: rgba(255, 255, 255, 0.93);
  220. backdrop-filter: blur(25px);
  221. margin-top: 100px;
  222. }
  223.  
  224. /* 设置标题 */
  225. #qwerSettingBox_title {
  226. margin-top: 0;
  227. color: #5F6368;
  228. text-align: center;
  229. margin-bottom: 20px;
  230. }
  231.  
  232. /* 设置提示内容 */
  233. #qwerSettingBox_hint {
  234. margin-top: 0;
  235. color: #ff9916;
  236. text-align: center;
  237. margin-bottom: 10px;
  238. font-size: 14px;
  239. }
  240.  
  241. /* label */
  242. .qwerSettingBox_label {
  243. display: block;
  244. margin-bottom: 10px;
  245. color: #5F6368;
  246. display: flex;
  247. align-items: center;
  248. justify-content: space-between;
  249. }
  250.  
  251. .qwerSettingBox_label .input {
  252. width: 118px;
  253. height: 31px;
  254. border-radius: 8px;
  255. }
  256.  
  257. /* 按钮开关 */
  258. .qwerSettingBox_label #fullScreenMode,
  259. .qwerSettingBox_label #HideTheBottomSisclaimer,
  260. .qwerSettingBox_label #ThumbsUpFeedback,
  261. .qwerSettingBox_label #HoverDisplay_ {
  262. margin-right: 76px;
  263. border-radius: 20px;
  264. width: 40px;
  265. height: 20px;
  266. cursor: pointer;
  267. -webkit-appearance: none;
  268. -moz-appearance: none;
  269. appearance: none;
  270. outline: none;
  271. }
  272.  
  273. /* 快捷键 */
  274. .qwerSettingBox_label #keyLetter {
  275. width: 25px;
  276. height: 31px;
  277. border-radius: 8px;
  278. padding: 0px 5px;
  279. }
  280. .qwerSettingBox_label #keyModifier {
  281. width: 69px;
  282. height: 31px;
  283. border-radius: 8px;
  284. padding: 0px 5px;
  285. }
  286. .qwerSettingBox_label .FullScreenModeShortcutKeys {
  287. display: flex;
  288. align-items: center;
  289. width: 118px;
  290. justify-content: space-between;
  291. }
  292.  
  293. /* 按钮 */
  294. #qwerSettingBox_button {
  295. margin-top: 30px;
  296. display: flex;
  297. justify-content: space-evenly;
  298. }
  299.  
  300. #qwerSettingBox_button button {
  301. transition: all 0.2s;
  302. color: white;
  303. border: none;
  304. width: 67px;
  305. height: 38px;
  306. cursor: pointer;
  307. border-radius: 4px;
  308. }
  309.  
  310. /* 隐藏底部免责声明 */
  311. ${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"] {
  312. display: none !important;
  313. }
  314. div[class="relative flex h-full flex-1 items-stretch md:flex-col"] {
  315. margin-bottom: 45px !important;
  316. }
  317. ` : ''
  318. }
  319.  
  320. /* 隐藏点赞反馈按钮 */
  321. ${ThumbsUpFeedback ? `div [class='flex gap-1'] {
  322. display: none !important;
  323. }
  324. ` : ''
  325. }
  326.  
  327. @media (min-width: 1280px) {
  328. .text-base {
  329. padding-left: 1rem !important;
  330. padding-right: 1rem !important;
  331. }
  332. }
  333.  
  334. @media (min-width: 1024px) {
  335. .text-base {
  336. padding-left: 1rem !important;
  337. padding-right: 1rem !important;
  338. }
  339. }
  340.  
  341. @media (min-width: 1280px) {
  342. .stretch {
  343. padding-left: 1rem !important;
  344. padding-right: 1rem !important;
  345. }
  346. }
  347.  
  348. @media (min-width: 1024px) {
  349. .stretch {
  350. padding-left: 1rem !important;
  351. padding-right: 1rem !important;
  352. }
  353. }
  354.  
  355. #dialogCancel:hover {
  356. box-shadow: 0px 0px 20px 0px rgb(0 0 0 / 28%);
  357. transform: translateY(-2px);
  358. }
  359.  
  360. #dialogOK:hover {
  361. box-shadow: 0px 0px 20px 0px rgb(0 0 0 / 28%);
  362. transform: translateY(-2px);
  363. }`)
  364.  
  365. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址