From 8baaa5418cbe7bf29d8a8dc63e9106cc5b8a7414 Mon Sep 17 00:00:00 2001 From: DICE Date: Fri, 31 Mar 2023 01:27:12 +0800 Subject: [PATCH] feat: support keyboard shortcuts --- forge.config.js | 4 +- main.js | 76 +++++++++++++++++++++++++++++++++--- package-lock.json | 4 +- package.json | 2 +- preload.js | 98 ++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 172 insertions(+), 12 deletions(-) diff --git a/forge.config.js b/forge.config.js index 59858fe..3a495c2 100644 --- a/forge.config.js +++ b/forge.config.js @@ -39,7 +39,7 @@ module.exports = { productName: 'BingGPT', description: 'AI-powered copilot', productDescription: 'AI-powered copilot', - version: '0.3.1', + version: '0.3.2', categories: ['Utility'], maintainer: 'dice2o', homepage: 'https://github.com/dice2o/BingGPT', @@ -56,7 +56,7 @@ module.exports = { productName: 'BingGPT', description: 'AI-powered copilot', productDescription: 'AI-powered copilot', - version: '0.3.1', + version: '0.3.2', categories: ['Utility'], maintainer: 'dice2o', homepage: 'https://github.com/dice2o/BingGPT', diff --git a/main.js b/main.js index 0e5bcc7..6717cf8 100644 --- a/main.js +++ b/main.js @@ -111,10 +111,7 @@ const createWindow = () => { type: 'checkbox', checked: mainWindow.isAlwaysOnTop() ? true : false, visible: parameters.selectionText.trim().length === 0, - click: () => { - config.set('alwaysOnTop', !mainWindow.isAlwaysOnTop()) - mainWindow.setAlwaysOnTop(!mainWindow.isAlwaysOnTop()) - }, + click: () => alwaysOnTopHandler(), }, { type: 'separator', @@ -222,7 +219,7 @@ const createWindow = () => { }, }, { - label: 'BingGPT v0.3.1', + label: 'BingGPT v0.3.2', visible: parameters.selectionText.trim().length === 0, click: () => { shell.openExternal('https://github.com/dice2o/BingGPT/releases') @@ -273,10 +270,17 @@ const createWindow = () => { mainWindow.webContents.session.webRequest.onBeforeSendHeaders( (details, callback) => { details.requestHeaders['user-agent'] = userAgent - details.requestHeaders['x-forwarded-for'] = '1.1.1.1' + if (details.url !== bingUrl) { + details.requestHeaders['x-forwarded-for'] = '1.1.1.1' + } callback({ requestHeaders: details.requestHeaders, cancel: false }) } ) + // Always on top + const alwaysOnTopHandler = () => { + config.set('alwaysOnTop', !mainWindow.isAlwaysOnTop()) + mainWindow.setAlwaysOnTop(!mainWindow.isAlwaysOnTop()) + } // Theme const themeHandler = (newTheme) => { config.set('theme', newTheme) @@ -299,6 +303,66 @@ const createWindow = () => { config.set('fontSize', newSize) mainWindow.webContents.send('set-font-size', newSize) } + // Shortcuts + mainWindow.webContents.on('before-input-event', (event, input) => { + const cmdKey = process.platform === 'darwin' ? input.meta : input.control + if (cmdKey) { + switch (input.code) { + case 'KeyN': + mainWindow.webContents.send('new-topic') + event.preventDefault() + break + case 'KeyR': + mainWindow.reload() + event.preventDefault() + break + case 'KeyT': + alwaysOnTopHandler() + event.preventDefault() + break + case 'KeyI': + mainWindow.webContents.send('focus-on-textarea') + event.preventDefault() + break + case 'KeyS': + mainWindow.webContents.send('stop-responding') + event.preventDefault() + break + case 'Equal': + if ( + configSchema.fontSize.enum.indexOf(config.get('fontSize') + 2) !== + -1 + ) { + fontSizeHandler(config.get('fontSize') + 2) + event.preventDefault() + } + break + case 'Minus': + if ( + configSchema.fontSize.enum.indexOf(config.get('fontSize') - 2) !== + -1 + ) { + fontSizeHandler(config.get('fontSize') - 2) + event.preventDefault() + } + break + case 'Comma': + mainWindow.webContents.send('switch-tone', 'left') + event.preventDefault() + break + case 'Period': + mainWindow.webContents.send('switch-tone', 'right') + event.preventDefault() + break + default: + if (input.code.indexOf('Digit') === 0) { + const id = input.code.split('Digit')[1] + mainWindow.webContents.send('quick-reply', Number(id)) + event.preventDefault() + } + } + } + }) } app.whenReady().then(() => { diff --git a/package-lock.json b/package-lock.json index a992f78..81c58ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "binggpt", - "version": "0.3.1", + "version": "0.3.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "binggpt", - "version": "0.3.1", + "version": "0.3.2", "license": "Apache-2.0", "dependencies": { "electron-context-menu": "^3.6.1", diff --git a/package.json b/package.json index 04def37..e05f7a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "binggpt", "productName": "BingGPT", - "version": "0.3.1", + "version": "0.3.2", "description": "AI-powered copilot", "author": "dice2o", "license": "Apache-2.0", diff --git a/preload.js b/preload.js index dbf31c6..f011c5a 100644 --- a/preload.js +++ b/preload.js @@ -112,6 +112,102 @@ window.addEventListener('DOMContentLoaded', () => { } }) +// New topic +ipcRenderer.on('new-topic', () => { + try { + const newTopicBtn = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-action-bar-main') + .shadowRoot.querySelector('button[class="button-compose"]') + if (newTopicBtn) { + newTopicBtn.click() + } + } catch (err) { + console.log(err) + } +}) + +// Focus on textarea +ipcRenderer.on('focus-on-textarea', () => { + try { + const textarea = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-action-bar-main') + .shadowRoot.getElementById('searchbox') + if (textarea) { + textarea.focus() + } + } catch (err) { + console.log(err) + } +}) + +// Stop responding +ipcRenderer.on('stop-responding', () => { + try { + const stopBtn = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-action-bar-main') + .shadowRoot.querySelector('cib-typing-indicator') + .shadowRoot.getElementById('stop-responding-button') + if (stopBtn) { + stopBtn.click() + } + } catch (err) { + console.log(err) + } +}) + +// Quick reply +ipcRenderer.on('quick-reply', (event, id) => { + try { + const suggestionReplies = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-conversation-main') + .shadowRoot.querySelector('cib-suggestion-bar') + .shadowRoot.querySelectorAll('cib-suggestion-item') + if (suggestionReplies) { + suggestionReplies[id - 1].shadowRoot.querySelector('button').click() + } + } catch (err) { + console.log(err) + } +}) + +// Switch tone +ipcRenderer.on('switch-tone', (event, direction) => { + try { + const toneOptions = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-conversation-main') + .shadowRoot.querySelector('cib-tone-selector') + .shadowRoot.getElementById('tone-options') + if (toneOptions) { + const toneBtns = toneOptions.querySelectorAll('button') + const selectedBtn = toneOptions.querySelector('button[selected]') + let index = Array.from(toneBtns).indexOf(selectedBtn) + switch (direction) { + case 'right': + if (index === toneBtns.length - 1) { + index = 0 + } else { + index++ + } + break + case 'left': + if (index === 0) { + index = toneBtns.length - 1 + } else { + index-- + } + } + toneBtns[index].click() + } + } catch (err) { + console.log(err) + } +}) + // Set font size ipcRenderer.on('set-font-size', (event, size) => { try { @@ -239,7 +335,7 @@ const markdownHandler = (element) => { replacement: (content, node) => { return `[${content.replace(/^(\d+)(\\.)/, '[$1]')}](${node.getAttribute( 'href' - )} "${node.getAttribute('title')}")` + )} "${node.getAttribute('title').replace(/\"/g, '')}")` }, }) turndownService.addRule('userMessage', {