From e01d0bc34d045d4bd751d1dbcd6abebb8b4ea645 Mon Sep 17 00:00:00 2001 From: lony2003 Date: Fri, 5 Jan 2024 21:19:58 +0800 Subject: [PATCH] login error found, but no fix currently --- electron-builder.json5 | 33 +- electron/main.js | 850 ++++++++++++++++++++--------------------- electron/preload.js | 633 +++++++++++++++--------------- src/App.vue | 2 +- src/pages/Main.vue | 9 +- src/pages/Splash.vue | 2 +- 6 files changed, 784 insertions(+), 745 deletions(-) diff --git a/electron-builder.json5 b/electron-builder.json5 index 3df7db4..2a5c98d 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -16,7 +16,13 @@ ], "mac": { "target": [ - "dmg" + { + "target": "dmg", + "arch": [ + "x64", + "arm64" + ] + } ], "artifactName": "${productName}-Mac-${arch}-${version}-Installer.${ext}" }, @@ -26,7 +32,8 @@ { "target": "nsis", "arch": [ - "x64" + "x64", + "arm64" ] } ], @@ -40,7 +47,27 @@ }, "linux": { "target": [ - "AppImage", "deb", "rpm" + { + "target": "AppImage", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "deb", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "rpm", + "arch": [ + "x64", + "arm64" + ] + } ], "artifactName": "${productName}-Linux-${arch}-${version}.${ext}" } diff --git a/electron/main.js b/electron/main.js index 860e10b..04277eb 100644 --- a/electron/main.js +++ b/electron/main.js @@ -16,6 +16,7 @@ import * as urlUtil from "node:url" process.env.DIST = path.join(__dirname, '../dist') process.env.VITE_PUBLIC = app.isPackaged ? process.env.DIST : path.join(process.env.DIST, '../public') +app.commandLine.appendSwitch('disable-site-isolation-trials'); let mainWindow // 🚧 Use ['ENV_NAME'] avoid vite:define plugin - Vite@2.x @@ -23,469 +24,464 @@ const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL'] //config init const configSchema = { - theme: { - enum: ['system', 'light', 'dark'], - default: 'system', - }, - fontSize: { - enum: [14, 16, 18, 20], - default: 14, - }, - alwaysOnTop: { - type: 'boolean', - default: false, - }, + theme: { + enum: ['system', 'light', 'dark'], + default: 'system', + }, + fontSize: { + enum: [14, 16, 18, 20], + default: 14, + }, + alwaysOnTop: { + type: 'boolean', + default: false, + }, } -const config = new Store({ schema: configSchema, clearInvalidConfig: true }) +const config = new Store({schema: configSchema, clearInvalidConfig: true}) function getWrapperUrl() { - // and load the index.html of the app. - if (VITE_DEV_SERVER_URL) { - return VITE_DEV_SERVER_URL; - } else { - return urlUtil.format({ - protocol: 'file', - slashes: true, - pathname: path.join(process.env.DIST, 'index.html') - }) - } + // and load the index.html of the app. + if (VITE_DEV_SERVER_URL) { + return VITE_DEV_SERVER_URL; + } else { + return urlUtil.format({ + protocol: 'file', + slashes: true, + pathname: path.join(process.env.DIST, 'index.html') + }) + } } function createWindow() { - // Get theme settings - const theme = config.get('theme') - const isDarkMode = - theme === 'system' - ? nativeTheme.shouldUseDarkColors - : theme === 'dark' - ? true - : false + // Get theme settings + const theme = config.get('theme') + const isDarkMode = + theme === 'system' + ? nativeTheme.shouldUseDarkColors + : theme === 'dark' + ? true + : false - nativeTheme.themeSource = theme + nativeTheme.themeSource = theme - // win = new BrowserWindow({ - // icon: path.join(process.env.VITE_PUBLIC, 'electron-vite.svg'), - // webPreferences: { - // preload: path.join(__dirname, 'preload.js'), - // }, - // }) + // win = new BrowserWindow({ + // icon: path.join(process.env.VITE_PUBLIC, 'electron-vite.svg'), + // webPreferences: { + // preload: path.join(__dirname, 'preload.js'), + // }, + // }) - mainWindow = new BrowserWindow({ - title: 'BingGPT', - backgroundColor: isDarkMode ? '#1c1c1c' : '#eeeeee', - icon:path.join(process.env.VITE_PUBLIC, 'icon.png'), - width: 601, - height: 800, - titleBarStyle: 'hidden', - titleBarOverlay: { - color: isDarkMode ? '#333333' : '#ffffff', - symbolColor: isDarkMode ? '#eeeeee' : '#1c1c1c', - }, - webPreferences: { - preload: path.join(__dirname, 'preload.js'), - devTools: true, - nodeIntegration: true, - }, - }) + mainWindow = new BrowserWindow({ + title: 'BingGPT', + backgroundColor: isDarkMode ? '#1c1c1c' : '#eeeeee', + icon: path.join(process.env.VITE_PUBLIC, 'icon.png'), + width: 601, + height: 800, + titleBarStyle: 'hidden', + titleBarOverlay: { + color: isDarkMode ? '#333333' : '#ffffff', + symbolColor: isDarkMode ? '#eeeeee' : '#1c1c1c', + }, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + devTools: true, + nodeIntegration: true, + contextIsolation: false, + webSecurity: false, + allowRunningInsecureContent: true + }, + }) - // Get always on top settings - const alwaysOnTop = config.get('alwaysOnTop') - mainWindow.setAlwaysOnTop(alwaysOnTop) + // Get always on top settings + const alwaysOnTop = config.get('alwaysOnTop') + mainWindow.setAlwaysOnTop(alwaysOnTop) - // Hide main menu (Windows) - Menu.setApplicationMenu(null) - // Create context menu - contextMenu({ - window: mainWindow.webContents, - showServices: true, - showSelectAll: false, - append: (defaultActions, parameters, browserWindow) => [ - { - label: 'Reload', - visible: parameters.selectionText.trim().length === 0, - click: () => { - mainWindow.reload() - }, - }, - { - label: 'Export', - visible: parameters.selectionText.trim().length === 0, - submenu: [ - { - label: 'Markdown', - click() { - mainWindow.webContents.send('export', 'md', isDarkMode) + // Hide main menu (Windows) + Menu.setApplicationMenu(null) + // Create context menu + contextMenu({ + window: mainWindow.webContents, + showServices: true, + showSelectAll: false, + append: (defaultActions, parameters, browserWindow) => [ + { + label: 'Reload', + visible: parameters.selectionText.trim().length === 0, + click: () => { + mainWindow.reload() + }, }, - }, - { - label: 'PNG', - click() { - mainWindow.webContents.send('export', 'png', isDarkMode) + { + label: 'Export', + visible: parameters.selectionText.trim().length === 0, + submenu: [ + { + label: 'Markdown', + click() { + mainWindow.webContents.send('export', 'md', isDarkMode) + }, + }, + { + label: 'PNG', + click() { + mainWindow.webContents.send('export', 'png', isDarkMode) + }, + }, + { + label: 'PDF', + click() { + mainWindow.webContents.send('export', 'pdf', isDarkMode) + }, + }, + ], }, - }, - { - label: 'PDF', - click() { - mainWindow.webContents.send('export', 'pdf', isDarkMode) + { + type: 'separator', + visible: parameters.selectionText.trim().length === 0, }, - }, - ], - }, - { - type: 'separator', - visible: parameters.selectionText.trim().length === 0, - }, - { - label: 'Always on Top', - type: 'checkbox', - checked: mainWindow.isAlwaysOnTop() ? true : false, - visible: parameters.selectionText.trim().length === 0, - click: () => alwaysOnTopHandler(), - }, - { - type: 'separator', - visible: parameters.selectionText.trim().length === 0, - }, - { - label: 'Appearance', - visible: parameters.selectionText.trim().length === 0, - submenu: [ - { - label: 'Theme', - submenu: [ - { - label: 'System', - type: 'radio', - checked: config.get('theme') === 'system', - click() { - themeHandler('system') - }, - }, - { - label: 'Light', - type: 'radio', - checked: config.get('theme') === 'light', - click() { - themeHandler('light') - }, - }, - { - label: 'Dark', - type: 'radio', - checked: config.get('theme') === 'dark', - click() { - themeHandler('dark') - }, - }, - ], - }, - { - label: 'Font Size', - submenu: [ - { - label: 'Default', - type: 'radio', - checked: config.get('fontSize') === 14, - click() { - fontSizeHandler(14) - }, - }, - { - label: 'Medium', - type: 'radio', - checked: config.get('fontSize') === 16, - click() { - fontSizeHandler(16) + { + label: 'Always on Top', + type: 'checkbox', + checked: mainWindow.isAlwaysOnTop() ? true : false, + visible: parameters.selectionText.trim().length === 0, + click: () => alwaysOnTopHandler(), + }, + { + type: 'separator', + visible: parameters.selectionText.trim().length === 0, + }, + { + label: 'Appearance', + visible: parameters.selectionText.trim().length === 0, + submenu: [ + { + label: 'Theme', + submenu: [ + { + label: 'System', + type: 'radio', + checked: config.get('theme') === 'system', + click() { + themeHandler('system') + }, + }, + { + label: 'Light', + type: 'radio', + checked: config.get('theme') === 'light', + click() { + themeHandler('light') + }, + }, + { + label: 'Dark', + type: 'radio', + checked: config.get('theme') === 'dark', + click() { + themeHandler('dark') + }, + }, + ], + }, + { + label: 'Font Size', + submenu: [ + { + label: 'Default', + type: 'radio', + checked: config.get('fontSize') === 14, + click() { + fontSizeHandler(14) + }, + }, + { + label: 'Medium', + type: 'radio', + checked: config.get('fontSize') === 16, + click() { + fontSizeHandler(16) + }, + }, + { + label: 'Large', + type: 'radio', + checked: config.get('fontSize') === 18, + click() { + fontSizeHandler(18) + }, + }, + { + label: 'Extra Large', + type: 'radio', + checked: config.get('fontSize') === 20, + click() { + fontSizeHandler(20) + }, + }, + ], + }, + ], + }, + { + type: 'separator', + visible: parameters.selectionText.trim().length === 0, + }, + { + label: 'Reset', + visible: parameters.selectionText.trim().length === 0, + click: () => { + mainWindow.webContents.session.clearStorageData().then(() => { + mainWindow.reload() + }) }, - }, - { - label: 'Large', - type: 'radio', - checked: config.get('fontSize') === 18, - click() { - fontSizeHandler(18) + }, + { + type: 'separator', + visible: parameters.selectionText.trim().length === 0, + }, + { + label: 'Feedback', + visible: parameters.selectionText.trim().length === 0, + click: () => { + shell.openExternal('https://github.com/fangkehou-team/BingGPT/issues') }, - }, - { - label: 'Extra Large', - type: 'radio', - checked: config.get('fontSize') === 20, - click() { - fontSizeHandler(20) + }, + { + label: 'BingGPT v0.4.3', + visible: parameters.selectionText.trim().length === 0, + click: () => { + shell.openExternal('https://github.com/fangkehou-team/BingGPT/releases') }, - }, - ], - }, + }, ], - }, - { - type: 'separator', - visible: parameters.selectionText.trim().length === 0, - }, - { - label: 'Reset', - visible: parameters.selectionText.trim().length === 0, - click: () => { - mainWindow.webContents.session.clearStorageData().then(() => { - mainWindow.reload() - }) - }, - }, - { - type: 'separator', - visible: parameters.selectionText.trim().length === 0, - }, - { - label: 'Feedback', - visible: parameters.selectionText.trim().length === 0, - click: () => { - shell.openExternal('https://github.com/fangkehou-team/BingGPT/issues') - }, - }, - { - label: 'BingGPT v0.3.7', - visible: parameters.selectionText.trim().length === 0, - click: () => { - shell.openExternal('https://github.com/fangkehou-team/BingGPT/releases') - }, - }, - ], - }) + }) - const bingUrl = getWrapperUrl() - mainWindow.loadURL(urlUtil.format(bingUrl)) + const bingUrl = getWrapperUrl() + mainWindow.loadURL(urlUtil.format(bingUrl)) - // mainWindow.webContents.openDevTools(); + // mainWindow.webContents.openDevTools(); - // Open links in default browser - mainWindow.webContents.setWindowOpenHandler(({ url }) => { - shell.openExternal(url) - return { action: 'deny' } - }) - // Login - mainWindow.webContents.on('will-redirect', (event, url) => { - if ( - url.indexOf('https://edgeservices.bing.com/edgesvc/urlredirect') !== -1 - ) { - event.preventDefault() - // Get cookies - mainWindow - ?.loadURL(bingUrl.replace('edgediscover/query', 'edgesvc/shell')) - .then(() => { - setTimeout(() => { - mainWindow.loadURL(bingUrl) - }, 3000) - }) - } - }) - // Modify Content Security Policy - mainWindow.webContents.session.webRequest.onHeadersReceived( - (details, callback) => { - let responseHeaders = details.responseHeaders - const CSP = responseHeaders['content-security-policy'] - if (details.url === bingUrl && CSP) { - responseHeaders['content-security-policy'] = CSP[0] - .replace(`require-trusted-types-for 'script'`, '') - .replace('report-to csp-endpoint', '') - callback({ - cancel: false, - responseHeaders, - }) - } else { - return callback({ cancel: false }) - } - } - ) - // Always on top - const alwaysOnTopHandler = () => { - config.set('alwaysOnTop', !mainWindow.isAlwaysOnTop()) - mainWindow.setAlwaysOnTop(!mainWindow.isAlwaysOnTop()) - } - // Theme - const themeHandler = (newTheme) => { - config.set('theme', newTheme) - dialog - .showMessageBox(mainWindow, { - type: 'question', - buttons: ['Yes', 'No'], - message: 'Theme Saved', - detail: 'Do you want to reload BingGPT now?', - }) - .then((result) => { - if (result.response === 0) { - mainWindow.close() - createWindow() - } - }) - } - // Font size - const fontSizeHandler = (newSize) => { - 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)) + // Open links in default browser + mainWindow.webContents.setWindowOpenHandler(({url}) => { + shell.openExternal(url) + return {action: 'deny'} + }) + // Login + mainWindow.webContents.on('will-redirect', (event, url) => { + if ( + url.indexOf('https://bing.com') !== -1 + ) { event.preventDefault() - } - } + // Get cookies + mainWindow.loadURL(urlUtil.format(bingUrl + "?login=1")) + } + }) + // Modify Content Security Policy + mainWindow.webContents.session.webRequest.onHeadersReceived( + (details, callback) => { + let responseHeaders = details.responseHeaders + const CSP = responseHeaders['content-security-policy'] + if (details.url === bingUrl && CSP) { + responseHeaders['content-security-policy'] = CSP[0] + .replace(`require-trusted-types-for 'script'`, '') + .replace('report-to csp-endpoint', '') + callback({ + cancel: false, + responseHeaders, + }) + } else { + return callback({cancel: false}) + } + } + ) + // Always on top + const alwaysOnTopHandler = () => { + config.set('alwaysOnTop', !mainWindow.isAlwaysOnTop()) + mainWindow.setAlwaysOnTop(!mainWindow.isAlwaysOnTop()) } - }) - // Replace compose page or reload window - mainWindow.webContents.on('dom-ready', () => { - const url = mainWindow.webContents.getURL() - if (url === bingUrl) { - mainWindow.webContents.send('replace-compose-page', isDarkMode) + // Theme + const themeHandler = (newTheme) => { + config.set('theme', newTheme) + dialog + .showMessageBox(mainWindow, { + type: 'question', + buttons: ['Yes', 'No'], + message: 'Theme Saved', + detail: 'Do you want to reload BingGPT now?', + }) + .then((result) => { + if (result.response === 0) { + mainWindow.close() + createWindow() + } + }) } - - // console.log(url); - if (url === "https://www.bing.com/") { - setTimeout(() => { - mainWindow.loadURL(urlUtil.format(bingUrl + "?login=1")); - }, 3000); + // Font size + const fontSizeHandler = (newSize) => { + 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() + } + } + } + }) + // Replace compose page or reload window + mainWindow.webContents.on('dom-ready', () => { + const url = mainWindow.webContents.getURL() + if (url === bingUrl) { + mainWindow.webContents.send('replace-compose-page', isDarkMode) + } - }) + if (url.indexOf('https://www.bing.com') !== -1) { + setTimeout(()=>{ + mainWindow.webContents.loadURL(urlUtil.format(bingUrl + "?login=1")); + }, 3000); + } + }) } app.whenReady().then(() => { - // Save to file - ipcMain.on('export-data', (event, format, dataURL) => { - if (format) { - const fileName = `BingGPT-${Math.floor(Date.now() / 1000)}.${format}` - let filters - switch (format) { - case 'md': - filters = [{ name: 'Markdown', extensions: ['md'] }] - break - case 'png': - filters = [{ name: 'Image', extensions: ['png'] }] - break - case 'pdf': - filters = [{ name: 'PDF', extensions: ['pdf'] }] - } - dialog - .showSaveDialog(BrowserWindow.getAllWindows()[0], { - title: 'Export', - defaultPath: fileName, - filters: filters, - }) - .then((result) => { - if (!result.canceled) { - const filePath = result.filePath - const data = dataURL.replace(/^data:\S+;base64,/, '') - fs.writeFile(filePath, data, 'base64', (err) => { - if (err) { - dialog.showMessageBox({ - type: 'info', - message: 'Error', - detail: err, - }) - } - }) + // Save to file + ipcMain.on('export-data', (event, format, dataURL) => { + if (format) { + const fileName = `BingGPT-${Math.floor(Date.now() / 1000)}.${format}` + let filters + switch (format) { + case 'md': + filters = [{name: 'Markdown', extensions: ['md']}] + break + case 'png': + filters = [{name: 'Image', extensions: ['png']}] + break + case 'pdf': + filters = [{name: 'PDF', extensions: ['pdf']}] } - }) - } - }) - // Init style - ipcMain.on('init-style', () => { - const fontSize = config.get('fontSize') - setTimeout(() => { - if (fontSize !== 14) { - BrowserWindow.getAllWindows()[0].webContents.send( - 'set-font-size', - fontSize - ) - } - BrowserWindow.getAllWindows()[0].webContents.send('set-initial-style') - }, 1000) - }) - // Error message - ipcMain.on('error', (event, detail) => { - dialog.showMessageBox({ - type: 'info', - message: 'Error', - detail: detail, + dialog + .showSaveDialog(BrowserWindow.getAllWindows()[0], { + title: 'Export', + defaultPath: fileName, + filters: filters, + }) + .then((result) => { + if (!result.canceled) { + const filePath = result.filePath + const data = dataURL.replace(/^data:\S+;base64,/, '') + fs.writeFile(filePath, data, 'base64', (err) => { + if (err) { + dialog.showMessageBox({ + type: 'info', + message: 'Error', + detail: err, + }) + } + }) + } + }) + } }) - }) - //getChatUrl - ipcMain.on("get-chat-url", (event, page) => { + // Init style + ipcMain.on('init-style', () => { + const fontSize = config.get('fontSize') + setTimeout(() => { + if (fontSize !== 14) { + BrowserWindow.getAllWindows()[0].webContents.send( + 'set-font-size', + fontSize + ) + } + BrowserWindow.getAllWindows()[0].webContents.send('set-initial-style') + }, 1000) + }) + // Error message + ipcMain.on('error', (event, detail) => { + dialog.showMessageBox({ + type: 'info', + message: 'Error', + detail: detail, + }) + }) + //getChatUrl + ipcMain.on("get-chat-url", (event, page) => { - // Get theme settings - const theme = config.get('theme') - const isDarkMode = - theme === 'system' - ? nativeTheme.shouldUseDarkColors - : theme === 'dark' - ? true - : false - const locale = app.getLocale() || 'en-US' + // Get theme settings + const theme = config.get('theme') + const isDarkMode = + theme === 'system' + ? nativeTheme.shouldUseDarkColors + : theme === 'dark' + ? true + : false + const locale = app.getLocale() || 'en-US' - // Load Bing - event.returnValue = `https://edgeservices.bing.com/edgesvc/${page}?&${ - isDarkMode ? 'dark' : 'light' - }schemeovr=1&FORM=SHORUN&udscs=1&udsnav=1&setlang=${locale}&features=udssydinternal&clientscopes=noheader,coauthor,chat,channelstable,&udsframed=1` + // Load Bing + event.returnValue = `https://edgeservices.bing.com/edgesvc/${page}?&${ + isDarkMode ? 'dark' : 'light' + }schemeovr=1&FORM=SHORUN&udscs=1&udsnav=1&setlang=${locale}&features=udssydinternal&clientscopes=noheader,coauthor,chat,channelstable,&udsframed=1` - }) - createWindow() - app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) createWindow() - }) + }) + createWindow() + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow() + }) }) app.on('window-all-closed', () => { - if (process.platform !== 'darwin') app.quit() + if (process.platform !== 'darwin') app.quit() }) diff --git a/electron/preload.js b/electron/preload.js index 10468ce..4621da0 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -1,6 +1,6 @@ -import { contextBridge, ipcRenderer } from 'electron' +import {contextBridge, ipcRenderer} from 'electron' import html2canvas from 'html2canvas' -import { jsPDF } from 'jspdf' +import {jsPDF} from 'jspdf' import TurndownService from 'turndown' // --------- Expose some API to the Renderer process --------- @@ -8,374 +8,389 @@ import TurndownService from 'turndown' // `exposeInMainWorld` can't detect attributes and methods of `prototype`, manually patching it. function withPrototype(obj) { - const protos = Object.getPrototypeOf(obj) + const protos = Object.getPrototypeOf(obj) - for (const [key, value] of Object.entries(protos)) { - if (Object.prototype.hasOwnProperty.call(obj, key)) continue + for (const [key, value] of Object.entries(protos)) { + if (Object.prototype.hasOwnProperty.call(obj, key)) continue - if (typeof value === 'function') { - // Some native APIs, like `NodeJS.EventEmitter['on']`, don't work in the Renderer process. Wrapping them into a function. - obj[key] = function (...args) { - return value.call(obj, ...args) - } - } else { - obj[key] = value + if (typeof value === 'function') { + // Some native APIs, like `NodeJS.EventEmitter['on']`, don't work in the Renderer process. Wrapping them into a function. + obj[key] = function (...args) { + return value.call(obj, ...args) + } + } else { + obj[key] = value + } } - } - return obj + return obj } window.addEventListener('DOMContentLoaded', () => { - // Change page title - document.title = 'BingGPT' + // Change page title + document.title = 'BingGPT' - // Chat area of main page - // const results = document.getElementById('b_results') - // if (results) { - // const chatWrapper = document.getElementsByClassName('uds_sydney_wrapper')[0] - // const serp = document.getElementsByTagName('cib-serp') - // if (chatWrapper) { - // chatWrapper.style.cssText = 'margin-top: -76px' - // } - // if (serp) { - // ipcRenderer.send('init-style') - // } - // } - // Compose page - /*const composeWrapper = document.getElementsByClassName( - 'uds_coauthor_wrapper' - )[0] - const composeMain = document.getElementsByClassName('sidebar')[0] - const insertBtn = document.getElementById('insert_button') - const previewText = document.getElementById('preview_text') - const previewOptions = document.getElementsByClassName('preview-options')[0] - if (composeWrapper) { - composeWrapper.style.cssText = 'margin-top: -64px' - } - if (composeMain) { - composeMain.style.cssText = 'height: calc(100% - 64px); margin-top: 64px' - } - if (insertBtn) { - insertBtn.style.cssText = 'display: none' - } - if (previewText) { - previewText.style.cssText = 'height: 100%' - } - if (previewOptions) { - previewOptions.style.cssText = 'bottom: 1px' - }*/ + // Chat area of main page + // const results = document.getElementById('b_results') + // if (results) { + // const chatWrapper = document.getElementsByClassName('uds_sydney_wrapper')[0] + // const serp = document.getElementsByTagName('cib-serp') + // if (chatWrapper) { + // chatWrapper.style.cssText = 'margin-top: -76px' + // } + // if (serp) { + // ipcRenderer.send('init-style') + // } + // } + // Compose page + /*const composeWrapper = document.getElementsByClassName( + 'uds_coauthor_wrapper' + )[0] + const composeMain = document.getElementsByClassName('sidebar')[0] + const insertBtn = document.getElementById('insert_button') + const previewText = document.getElementById('preview_text') + const previewOptions = document.getElementsByClassName('preview-options')[0] + if (composeWrapper) { + composeWrapper.style.cssText = 'margin-top: -64px' + } + if (composeMain) { + composeMain.style.cssText = 'height: calc(100% - 64px); margin-top: 64px' + } + if (insertBtn) { + insertBtn.style.cssText = 'display: none' + } + if (previewText) { + previewText.style.cssText = 'height: 100%' + } + if (previewOptions) { + previewOptions.style.cssText = 'bottom: 1px' + }*/ }) // New topic ipcRenderer.on('new-topic', () => { - try { - const newTopicBtn = document - .getElementsByTagName('cib-serp')[0] - .shadowRoot.getElementById('cib-action-bar-main') - .shadowRoot.querySelector('.button-compose') - if (newTopicBtn) { - newTopicBtn.click() + try { + const newTopicBtn = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-action-bar-main') + .shadowRoot.querySelector('.button-compose') + if (newTopicBtn) { + newTopicBtn.click() + } + } catch (err) { + console.log(err) } - } 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.querySelector('cib-text-input') - .shadowRoot.getElementById('searchbox') - if (textarea) { - textarea.focus() + try { + const textarea = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-action-bar-main') + .shadowRoot.querySelector('cib-text-input') + .shadowRoot.getElementById('searchbox') + if (textarea) { + textarea.focus() + } + } catch (err) { + console.log(err) } - } 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() + 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) } - } 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() + 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) } - } 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-welcome-container') - .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() + try { + const toneOptions = document + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-conversation-main') + .shadowRoot.querySelector('cib-welcome-container') + .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) } - } catch (err) { - console.log(err) - } }) // Set font size ipcRenderer.on('set-font-size', (event, size) => { - try { - const serp = document.querySelector('.cib-serp-main') - const conversationMain = serp.shadowRoot.getElementById( - 'cib-conversation-main' - ) - conversationMain.style.cssText = - serp.style.cssText += `--cib-type-body1-font-size: ${size}px; --cib-type-body1-strong-font-size: ${size}px; --cib-type-body2-font-size: ${size}px; --cib-type-body2-line-height: ${ - size + 6 - }px` - } catch (err) { - console.log(err) - } + try { + const serp = document.querySelector('.cib-serp-main') + const conversationMain = serp.shadowRoot.getElementById( + 'cib-conversation-main' + ) + conversationMain.style.cssText = + serp.style.cssText += `--cib-type-body1-font-size: ${size}px; --cib-type-body1-strong-font-size: ${size}px; --cib-type-body2-font-size: ${size}px; --cib-type-body2-line-height: ${ + size + 6 + }px` + } catch (err) { + console.log(err) + } }) // Set initial style ipcRenderer.on('set-initial-style', (event) => { - try { - const serp = document.querySelector('.cib-serp-main') - const conversationMain = serp.shadowRoot.getElementById( - 'cib-conversation-main' - ) - // Center element - const scroller = conversationMain.shadowRoot.querySelector('.scroller') - const actionBarMain = serp.shadowRoot.getElementById('cib-action-bar-main') - scroller.style.cssText += 'justify-content: center' - actionBarMain.style.cssText += 'max-width: unset' - } catch (err) { - console.log(err) - } + try { + const serp = document.querySelector('.cib-serp-main') + const conversationMain = serp.shadowRoot.getElementById( + 'cib-conversation-main' + ) + // Center element + const scroller = conversationMain.shadowRoot.querySelector('.scroller') + const actionBarMain = serp.shadowRoot.getElementById('cib-action-bar-main') + scroller.style.cssText += 'justify-content: center' + actionBarMain.style.cssText += 'max-width: unset' + } catch (err) { + console.log(err) + } }) // Replace compose page ipcRenderer.on('replace-compose-page', (event, isDarkMode) => { - try { - const composeModule = document.getElementById('underside-coauthor-module') - composeModule.innerHTML = `` - } catch (err) { - console.log(err) - } + try { + const composeModule = document.getElementById('underside-coauthor-module') + composeModule.innerHTML = `` + } catch (err) { + console.log(err) + } }) // Convert from conversation ipcRenderer.on('export', (event, format, isDarkMode) => { - try { - const chatMain = document - .getElementsByTagName('cib-serp')[0] - .shadowRoot.getElementById('cib-conversation-main') - .shadowRoot.getElementById('cib-chat-main') - html2canvas(chatMain, { - backgroundColor: isDarkMode ? '#2b2b2b' : '#f3f3f3', - logging: false, - useCORS: true, - allowTaint: true, - ignoreElements: (element) => { - if ( - element.tagName === 'CIB-WELCOME-CONTAINER' || - element.tagName === 'CIB-NOTIFICATION-CONTAINER' || - element.getAttribute('type') === 'host' - ) { - return true - } - if ( - format === 'md' && - (element.classList.contains('label') || - element.classList.contains('hidden') || - element.classList.contains('expand-button') || - element.getAttribute('type') === 'meta' || - element.tagName === 'CIB-TURN-COUNTER' || - element.tagName === 'BUTTON') - ) { - return true - } - }, - onclone: (doc) => { - const bodyWidth = doc.body.clientWidth - const paddingX = bodyWidth > 832 ? '32px' : '16px' - const paddingBottom = '48px' - const paddingTop = bodyWidth > 832 ? '24px' : '0px' - doc.getElementById( - 'cib-chat-main' - ).style.cssText = `padding: ${paddingTop} ${paddingX} ${paddingBottom} ${paddingX}` - // Markdown - if (format === 'md') { - markdownHandler(doc.getElementById('cib-chat-main')) - } - }, - }).then((canvas) => { - const pngDataURL = canvas.toDataURL('image/png') - if (format === 'png') { - // PNG - ipcRenderer.send('export-data', 'png', pngDataURL) - } else if (format === 'pdf') { - // PDF - pdfHandler(canvas, pngDataURL) - } - // Rerender the draggable area - const titleBar = document.getElementById('titleBar') - if (titleBar) { - titleBar.style.top === '1px' - ? (titleBar.style.top = '0px') - : (titleBar.style.top = '1px') - } - }) - } catch (err) { - console.log(err) - ipcRenderer.send('error', 'Unable to export conversation') - } + try { + const chatWindow = document.querySelector("#app > iframe.underside-iframe.active"); + let chatWindowDocument = chatWindow.contentDocument; + + const chatMain = chatWindowDocument + .getElementsByTagName('cib-serp')[0] + .shadowRoot.getElementById('cib-conversation-main') + .shadowRoot.getElementById('cib-chat-main') + html2canvas(chatMain, { + backgroundColor: isDarkMode ? '#2b2b2b' : '#f3f3f3', + logging: false, + useCORS: true, + allowTaint: true, + ignoreElements: (element) => { + if ( + element.tagName === 'CIB-WELCOME-CONTAINER' || + element.tagName === 'CIB-NOTIFICATION-CONTAINER' || + element.getAttribute('type') === 'host' + ) { + return true + } + if ( + format === 'md' && + (element.classList.contains('label') || + element.classList.contains('hidden') || + element.classList.contains('expand-button') || + element.getAttribute('type') === 'meta' || + element.tagName === 'CIB-TURN-COUNTER' || + element.tagName === 'BUTTON') + ) { + return true + } + }, + onclone: (doc) => { + const bodyWidth = doc.body.clientWidth + const paddingX = bodyWidth > 832 ? '32px' : '16px' + const paddingBottom = '48px' + const paddingTop = bodyWidth > 832 ? '24px' : '0px' + doc.getElementById( + 'cib-chat-main' + ).style.cssText = `padding: ${paddingTop} ${paddingX} ${paddingBottom} ${paddingX}` + // Markdown + if (format === 'md') { + markdownHandler(doc.getElementById('cib-chat-main')) + } + }, + }).then((canvas) => { + const pngDataURL = canvas.toDataURL('image/png') + if (format === 'png') { + // PNG + ipcRenderer.send('export-data', 'png', pngDataURL) + } else if (format === 'pdf') { + // PDF + pdfHandler(canvas, pngDataURL) + } + // Rerender the draggable area + const titleBar = chatWindowDocument.getElementById('titleBar') + if (titleBar) { + titleBar.style.top === '1px' + ? (titleBar.style.top = '0px') + : (titleBar.style.top = '1px') + } + }) + } catch (err) { + console.log(err) + ipcRenderer.send('error', 'Unable to export conversation') + } }) const pdfHandler = (canvas, pngDataURL) => { - const pdfWidth = canvas.width / window.devicePixelRatio - const pdfHeight = canvas.height / window.devicePixelRatio - const pdf = new jsPDF(pdfWidth > pdfHeight ? 'landscape' : 'portrait', 'pt', [ - pdfWidth, - pdfHeight, - ]) - pdf.addImage(pngDataURL, 'PNG', 0, 0, pdfWidth, pdfHeight, '', 'FAST') - const pdfDataURL = pdf.output('dataurlstring') - ipcRenderer.send('export-data', 'pdf', pdfDataURL) + const pdfWidth = canvas.width / window.devicePixelRatio + const pdfHeight = canvas.height / window.devicePixelRatio + const pdf = new jsPDF(pdfWidth > pdfHeight ? 'landscape' : 'portrait', 'pt', [ + pdfWidth, + pdfHeight, + ]) + pdf.addImage(pngDataURL, 'PNG', 0, 0, pdfWidth, pdfHeight, '', 'FAST') + const pdfDataURL = pdf.output('dataurlstring') + ipcRenderer.send('export-data', 'pdf', pdfDataURL) } const markdownHandler = (element) => { - const turndownService = new TurndownService({ - codeBlockStyle: 'fenced', - }) - turndownService.addRule('numberLink', { - filter: 'sup', - replacement: (content) => { - return `[${content}]` - }, - }) - turndownService.addRule('textLink', { - filter: (node) => { - return node.classList.contains('tooltip-target') - }, - replacement: (content) => { - return content - }, - }) - turndownService.addRule('learnMore', { - filter: (node) => { - return node.classList.contains('learn-more') - }, - replacement: (content, node) => { - return node.parentNode.querySelector('a[class="attribution-item"]') - ? content - : '' - }, - }) - turndownService.addRule('footerLink', { - filter: (node) => { - return node.classList.contains('attribution-item') - }, - replacement: (content, node) => { - return `[${content.replace(/^(\d+)(\\.)/, '[$1]')}](${node.getAttribute( - 'href' - )} "${node.getAttribute('title').replace(/\"/g, '')}")` - }, - }) - turndownService.addRule('userMessage', { - filter: (node) => { - return node.classList.contains('text-message-content') - }, - replacement: (content, node) => { - return `> **${node.firstElementChild.innerHTML}**${ - node.querySelector('img') - ? `\n> ![](${node.querySelector('img').getAttribute('src')})` - : '' - }` - }, - }) - turndownService.addRule('latex', { - filter: (node) => { - return node.classList.contains('katex-block') - }, - replacement: (content, node) => { - return `$$${node.querySelector('annotation').innerHTML.trim()}$$\n` - }, - }) - turndownService.addRule('inlineLatex', { - filter: (node) => { - return node.classList.contains('katex') - }, - replacement: (content, node) => { - return `$${node.querySelector('annotation').innerHTML.trim()}$` - }, - }) - const mdDataURL = Buffer.from( - turndownService.turndown(element), - 'utf-8' - ).toString('base64') - ipcRenderer.send('export-data', 'md', mdDataURL) + const turndownService = new TurndownService({ + codeBlockStyle: 'fenced', + }) + turndownService.addRule('numberLink', { + filter: 'sup', + replacement: (content) => { + return `[${content}]` + }, + }) + turndownService.addRule('textLink', { + filter: (node) => { + return node.classList.contains('tooltip-target') + }, + replacement: (content) => { + return content + }, + }) + turndownService.addRule('learnMore', { + filter: (node) => { + return node.classList.contains('learn-more') + }, + replacement: (content, node) => { + return node.parentNode.querySelector('a[class="attribution-item"]') + ? content + : '' + }, + }) + turndownService.addRule('footerLink', { + filter: (node) => { + return node.classList.contains('attribution-item') + }, + replacement: (content, node) => { + return `[${content.replace(/^(\d+)(\\.)/, '[$1]')}](${node.getAttribute( + 'href' + )} "${node.getAttribute('title').replace(/\"/g, '')}")` + }, + }) + turndownService.addRule('userMessage', { + filter: (node) => { + return node.classList.contains('text-message-content') + }, + replacement: (content, node) => { + return `> **${node.firstElementChild.innerHTML}**${ + node.querySelector('img') + ? `\n> ![](${node.querySelector('img').getAttribute('src')})` + : '' + }` + }, + }) + turndownService.addRule('latex', { + filter: (node) => { + return node.classList.contains('katex-block') + }, + replacement: (content, node) => { + return `$$${node.querySelector('annotation').innerHTML.trim()}$$\n` + }, + }) + turndownService.addRule('inlineLatex', { + filter: (node) => { + return node.classList.contains('katex') + }, + replacement: (content, node) => { + return `$${node.querySelector('annotation').innerHTML.trim()}$` + }, + }) + const mdDataURL = Buffer.from( + turndownService.turndown(element), + 'utf-8' + ).toString('base64') + ipcRenderer.send('export-data', 'md', mdDataURL) }// See the Electron documentation for details on how to use preload scripts: // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts -const electronHandler = { - ipcRenderer: { +// const electronHandler = { +// ipcRenderer: { +// getChatUrl() { +// const resp = ipcRenderer.sendSync("get-chat-url", "chat") +// return resp +// }, +// +// getComposeUrl() { +// const resp = ipcRenderer.sendSync("get-chat-url", "compose") +// return resp +// }, +// } +// } + +// contextBridge.exposeInMainWorld('electron', electronHandler); + +window.ipcRenderer = { getChatUrl() { - const resp = ipcRenderer.sendSync("get-chat-url", "chat") - return resp + const resp = ipcRenderer.sendSync("get-chat-url", "chat") + return resp }, getComposeUrl() { - const resp = ipcRenderer.sendSync("get-chat-url", "compose") - return resp + const resp = ipcRenderer.sendSync("get-chat-url", "compose") + return resp }, - } } - -contextBridge.exposeInMainWorld('electron', electronHandler); \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 4a9d2ec..e0a66c7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -10,7 +10,7 @@ let login = location.search.indexOf("login") >= 0 if (login) { router.push("/main") } else if (localStorage.getItem("nosplash") == "true") { - window.location.replace("https://www.bing.com/fd/auth/signin?action=interactive&provider=windows_live_id&return_url=https%3a%2f%2fwww.bing.com") + window.location.replace("https://www.bing.com/fd/auth/signin?action=interactive&provider=windows_live_id&return_url=https%3A%2F%2Fbing.com") } else { router.push("/splash") } diff --git a/src/pages/Main.vue b/src/pages/Main.vue index 9c757aa..d14dc38 100644 --- a/src/pages/Main.vue +++ b/src/pages/Main.vue @@ -1,8 +1,9 @@ @@ -16,11 +17,11 @@ let tab = ref("0") - - diff --git a/src/pages/Splash.vue b/src/pages/Splash.vue index 572f96c..4819cff 100644 --- a/src/pages/Splash.vue +++ b/src/pages/Splash.vue @@ -18,7 +18,7 @@ watch(nosplash, async (newSplash, oldSplash) => {

BingGPT

Powered By Copilot with Bing Chat

don't show this again

- +