diff --git a/assets/TrayTemplate.png b/assets/TrayTemplate.png new file mode 100644 index 0000000..0841ae5 Binary files /dev/null and b/assets/TrayTemplate.png differ diff --git a/assets/TrayTemplate@2x.png b/assets/TrayTemplate@2x.png new file mode 100644 index 0000000..98df4a8 Binary files /dev/null and b/assets/TrayTemplate@2x.png differ diff --git a/assets/icons/TrayTemplate.png b/assets/icons/TrayTemplate.png new file mode 100644 index 0000000..0841ae5 Binary files /dev/null and b/assets/icons/TrayTemplate.png differ diff --git a/assets/icons/TrayTemplate@2x.png b/assets/icons/TrayTemplate@2x.png new file mode 100644 index 0000000..98df4a8 Binary files /dev/null and b/assets/icons/TrayTemplate@2x.png differ diff --git a/package-lock.json b/package-lock.json index 7fb2092..bc02af9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { + "@ant-design/icons": "^5.1.4", "@mozilla/readability": "^0.4.4", "antd": "^5.3.2", "axios": "^1.4.0", @@ -142,15 +143,15 @@ } }, "node_modules/@ant-design/icons": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.1.0.tgz", - "integrity": "sha512-s7NJeBY2NS44+sAhpgaxtgvBda81vpVxLPXXdCWNXwIVR8T7DdhDsSZqqVMPlZwCKwRo89ksWhFifZo0Ulgxdw==", + "version": "5.1.4", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.1.4.tgz", + "integrity": "sha512-YHKL7Jx3bM12OxvtiYDon04BsBT/6LGitYEqar3GljzWaAyMOAD8i/uF1Rsi5Us/YNdWWXBGSvZV2OZWMpJlcA==", "dependencies": { "@ant-design/colors": "^7.0.0", "@ant-design/icons-svg": "^4.2.1", "@babel/runtime": "^7.11.2", "classnames": "^2.2.6", - "rc-util": "^5.9.4" + "rc-util": "^5.31.1" }, "engines": { "node": ">=8" @@ -14895,9 +14896,9 @@ } }, "node_modules/rc-util": { - "version": "5.30.0", - "resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.30.0.tgz", - "integrity": "sha512-uaWpF/CZGyXuhQG71MWxkU+0bWkPEgqZUxEv251Cu7p3kpHDNm5+Ygu/U8ux0a/zbfGW8PsKcJL0XVBOMrlIZg==", + "version": "5.32.3", + "resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.32.3.tgz", + "integrity": "sha512-+Pv1nOiTtmp6kpz8yZ/DToMrZHz4DIUi1/EhpIsGQhhF12jANx3rb+gsp0YUWWtxUDf6U1Eyhe0EN+mBlCJXoA==", "dependencies": { "@babel/runtime": "^7.18.3", "react-is": "^16.12.0" diff --git a/package.json b/package.json index 7c36d23..67993c6 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ } }, "dependencies": { + "@ant-design/icons": "^5.1.4", "@mozilla/readability": "^0.4.4", "antd": "^5.3.2", "axios": "^1.4.0", diff --git a/release/app/package-lock.json b/release/app/package-lock.json index 9e2f880..7ff364a 100644 --- a/release/app/package-lock.json +++ b/release/app/package-lock.json @@ -1,11 +1,11 @@ { - "name": "electron-react-boilerplate", + "name": "Earth", "version": "1.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "electron-react-boilerplate", + "name": "Earth", "version": "1.0.1", "hasInstallScript": true, "license": "MIT", diff --git a/src/main/libs/ipc.js b/src/main/libs/ipc.js index 7abc868..4e87dea 100644 --- a/src/main/libs/ipc.js +++ b/src/main/libs/ipc.js @@ -2,6 +2,7 @@ import { ipcMain, app, BrowserWindow, shell, dialog } from 'electron'; import _ from 'lodash'; import axios from 'axios'; import fs from 'fs'; + function delay(ms) { return new Promise((resolve, reject) => { setTimeout(() => { @@ -12,8 +13,15 @@ function delay(ms) { const processHandler = { async dbt_close_app() { - app.quit(); - process.exit(0); + let mainWin = BrowserWindow.fromId(global.mainWindowId); + if (!mainWin) { + return; + } + + mainWin.hide(); + + // app.quit(); + // process.exit(0); }, bing_login() { return new Promise((resolve, reject) => { @@ -104,6 +112,57 @@ const processHandler = { evt.reply('importComboBack', { data: json }); }, + dbt_pop_search(evt, data) { + let mainWin = BrowserWindow.fromId(global.mainWindowId); + if (!mainWin) { + return; + } + + mainWin.show(); + mainWin.focus(); + mainWin.webContents.send('dbt_pop_search', data); + }, + dbt_pop_typechange(evt, data) { + let mainWin = BrowserWindow.fromId(global.mainWindowId); + if (!mainWin) { + return; + } + + // mainWin.show(); + // mainWin.focus(); + mainWin.webContents.send('dbt_pop_typechange', data); + }, + dbt_main_typechange(evt, data) { + let popWin = BrowserWindow.fromId(global.popWindowId); + if (!popWin) { + return; + } + + // mainWin.show(); + // mainWin.focus(); + popWin.webContents.send('dbt_main_typechange', data); + }, + dbt_pop_close(evt, data) { + let popWin = BrowserWindow.fromId(global.popWindowId); + if (!popWin) { + return; + } + + popWin.hide(); + }, + click_through(evt, data) { + let flag = data?.flag || false; + let popWin = BrowserWindow.fromId(global.popWindowId); + if (!popWin) { + return; + } + + if (flag) { + popWin.setIgnoreMouseEvents(true, { forward: true }); + } else { + popWin.setIgnoreMouseEvents(false); + } + }, }; export default function ipc() { diff --git a/src/main/libs/popWindow.js b/src/main/libs/popWindow.js new file mode 100644 index 0000000..70f7174 --- /dev/null +++ b/src/main/libs/popWindow.js @@ -0,0 +1,6 @@ +import path from 'path'; +import { app, BrowserWindow, shell, ipcMain } from 'electron'; + + + +export default createWindow; diff --git a/src/main/main.ts b/src/main/main.ts index a03e977..3f263f8 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -9,8 +9,19 @@ * `./src/main.js` using webpack. This gives us some performance wins. */ import path from 'path'; -import { app, BrowserWindow, shell, ipcMain } from 'electron'; +import { + app, + BrowserWindow, + shell, + ipcMain, + screen, + Tray, + Menu, + globalShortcut, + nativeImage, +} from 'electron'; import { autoUpdater } from 'electron-updater'; +import { checkAccessibilityPermissions } from 'node-selection'; import watchSelection from './watchSelection'; import log from 'electron-log'; import MenuBuilder from './menu'; @@ -19,7 +30,7 @@ import ipc from './libs/ipc'; let mouseDownPos = { x: 0, y: 0 }; // 记录鼠标按下的坐标 let isMouseDown = false; -let tray = null; +let tray: any = null; class AppUpdater { constructor() { @@ -30,6 +41,7 @@ class AppUpdater { } let mainWindow: BrowserWindow | null = null; +let popWindow: BrowserWindow | null = null; ipcMain.on('ipc-example', async (event, arg) => { const msgTemplate = (pingPong: string) => `IPC test: ${pingPong}`; @@ -47,7 +59,7 @@ const isDebug = process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true'; if (isDebug) { - require('electron-debug')(); + // require('electron-debug')(); } const installExtensions = async () => { @@ -63,18 +75,67 @@ const installExtensions = async () => { .catch(console.log); }; -const createWindow = async () => { +const RESOURCES_PATH = app.isPackaged + ? path.join(process.cwd(), '/resources/assets') // ? path.join(process.resourcesPath, 'assets') + : path.join(process.cwd(), '/assets'); //path.join(__dirname, '../../assets'); + +const getAssetPath = (...paths: string[]): string => { + return path.join(RESOURCES_PATH, ...paths); +}; + +const createPopWindow = async () => { + if (!(await checkAccessibilityPermissions({ prompt: true }))) { + console.log('grant accessibility permissions and restart this program'); + } + + if (!popWindow) { + let xw = screen.getPrimaryDisplay().workAreaSize.width; + + popWindow = new BrowserWindow({ + width: xw * 0.35, + height: 200, + y: 5, + icon: getAssetPath('icon.png'), + show: false, + transparent: true, + alwaysOnTop: true, + skipTaskbar: true, + resizable: false, + frame: false, + movable: true, + + webPreferences: { + preload: app.isPackaged + ? path.join(__dirname, 'preload.js') + : path.join(__dirname, '../../.erb/dll/preload.js'), + }, + }); + + global.popWindowId = popWindow.id; + popWindow.setPosition(xw * 0.325, 10); + } + if (isDebug) { - // await installExtensions(); + // popWindow.webContents.openDevTools(); + popWindow.loadURL(resolveHtmlPath('index.html', { hash: '/pop' })); + } else { + popWindow.loadFile(resolveHtmlPath('index.html', null), { hash: '/pop' }); } + popWindow.show(); - const RESOURCES_PATH = app.isPackaged - ? path.join(process.resourcesPath, 'assets') - : path.join(__dirname, '../../assets'); + // popWindow.webContents.on('did-finish-load', () => { + // console.log('did-finish-load'); + // }); - const getAssetPath = (...paths: string[]): string => { - return path.join(RESOURCES_PATH, ...paths); - }; + // popWindow.on('closed', () => { + // popWindow = null; + // }); +}; + +const createWindow = async () => { + if (isDebug) { + // await installExtensions(); + } mainWindow = new BrowserWindow({ show: false, @@ -89,7 +150,54 @@ const createWindow = async () => { }, }); - mainWindow.loadURL(resolveHtmlPath('index.html')); + global.mainWindowId = mainWindow.id; + + if (isDebug) { + mainWindow.webContents.openDevTools(); + mainWindow.loadURL(resolveHtmlPath('index.html', null)); + } else { + mainWindow.loadFile(resolveHtmlPath('index.html', null)); + } + + if (!tray) { + let icon = nativeImage.createFromDataURL( + 'data:image/png;base64,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' + ); + tray = new Tray(icon); + const contextMenu = Menu.buildFromTemplate([ + { + label: '打开搜索栏', + type: 'normal', + click: () => { + let popWin = BrowserWindow.fromId(global.popWindowId); + if (popWin) { + popWin.show(); + } + }, + }, + { + label: '退出', + type: 'normal', + click: () => { + if (app) { + app.quit(); + process.exit(0); + } + }, + }, + ]); + + tray.setContextMenu(contextMenu); + + tray.setToolTip('Earth'); + + tray.on('click', () => { + let xWindow = BrowserWindow.fromId(global.mainWindowId); + if (xWindow) { + xWindow.isVisible() ? xWindow.hide() : xWindow.show(); + } + }); + } mainWindow.on('ready-to-show', () => { if (!mainWindow) { @@ -100,12 +208,13 @@ const createWindow = async () => { } else { mainWindow.show(); } + + createPopWindow(); }); mainWindow.webContents.on('did-finish-load', () => { console.log('did-finish-load'); - watchSelection(mainWindow) - + watchSelection(mainWindow); }); mainWindow.on('closed', () => { @@ -130,8 +239,7 @@ const createWindow = async () => { * Add event listeners... */ -app.on('before-quit', () => { -}); +app.on('before-quit', () => {}); app.on('window-all-closed', () => { // Respect the OSX convention of having the application in memory even @@ -144,6 +252,19 @@ app.on('window-all-closed', () => { app .whenReady() .then(() => { + globalShortcut.register('Ctrl+Shift+M', () => { + let xWindow = BrowserWindow.fromId(global.mainWindowId); + if (xWindow) { + xWindow.isVisible() ? xWindow.hide() : xWindow.show(); + } + }); + + globalShortcut.register('Ctrl+Shift+F', () => { + let popWin = BrowserWindow.fromId(global.popWindowId); + if (popWin) { + popWin.isVisible() ? popWin.hide() : popWin.show(); + } + }); createWindow(); app.on('activate', () => { // On macOS it's common to re-create a window in the app when the diff --git a/src/main/util.ts b/src/main/util.ts index 7775eda..bd8a83b 100644 --- a/src/main/util.ts +++ b/src/main/util.ts @@ -2,12 +2,15 @@ import { URL } from 'url'; import path from 'path'; -export function resolveHtmlPath(htmlFileName: string) { +export function resolveHtmlPath(htmlFileName: string, opts: any) { if (process.env.NODE_ENV === 'development') { const port = process.env.PORT || 1212; const url = new URL(`http://localhost:${port}`); url.pathname = htmlFileName; + if (opts?.hash) { + url.hash = opts.hash; + } return url.href; } - return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`; + return path.resolve(__dirname, '../renderer/', htmlFileName); } diff --git a/src/main/watchSelection.js b/src/main/watchSelection.js index 9d9e199..65a5db5 100644 --- a/src/main/watchSelection.js +++ b/src/main/watchSelection.js @@ -9,16 +9,14 @@ function delay(ms) { } async function wa(modalWindow) { - if (await checkAccessibilityPermissions({ prompt: true })) { - let res = await getSelection().catch((e) => e); - // 如果当前主窗口是显示的 则往住窗口发数据 否则显示menu弹窗 - if (res?.text) { - const { text } = res; - modalWindow.webContents.send('win_selection_txt', { - text, - code: 200, - }); - } + let res = await getSelection().catch((e) => e); + // 如果当前主窗口是显示的 则往住窗口发数据 否则显示menu弹窗 + if (res?.text) { + const { text } = res; + modalWindow.webContents.send('win_selection_txt', { + text, + code: 200, + }); } await delay(500); diff --git a/src/renderer/App.jsx b/src/renderer/App.jsx index 6d409b1..607530a 100644 --- a/src/renderer/App.jsx +++ b/src/renderer/App.jsx @@ -1,8 +1,9 @@ import React, { useEffect } from 'react'; -import { MemoryRouter as Router, Routes, Route } from 'react-router-dom'; +import { HashRouter as Router, Routes, Route } from 'react-router-dom'; import { getConfigFromUrl } from '@/components/Utils'; import Main from './pages/content/Main'; +import PopWindow from './pages/popWindow'; import backgroundHandle from './pages/background'; import './App.css'; @@ -22,6 +23,7 @@ export default function App() { return ( + } /> { + if (!data?.text) { + return; + } + + this.setState( + { + userInput: { + prompt: data?.text, + tag: data?.text, + }, + }, + () => { + this._sendBtnClick(); + } + ); + }; + handleSelection(data: any) { const text = data?.text || ''; this.setState({ - placeholder: - text.length > 0 ? text.trim() : 'Ask or search anything', + placeholder: text.length > 0 ? text.trim() : 'Ask or search anything', userSelected: text.length > 0, }); } @@ -177,6 +203,8 @@ class ChatBotInput extends React.Component { }, combo: -1, }; + + console.log('userInputuserInputuserInput', userInput, combo); this.props.callback({ cmd: 'send-talk', data: { diff --git a/src/renderer/components/chatbot/ChatBotSelect.tsx b/src/renderer/components/chatbot/ChatBotSelect.tsx index 5d06cfa..8c2a210 100644 --- a/src/renderer/components/chatbot/ChatBotSelect.tsx +++ b/src/renderer/components/chatbot/ChatBotSelect.tsx @@ -112,7 +112,10 @@ class ChatBotSelect extends React.Component { } componentDidMount() { - console.log('ChatBotSelect componentDidMount'); + this.popFn = window.electron.ipcRenderer.on( + 'dbt_pop_typechange', + this.handleTypeChange + ); } componentDidUpdate(prevProps: { isLoading: boolean }, prevState: any) { @@ -123,12 +126,21 @@ class ChatBotSelect extends React.Component { } } - componentWillUnmount() {} + componentWillUnmount() { + if (this.popFn) { + this.popFn(); + } + } + + handleTypeChange = (data) => { + this._onChange(data.type); + }; _onChange(type: string) { this.setState({ type, }); + window.electron.ipcRenderer.send('dbt_main_typechange', { type }); const { label, value } = this._updateStyle(type); diff --git a/src/renderer/pages/content/Main.tsx b/src/renderer/pages/content/Main.tsx index 664bc53..54c5048 100644 --- a/src/renderer/pages/content/Main.tsx +++ b/src/renderer/pages/content/Main.tsx @@ -315,6 +315,7 @@ class Main extends React.Component< this.initChatBot(); } } + getNotionPrompts = (data, x) => { let xData = comboParse(data.results) || []; comboDataUpdate(xData); @@ -1346,6 +1347,7 @@ class Main extends React.Component< return ( img { + flex-grow: 0; + flex-shrink: 0; + margin-right: 4px; + } +} +.dbt_drop { + pointer-events: auto; +} + +.dbt_drop .ant-dropdown-menu-item:focus { + border: none !important; + outline: none !important; + box-shadow: none !important; +} + +.dbt_drop .ant-dropdown-menu-item:active { + border: none; + outline: none; + box-shadow: none; +} + +.dbt_drop .ant-dropdown-menu-item:hover { + border: none; + box-shadow: none; + outline: none; +} + +.send-img { + -webkit-app-region: no-drag; + background: none; + + color: #333; + flex-grow: 0; + flex-shrink: 0; + font-size: 24px; + width: 24px; + cursor: pointer; +} + +.btn-send { + -webkit-app-region: no-drag; + background: none; + + color: #333; + flex-grow: 0; + flex-shrink: 0; + font-size: 24px; + cursor: pointer; +} + +.popPage .btn-send:focus { + border: none !important; + outline: none !important; + box-shadow: none !important; +} + +.popPage .btn-send:active { + border: none; + outline: none; + box-shadow: none; +} + +.popPage .btn-send:hover { + border: none; + box-shadow: none; + outline: none; +} + +.btn-more { + margin-left: 10px; + color: #999; +} +.close-img { + margin-right: 5px; +} diff --git a/src/renderer/pages/popWindow/index.js b/src/renderer/pages/popWindow/index.js new file mode 100644 index 0000000..755640b --- /dev/null +++ b/src/renderer/pages/popWindow/index.js @@ -0,0 +1,200 @@ +import React, { useState, useEffect } from 'react'; +import { Input, Dropdown, Space } from 'antd'; +import { + DownOutlined, + RightCircleOutlined, + MoreOutlined, + CloseCircleOutlined, +} from '@ant-design/icons'; +import './index.css'; + +import bingSvg from '@/assets/bing.svg'; +import chatgptPng from '@/assets/chatgpt.png'; +import chromePng from '@/assets/g-logo.png'; +import baiduLogo from '@/assets/baidu.jpg'; +import logoicon from '@/assets/logo.png'; + +export default function PopWindow() { + const [keyword, setKeyword] = useState(''); + const [isFocus, setFocus] = useState(''); + const [isMoving, setMoving] = useState(false); + const [selectedId, setSelectedId] = useState('ChatGPT'); + + useEffect(() => { + // 与主窗口同步数据 + window.electron.ipcRenderer.send('dbt_pop_typechange', { + type: selectedId, + }); + let fn = window.electron.ipcRenderer.on('dbt_main_typechange', (evt) => { + if (evt?.type) { + setSelectedId(evt?.type); + } + }); + + function handleMove(event) { + let flag = event.target === document.documentElement; + window.electron.ipcRenderer.send('click_through', { flag }); + } + + window.addEventListener('mousedown', () => { + setMoving(true); + }); + window.addEventListener('mousemove', handleMove); + window.addEventListener('mouseup', () => { + setMoving(false); + }); + return () => { + if (fn) { + fn(); + } + window.removeEventListener('mousemove', handleMove); + window.removeEventListener('mousemove', handleMove); + }; + }, []); + + let imgMap = { + Bing: bingSvg, + Google: chromePng, + Baidu: baiduLogo, + ChatGPT: chatgptPng, + }; + const items = [ + { + label: ( +
+  + ChatGPT +
+ ), + key: 'ChatGPT', + }, + { + label: ( +
+  Bing +
+ ), + key: 'Bing', + }, + { + label: ( +
+  + Google +
+ ), + key: 'Google', + }, + { + label: ( +
+  + Baidu +
+ ), + key: 'Baidu', + }, + ]; + + const menus = [ + { + label:
快捷键:CTRL+SHIFT+F
, + key: 'shortcut', + }, + { + label: ( +
+ + 关闭搜索栏 +
+ ), + key: 'close', + }, + ]; + + const handleChange = (evt) => { + setKeyword(evt.target.value); + }; + + const handleSend = (e) => { + if (!keyword || !keyword.trim()) { + return; + } + if (selectedId === 'Baidu') { + let url = `https://www.baidu.com/s?wd=${keyword}`; + window.electron.ipcRenderer.send('open_url', { + url, + }); + } else if (selectedId === 'Google') { + let url = `https://www.google.com/search?q=${keyword}`; + window.electron.ipcRenderer.send('open_url', { + url, + }); + } else { + window.electron.ipcRenderer.send('dbt_pop_search', { + text: keyword, + type: selectedId, + }); + } + + setKeyword(''); + }; + + const handleItemClick = (evt) => { + setSelectedId(evt.key); + if (['Baidu', 'Google'].indexOf(evt.key) >= 0) { + return; + } + window.electron.ipcRenderer.send('dbt_pop_typechange', { + type: evt.key, + }); + }; + + const handleMenuClick = (evt) => { + if (evt.key !== 'close') { + return; + } + setTimeout(() => { + window.electron.ipcRenderer.send('dbt_pop_close'); + }, 350); + }; + + return ( +
+
+ +
+ + +
+
+
+ setFocus(true)} + onBlur={() => setFocus(false)} + onPressEnter={handleSend} + placeholder={`Search by ${selectedId}`} + /> + + + + + +
+ ); +}