- // ==UserScript==
- // @name Gemini Keyboard Shortcuts
- // @namespace http://tampermonkey.net/
- // @version 1.2.5
- // @description This userscript enhances your Gemini experience by adding a wide range of keyboard shortcuts for streamlined navigation and interaction, as well as cleaning up Gemini's UI.
- // @license MIT
- // @author Henry Getz
- // @match https://gemini.google.com/u/*
- // @match https://gemini.google.com/app*
- // @icon data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAyOCAyOCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0IDI4QzE0IDI2LjA2MzMgMTMuNjI2NyAyNC4yNDMzIDEyLjg4IDIyLjU0QzEyLjE1NjcgMjAuODM2NyAxMS4xNjUgMTkuMzU1IDkuOTA1IDE4LjA5NUM4LjY0NSAxNi44MzUgNy4xNjMzMyAxNS44NDMzIDUuNDYgMTUuMTJDMy43NTY2NyAxNC4zNzMzIDEuOTM2NjcgMTQgMCAxNEMxLjkzNjY3IDE0IDMuNzU2NjcgMTMuNjM4MyA1LjQ2IDEyLjkxNUM3LjE2MzMzIDEyLjE2ODMgOC42NDUgMTEuMTY1IDkuOTA1IDkuOTA1QzExLjE2NSA4LjY0NSAxMi4xNTY3IDcuMTYzMzMgMTIuODggNS40NkMxMy42MjY3IDMuNzU2NjcgMTQgMS45MzY2NyAxNCAwQzE0IDEuOTM2NjcgMTQuMzYxNyAzLjc1NjY3IDE1LjA4NSA1LjQ2QzE1LjgzMTcgNy4xNjMzMyAxNi44MzUgOC42NDUgMTguMDk1IDkuOTA1QzE5LjM1NSAxMS4xNjUgMjAuODM2NyAxMi4xNjgzIDIyLjU0IDEyLjkxNUMyNC4yNDMzIDEzLjYzODMgMjYuMDYzMyAxNCAyOCAxNEMyNi4wNjMzIDE0IDI0LjI0MzMgMTQuMzczMyAyMi41NCAxNS4xMkMyMC44MzY3IDE1Ljg0MzMgMTkuMzU1IDE2LjgzNSAxOC4wOTUgMTguMDk1QzE2LjgzNSAxOS4zNTUgMTUuODMxNyAyMC44MzY3IDE1LjA4NSAyMi41NEMxNC4zNjE3IDI0LjI0MzMgMTQgMjYuMDYzMyAxNCAyOFoiIGZpbGw9InVybCgjcGFpbnQwX3JhZGlhbF8xNjc3MV81MzIxMikiLz4KPGRlZnM+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQwX3JhZGlhbF8xNjc3MV81MzIxMiIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgyLjc3ODc2IDExLjM3OTUpIHJvdGF0ZSgxOC42ODMyKSBzY2FsZSgyOS44MDI1IDIzOC43MzcpIj4KPHN0b3Agb2Zmc2V0PSIwLjA2NzEyNDYiIHN0b3AtY29sb3I9IiM5MTY4QzAiLz4KPHN0b3Agb2Zmc2V0PSIwLjM0MjU1MSIgc3RvcC1jb2xvcj0iIzU2ODREMSIvPgo8c3RvcCBvZmZzZXQ9IjAuNjcyMDc2IiBzdG9wLWNvbG9yPSIjMUJBMUUzIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg==
- // @supportURL https://github.com/HenryGetz/GeminiPilot/issues
- // @grant none
- // @run-at document-start
- // ==/UserScript==
- /*
-
- #New Feature: URL Parameters!
-
- Empower your automation workflows! Directly open Gemini with pre-populated prompts by using query parameters in the URL (e.g., `https://gemini.google.com/app?q=YOURTESTPROMPT`).
-
-
- # Included Keyboard Shortcuts:
-
-
- ## Chat Management
-
- | Shortcut (Mac/Windows) | Action |
- |:--------------------------:|:--------------:|
- | ⌘/Ctrl + Shift + O | Open new chat |
- | ⌘/Ctrl + Shift + Backspace | Delete chat |
- | ⌘/Ctrl + Shift + F | Toggle sidebar |
- | ⌥/Alt + 1-9 | Go to nth chat |
- | ⌘/Ctrl + Shift + = | Next chat |
- | ⌘/Ctrl + Shift + – | Previous chat |
-
-
- ## Text Input and Editing
-
- | Shortcut (Mac/Windows) | Action |
- |:----------------------:|:-----------------------------:|
- | Shift + Esc | Focus chat input |
- | ⌘/Ctrl + Shift + E | Edit text |
- | ⌘/Ctrl + Shift + ; | Copy last code block |
- | ⌘/Ctrl + Shift + ' |Copy second-to-last code block |
- | ⌘/Ctrl + Shift + C | Copy response |
- | ⌘/Ctrl + Shift + K | Stop/start generation |
-
-
- ## Draft Navigation
-
- | Shortcut (Mac/Windows) | Action |
- |:----------------------:|:--------------------:|
- | ⌘/Ctrl + Shift + D | Generate more drafts |
- | ⌘/Ctrl + Shift + , | Next draft |
- | ⌘/Ctrl + Shift + . | Previous draft |
-
-
- ## Sharing and Linking
-
- | Shortcut (Mac/Windows) | Action |
- |:----------------------:|:-------------------------:|
- | ⌘/Ctrl + Shift + L | Copy prompt/response link |
- | ⌘/Ctrl + Shift + M | Copy chat link |
-
-
- ## Audio and File Shortcuts
-
- | Shortcut (Mac/Windows) | Action |
- |:----------------------:|:---------------------:|
- | ⌘/Ctrl + Shift + K | Stop/start generation |
- | ⌘/Ctrl + Shift + Y | Play/pause audio |
- | ⌘/Ctrl + Shift + S | Voice to text |
- | ⌘/Ctrl + O | Open file |
-
-
-
- */
-
- //With this false, it will copy from the response in the viewport.
-
- const assumeLastResponse = false;
-
- //This setting allows you to delete chats in succession, like browser tabs, instead of beign forced to go to a new one. Perfect if doing Gemini housekeeping
-
- const goToNextChatOnDelete = true;
-
-
-
- const hasQuery = window.location.href.includes("?q=");
- let url = new URL(window.location.href);
- let params = new URLSearchParams(url.search);
- let query = unescape(params.get('q'));
-
- window.onload = onLoad;
-
- function onLoad(){
- //This code makes the prompt take up the full width of the screen, and moves the heading
- let s = document.createElement("style");
- document.head.append(s);
- s.textContent = `
-
- .conversation-container, .input-area-container, .bottom-container {
- max-width: -webkit-fill-available !important;
- }
-
- .capabilities-disclaimer, #gbwa, .cdk-overlay-backdrop {
- display: none !important;
- }
-
- .code-block-decoration.footer, .code-block-decoration.header {
- user-select: none; /* Standard syntax */
- -webkit-user-select: none; /* WebKit (Safari, Chrome) browsers */
- -moz-user-select: none; /* Firefox */
- -ms-user-select: none; /* Internet Explorer/Edge */
-
- }
-
- .bottom-container {
- padding-bottom: 20px;
- }
-
- bard-mode-switcher {
- position: fixed;
- top: 0px;
- right: 64px;
- z-index: 1000;
- background: var(--bard-color-surface-container);
- border: solid var(--bard-color-surface-container) 4px;
- border-right: solid var(--bard-color-surface-container) 100px;
- transform: translate(100px, -4px);
- border-radius: 100px;
- box-shadow: 0 0 20px 12px rgba(var(--bard-color-main-container-background-rgb), 77%)
- }
-
- .mat-mdc-focus-indicator::before {
- border: none !important;
- }
-
- * > .conversation-container:first-child {
- border-top: solid transparent 60px !important;
- }
-
- `;
-
- const nums = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth"];
- const rapidClickDelayMS = 100;
- const capitalize = word => word.charAt(0).toUpperCase() + word.slice(1);
-
-
- //This code makes sure that the 'more chats' feature is selected without user interaction (so that you can select chats 6-9 with alt as well.)
-
- //This code also allows for query parameters in the URL.
-
- let showMoreClicked = false;
- let inputBarClicked = false;
- const observer = new MutationObserver((_, observer) => {
- const showMore = document.querySelector('[data-test-id="show-more-button"]');
- const inputBar = document.querySelector('.text-input-field');
- const textInput = document.querySelector('[aria-label="Enter a prompt here"]');
-
- if (showMore && !showMoreClicked) {
- showMoreClicked = true;
- simulateClick(showMore);
- }
- if (hasQuery && inputBar && !inputBarClicked) {
- if (textInput && !inputBarClicked) {
-
-
- inputBarClicked = true;
- console.log(query);
- params.delete('q');
- window.history.pushState(null,"",url.origin + url.pathname);
-
- setTimeout(function(){
- inputBar.click();
-
- setTimeout(function(){
- textInput.firstChild.remove();
- query = query.split("\n");
- for (let line of query) {
- let p = document.createElement("p");
- p.innerText = line;
- textInput.append(p);
- }
-
- //This waits to also change the url when the drafts generate. Google is weird and changes it back
- const observer = new MutationObserver((_, observer) => {
- let showDrafts = document.querySelector('[data-test-id="generate-more-drafts-button"]');
- if (showDrafts) {
- observer.disconnect();
-
- setTimeout(function(){
- url = new URL(window.location.href);
- params = new URLSearchParams(url.search);
- window.history.pushState(null,"",url.origin + url.pathname);
- }, 2000)
- }
- });
- observer.observe(document.body, {childList: true, subtree: true});
-
- setTimeout(function(){
- document.querySelector('[aria-label="Send message"]').click();
- }, rapidClickDelayMS)
- } ,rapidClickDelayMS)
- }, rapidClickDelayMS)
-
- }
- } else if (inputBar && !inputBarClicked) {
- console.log(hasQuery)
- inputBarClicked = true;
- setTimeout(() => inputBar.click(), rapidClickDelayMS)
- }
-
- if (showMoreClicked && inputBarClicked) {
- observer.disconnect();
- }
- });
- observer.observe(document.body, {childList: true, subtree: true});
-
- let c = null;
- function getLastElement(querySelector) {
- const containers = document.querySelectorAll('.conversation-container');
- c = containers[containers.length - 1];
- if (!assumeLastResponse) {
- let mostVisibleElement = null;
- let maxVisibleArea = 0;
-
- containers.forEach(container => {
- const rect = container.getBoundingClientRect();
- const viewportHeight = window.innerHeight;
-
- // Calculate visible area (only consider area within the viewport)
- const visibleArea = Math.max(0, Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0));
-
- if (visibleArea > maxVisibleArea && visibleArea !== 0) {
- maxVisibleArea = visibleArea;
- mostVisibleElement = container;
- }
- });
- c = mostVisibleElement;
- }
- return c.querySelectorAll(querySelector)[c.querySelectorAll(querySelector).length - 1];
- }
-
- function copy(text) {
- const textarea = document.createElement('textarea');
- textarea.value = text;
- document.body.appendChild(textarea);
- textarea.select();
- document.execCommand('copy');
- document.body.removeChild(textarea);
- }
-
- function copyRichTextFromDiv(element) {
- const div = element;
-
- if (!div) {
- console.error("Div not found.");
- return;
- }
-
- document.querySelectorAll('.code-block-decoration.footer, .code-block-decoration.header, .table-footer').forEach(el => el.style.display = 'none');
-
- const selection = window.getSelection();
- const range = document.createRange();
- range.selectNodeContents(div);
- selection.removeAllRanges();
- selection.addRange(range);
-
- try {
- const successful = document.execCommand('copy');
- } catch (err) {
- console.error('Failed to copy rich text: ', err);
- }
-
- selection.removeAllRanges();
- setTimeout(function(){
- document.querySelectorAll('.code-block-decoration.footer, .code-block-decoration.header').forEach(el => el.style.display = '');
- }, rapidClickDelayMS)
-
- }
-
-
-
- function clearNotifications() {
- for (let ele of document.querySelectorAll(".gemini-key-notification")) {
- ele.remove();
- }
- }
-
- function notify(text) {
- clearNotifications();
- for (let ele of document.querySelectorAll(".gmat-mdc-dialog")) {
- ele.remove();
- }
-
- var div = document.createElement('div');
- div.classList.add("gemini-key-notification");
- div.innerText = text;
- let tDuration = 125;
- let nDuration = 3000;
- let tLeft = nDuration - tDuration;
- div.style.cssText = `position: absolute;bottom: 26px;left: 26px;font-family: var(--mdc-snackbar-supporting-text-font);font-size: var(--mdc-snackbar-supporting-text-size);font-weight: var(--mdc-snackbar-supporting-text-weight);line-height: var(--mdc-snackbar-supporting-text-line-height);color: var(--mdc-snackbar-supporting-text-color);border-radius: var(--mdc-snackbar-container-shape);background-color: var(--mdc-snackbar-container-color);z-index: 2147483647;padding: 16px;line-height: 20px;transition-property: opacity, scale;transition-duration: ${tDuration}ms;transform-origin: center;scale: 0.6;opacity: 0;`;
- document.body.append(div);
- setTimeout(function(){div.style.opacity = 1; div.style.scale = 1;}, rapidClickDelayMS)
- setTimeout(function(){
- div.style.opacity = 0;
- setTimeout(function(){div.remove()}, tDuration)
- }, tLeft);
- }
-
-
- function simulateClick(element) {
- element.click();
- }
-
- let draftIndex = 0;
- let googleDraftCount = 3;
- let waitOnGeneration = false;
-
- function changeDraft(direction) {
- let draftButtons = document.querySelectorAll(".draft-preview-button");
- if (!waitOnGeneration) {
- draftIndex = (draftIndex + direction + googleDraftCount) % googleDraftCount; // Ensure index stays within 0-2
- }
-
- if (!waitOnGeneration && draftButtons[draftIndex]) {
- simulateClick(draftButtons[draftIndex]);
- //notify(`${capitalize(nums[draftIndex])} draft`)
- } else if (!waitOnGeneration) {
- draftIndex = 0;
- draftIndex = (draftIndex + direction + googleDraftCount) % googleDraftCount;
- simulateClick(getLastElement('[data-test-id="generate-more-drafts-button"]'));
- notify(`Generating ${nums[draftIndex]} draft`)
- waitOnGeneration = true;
-
- const observer = new MutationObserver((_, observer) => {
- draftButtons = document.querySelectorAll(".draft-preview-button");
- if (draftButtons[draftIndex]) {
- observer.disconnect();
- setTimeout(function(){
- waitOnGeneration = false;
- simulateClick(draftButtons[draftIndex]);
- //notify(`${capitalize(nums[draftIndex])} draft`)
- },rapidClickDelayMS * 2)
- }
- });
- observer.observe(document.body, {childList: true, subtree: true});
- } else {
- notify("Waiting on generation");
- }
- }
-
- const nextDraft = () => changeDraft(1);
- const previousDraft = () => changeDraft(-1);
-
- let chatIndex = 0;
- let waitOnLoadingMore = false;
-
- function changeChat(direction) {
- chatIndex = Array.from(document.querySelectorAll('[data-test-id="conversation"]')).indexOf(document.querySelector('.selected[data-test-id="conversation"]'));
- let chatButtons = document.querySelectorAll('[data-test-id="conversation"]');
-
- if (!waitOnLoadingMore) {
- chatIndex = Math.max(0, chatIndex + direction);
- }
-
- if (!waitOnLoadingMore && chatButtons[chatIndex]) {
- simulateClick(chatButtons[chatIndex]);
- notify(`"${chatButtons[chatIndex].querySelector(".conversation-title").innerHTML.trim()}"`)
- } else if (!waitOnLoadingMore) {
- simulateClick(document.querySelector('[data-test-id="load-more-button"]'));
- notify(`Loading chats`)
- waitOnLoadingMore = true;
-
- const observer = new MutationObserver((_, observer) => {
- chatButtons = document.querySelectorAll('[data-test-id="conversation"]');
- if (chatButtons[chatIndex]) {
- observer.disconnect();
- setTimeout(function(){
- waitOnLoadingMore = false;
- simulateClick(chatButtons[chatIndex]);
- //notify(`${capitalize(nums[draftIndex])} draft`)
- notify(`"${chatButtons[chatIndex].querySelector(".conversation-title").innerHTML.trim()}"`)
- },rapidClickDelayMS * 2)
- }
- });
- observer.observe(document.body, {childList: true, subtree: true});
- } else {
- notify("Chats loading");
- }
- }
-
- const nextChat = () => changeChat(1);
- const previousChat = () => changeChat(-1);
-
-
-
- var isMac = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);
-
- document.addEventListener('keydown', function(event) {
- // Check for Command or Control key
-
- if (event.shiftKey && event.key === "Escape") {
- simulateClick(document.querySelector('.text-input-field'));
- event.preventDefault();
- }
-
- let keyNumber = parseInt(event.code.replace("Digit",""));
- keyNumber = keyNumber === 0 ? 10 : keyNumber;
-
- if (event.altKey && keyNumber) {
- document.querySelectorAll('[data-test-id="conversation"]')[keyNumber - 1].click();
- chatIndex = Array.from(document.querySelectorAll('[data-test-id="conversation"]')).indexOf(document.querySelector('.selected[data-test-id="conversation"]'));
- notify(`"${document.querySelectorAll('[data-test-id="conversation"]')[chatIndex].querySelector(".conversation-title").innerHTML.trim()}"`)
- //notify(`${capitalize(nums[keyNumber-1])} conversation`)
- event.preventDefault();
- }
-
-
- if (event.key === "Escape" && document.activeElement.getAttribute("aria-label").includes("Edit prompt")) {
- simulateClick(getLastElement('[aria-label*="Cancel"]'));
- event.preventDefault();
- }
-
- const isCmdOrCtrl = (isMac && event.metaKey) || (!isMac && event.ctrlKey);
-
- if (!isCmdOrCtrl) return;
-
- if (isCmdOrCtrl && event.key === 'o' && !event.shiftKey) {
- event.preventDefault();
- simulateClick(document.querySelector('.upload-button button'));
- simulateClick(document.querySelector('[aria-label*="Upload files"]'))
- }
-
- switch (event.key) {
- case 'o':
- if (event.shiftKey) {
- simulateClick(document.querySelector('[aria-label*="New chat"] button'));
- simulateClick(document.querySelector('.text-input-field'));
- //notify("New chat created");
- event.preventDefault();
- } else {
- document.querySelector('[aria-label*="upload file"]').click(); setTimeout(function(){document.body.querySelector('[aria-label*="Upload files"]').click()}, rapidClickDelayMS);
- }
- break;
- //BELOW NEEDS MORE TIME
- case 'c':
- if (event.shiftKey) {
- event.preventDefault();
- getLastElement();
- copyRichTextFromDiv(c.querySelector(".model-response-text"));
- notify("Copied response")
-
-
- /* All of the below code was me desperately trying to do it through Google's menus, and failing for 2+ hours. Good riddance
-
- simulateClick(getLastElement('[aria-label*="options"]'));
- setTimeout(function(){simulateClick(document.querySelector('[aria-label*="Copy"]'))},rapidClickDelayMS*2)
- simulateClick(getLastElement('[aria-label*="options"]'));
- simulateClick(document.querySelector('#overflow-container'))
- setTimeout(function(){document.querySelector('.cdk-overlay-pane').style.top = "99999999px"; c.focus()},rapidClickDelayMS)
- clearNotifications();
- */
- }
- break;
- case 'i':
- if (event.shiftKey) {
- // Implement custom instructions if Gemini supports them
- event.preventDefault();
- }
- break;
- case 'f':
- if (event.shiftKey) {
- simulateClick(document.querySelector('[aria-label*="Main menu"]'));
- event.preventDefault();
- }
- break;
- case 'Backspace':
- if (event.shiftKey) {
- event.preventDefault();
- chatIndex = Array.from(document.querySelectorAll('[data-test-id="conversation"]')).indexOf(document.querySelector('.selected[data-test-id="conversation"]'));
- document.querySelector('.conversation.selected').parentElement.querySelector('[data-test-id="actions-menu-button"]').click(); setTimeout(function(){document.body.querySelector('[data-test-id="delete-button"]').click()}, rapidClickDelayMS); setTimeout(function(){document.body.querySelector('[data-test-id="confirm-button"]').click(); setTimeout(function(){if(goToNextChatOnDelete){simulateClick(document.querySelectorAll('[data-test-id="conversation"]')[chatIndex])}}, rapidClickDelayMS)}, rapidClickDelayMS)
- }
- break;
- case 'd':
- if (event.shiftKey) {
- let element = getLastElement('[data-test-id="generate-more-drafts-button"]');
- if (!element) {
- element = getLastElement('[mattooltip="Regenerate drafts"]');
- }
- simulateClick(element);
- event.preventDefault();
- }
- break;
- case 'e':
- if (event.shiftKey) {
- simulateClick(getLastElement('[mattooltip="Edit text"]'));
- event.preventDefault();
- }
- break;
- case ';':
- if (event.shiftKey) {
- event.preventDefault();
- // simulateClick(getLastElement('[mattooltip="Copy code"]'));
- getLastElement();
- copyRichTextFromDiv(c.querySelectorAll("code-block")[c.querySelectorAll("code-block").length - 1]);
- notify("Copied last code block to clipboard");
- }
- break;
- case '\'':
- if (event.shiftKey) {
- event.preventDefault();
- // simulateClick(getLastElement('[mattooltip="Copy code"]'));
- getLastElement();
- copyRichTextFromDiv(c.querySelectorAll("code-block")[c.querySelectorAll("code-block").length - 2]);
- notify("Copied second-last code block to clipboard");
- }
- break;
- case 'm':
- if (event.shiftKey) {
- simulateClick(getLastElement('[aria-label*="Share"]'));
- setTimeout(function(){simulateClick(document.querySelector('[aria-label*="Share response"]'))},rapidClickDelayMS)
- setTimeout(function(){simulateClick(document.querySelector('[data-test-id="share-mode-radio-button-full"] label'))},rapidClickDelayMS*2)
- setTimeout(function(){simulateClick(document.querySelector('[data-test-id="create-button"]'))},rapidClickDelayMS*3)
-
- //below waits until the link menu loads, then copies it and closes the menu
- const observer = new MutationObserver((_, observer) => {
- const element = document.querySelector('[aria-label="Copy public link"]');
- if (element) {
- observer.disconnect();
- simulateClick(element);
- setTimeout(function(){
- simulateClick(document.querySelector('[aria-label="Close"]'))
- notify("Chat link copied");
- },rapidClickDelayMS)
- }
- });
- observer.observe(document.body, {childList: true, subtree: true});
-
-
- clearNotifications();
- //notify("Last response copied to clipboard");
- event.preventDefault();
- }
- break;
- case 'l':
- if (event.shiftKey) {
- simulateClick(getLastElement('[aria-label*="Share"]'));
- setTimeout(function(){simulateClick(document.querySelector('[aria-label*="Share response"]'))},rapidClickDelayMS)
- setTimeout(function(){simulateClick(document.querySelector('[data-test-id="create-button"]'))},rapidClickDelayMS*2)
-
- //below waits until the link menu loads, then copies it and closes the menu
- const observer = new MutationObserver((_, observer) => {
- const element = document.querySelector('[aria-label="Copy public link"]');
- if (element) {
- observer.disconnect();
- simulateClick(element);
- setTimeout(function(){
- simulateClick(document.querySelector('[aria-label="Close"]'));
- notify("Prompt/response link copied");
- },rapidClickDelayMS)
- }
- });
- observer.observe(document.body, {childList: true, subtree: true});
- //notify("Last response copied to clipboard");
- event.preventDefault();
- }
- break;
- case ',':
- if (event.shiftKey) {
- previousDraft();
- }
- break;
- case '.':
- if (event.shiftKey) {
- nextDraft();
- }
- break;
- case '-':
- if (event.shiftKey) {
- event.preventDefault();
- previousChat();
- }
- break;
- case '=':
- if (event.shiftKey) {
- event.preventDefault();
- nextChat();
- }
- break;
- case 'k':
- event.preventDefault();
- if (event.shiftKey) {
- simulateClick(document.querySelector('[aria-label="Send message"]'));
- //notify("Last response copied to clipboard");
- }
- break;
- case 'y':
- if (event.shiftKey) {
- simulateClick(getLastElement('.response-tts-container button'));
- event.preventDefault();
- }
- break;
- case 's':
- if (event.shiftKey) {
- simulateClick(document.querySelector('[mattooltip="Use microphone"]'));
- event.preventDefault();
- }
- break;
- }
- });
- }