diff --git a/packages/ui/src/common/constant.ts b/packages/ui/src/common/constant.ts index 1570f00..6e8d81e 100644 --- a/packages/ui/src/common/constant.ts +++ b/packages/ui/src/common/constant.ts @@ -1 +1,2 @@ export const SINGLE_ITEM_DEFAULT_SERVE_WEIGHT = 1 +export const EXPECT_CHROMIUM_BUILD_ID = '139.0.7258.154' diff --git a/packages/ui/src/main/features/config-with-browser-assistant.ts b/packages/ui/src/main/features/config-with-browser-assistant.ts new file mode 100644 index 0000000..8f6562e --- /dev/null +++ b/packages/ui/src/main/features/config-with-browser-assistant.ts @@ -0,0 +1,26 @@ +import { ipcMain } from 'electron' +import { + createBrowserAssistantWindow, + browserAssistantWindow +} from '../window/browserAssistantWindow' + +export async function configWithBrowserAssistant({ windowOption } = {}) { + return new Promise((resolve, reject) => { + createBrowserAssistantWindow({ ...windowOption }) + + let processDone = false + function handler() { + processDone = true + browserAssistantWindow.close() + } + ipcMain.once('browser-config-saved', handler) + browserAssistantWindow.once('closed', () => { + ipcMain.off('browser-config-saved', handler) + if (processDone) { + resolve(true) + } else { + reject(new Error('USER_CANCELLED_CONFIG_BROWSER')) + } + }) + }) +} diff --git a/packages/ui/src/main/features/login-with-cookie-assistant.ts b/packages/ui/src/main/features/login-with-cookie-assistant.ts index 9cdefdc..5f475ee 100644 --- a/packages/ui/src/main/features/login-with-cookie-assistant.ts +++ b/packages/ui/src/main/features/login-with-cookie-assistant.ts @@ -6,11 +6,13 @@ export async function loginWithCookieAssistant({ windowOption } = {}) { createCookieAssistantWindow({ ...windowOption }) let processDone = false - ipcMain.once('cookie-saved', function handler() { + function handler() { processDone = true cookieAssistantWindow.close() - }) + } + ipcMain.once('cookie-saved', handler) cookieAssistantWindow.once('closed', () => { + ipcMain.off('cookie-saved', handler) if (processDone) { resolve(true) } else { diff --git a/packages/ui/src/main/flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/browser-history.ts b/packages/ui/src/main/flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/browser-history.ts index 7408309..bc10165 100644 --- a/packages/ui/src/main/flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/browser-history.ts +++ b/packages/ui/src/main/flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/browser-history.ts @@ -40,13 +40,6 @@ export const getLastUsedAndAvailableBrowser = async (): Promise { const puppeteerManager = await import('@puppeteer/browsers') @@ -16,7 +17,6 @@ const getPuppeteerManagerModule = async () => { return puppeteerManager } -const EXPECT_CHROMIUM_BUILD_ID = '139.0.7258.154' const cacheDir = path.join(os.homedir(), '.geekgeekrun', 'cache') const getExpectCachedPuppeteerExecutable = async (): Promise => { @@ -97,29 +97,36 @@ export const checkAndDownloadPuppeteerExecutable = async ( return installedBrowser } -export const getAnyAvailablePuppeteerExecutable = async (): Promise => { - const lastUsedOne = await getLastUsedAndAvailableBrowser() - if (lastUsedOne) { - return lastUsedOne +export const getAnyAvailablePuppeteerExecutable = async ({ + ignoreCached = false, + noSave = false +}: { + ignoreCached?: boolean + noSave?: boolean +} = {}): Promise => { + if (!ignoreCached) { + const lastUsedOne = await getLastUsedAndAvailableBrowser() + if (lastUsedOne) { + return lastUsedOne + } + } + // find existed browser - the fallback one + if (await checkCachedPuppeteerExecutable()) { + const cachedOne = await getExpectCachedPuppeteerExecutable() + !noSave && (await saveLastUsedAndAvailableBrowserInfo(cachedOne)) + + return cachedOne } // find existed browser - the one maybe actively installed by user or ship with os like Edge on windows try { const existedOne = await findAndLocateUserInstalledChromiumExecutableSync() - await saveLastUsedAndAvailableBrowserInfo(existedOne) + !noSave && (await saveLastUsedAndAvailableBrowserInfo(existedOne)) // save its path return existedOne } catch (err) { console.error(err) console.log('no existed browser path found') } - // find existed browser - the fallback one - if (await checkCachedPuppeteerExecutable()) { - const cachedOne = await getExpectCachedPuppeteerExecutable() - await saveLastUsedAndAvailableBrowserInfo(cachedOne) - - return cachedOne - } - // if no one available, then return null and remove last used browser await removeLastUsedAndAvailableBrowserPath() return null diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts index 261da65..2044f43 100644 --- a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts @@ -53,6 +53,7 @@ import gtag from '../../../utils/gtag' import { daemonEE, sendToDaemon } from '../connect-to-daemon' import { runCommon } from '../../../features/run-common' import { loginWithCookieAssistant } from '../../../features/login-with-cookie-assistant' +import { configWithBrowserAssistant } from '../../../features/config-with-browser-assistant' export default function initIpc() { ipcMain.handle('fetch-config-file-content', async () => { @@ -246,64 +247,6 @@ export default function initIpc() { return { runRecordId } }) - ipcMain.handle('check-dependencies', async () => { - const [anyAvailablePuppeteerExecutable] = await Promise.all([ - getAnyAvailablePuppeteerExecutable() - ]) - return { - puppeteerExecutableAvailable: !!anyAvailablePuppeteerExecutable - } - }) - - let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null - ipcMain.handle('setup-dependencies', async () => { - if (subProcessOfCheckAndDownloadDependencies) { - return - } - subProcessOfCheckAndDownloadDependencies = childProcess.spawn( - process.argv[0], - [process.argv[1], `--mode=checkAndDownloadDependenciesForInit`], - { - stdio: [null, null, null, 'pipe', 'ipc'] - } - ) - return new Promise((resolve, reject) => { - subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on( - 'data', - (raw) => { - const data = raw - switch (data.type) { - case 'NEED_RESETUP_DEPENDENCIES': - case 'PUPPETEER_DOWNLOAD_PROGRESS': { - mainWindow?.webContents.send(data.type, data) - break - } - case 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR': { - console.error(data) - break - } - default: { - return - } - } - } - ) - subProcessOfCheckAndDownloadDependencies!.once('exit', (exitCode) => { - switch (exitCode) { - case 0: { - resolve(exitCode) - break - } - default: { - reject('PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR') - break - } - } - subProcessOfCheckAndDownloadDependencies = null - }) - }) - }) - ipcMain.handle('stop-geek-auto-start-chat-with-boss', async () => { mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopping') const p = new Promise((resolve) => { @@ -613,6 +556,15 @@ export default function initIpc() { } }) }) + ipcMain.handle('config-with-browser-assistant', async () => { + return await configWithBrowserAssistant({ + windowOption: { + parent: mainWindow!, + modal: true, + show: true + } + }) + }) ipcMain.handle('exit-app-immediately', () => { app.exit(0) diff --git a/packages/ui/src/main/utils/initPublicIpc.ts b/packages/ui/src/main/utils/initPublicIpc.ts index f27496d..af2c41e 100644 --- a/packages/ui/src/main/utils/initPublicIpc.ts +++ b/packages/ui/src/main/utils/initPublicIpc.ts @@ -1,4 +1,4 @@ -import { BrowserWindow, ipcMain, shell } from 'electron' +import { BrowserWindow, dialog, ipcMain, shell } from 'electron' import gtag from './gtag' import buildInfo from '../../common/build-info.json' import os from 'node:os' @@ -71,4 +71,18 @@ export default function initPublicIpc() { ensureStorageFileExist() return await writeStorageFile(payload.fileName, JSON.parse(payload.data)) }) + ipcMain.handle('get-os-platform', () => { + return os.platform() + }) + ipcMain.handle('choose-file', (ev, { fileChooserConfig }) => { + if (!fileChooserConfig) { + fileChooserConfig = {} + } + const win = BrowserWindow.fromWebContents(ev.sender) + if (!win) { + return dialog.showOpenDialog(fileChooserConfig) + } else { + return dialog.showOpenDialog(win, fileChooserConfig) + } + }) } diff --git a/packages/ui/src/main/window/browserAssistantWindow.ts b/packages/ui/src/main/window/browserAssistantWindow.ts new file mode 100644 index 0000000..ae89825 --- /dev/null +++ b/packages/ui/src/main/window/browserAssistantWindow.ts @@ -0,0 +1,149 @@ +import { ChildProcess } from 'child_process' +import { BrowserWindow, ipcMain } from 'electron' +import path from 'path' +import { getAnyAvailablePuppeteerExecutable } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable' +import * as childProcess from 'node:child_process' +import * as JSONStream from 'JSONStream' +import { + getLastUsedAndAvailableBrowser, + saveLastUsedAndAvailableBrowserInfo +} from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/browser-history' + +export let browserAssistantWindow: BrowserWindow | null = null + +const registerHandleWithWindow = ( + win: BrowserWindow, + ...args: Parameters +) => { + const [channel, handler] = args + ipcMain.handle(channel, handler) + win.once('closed', () => ipcMain.removeHandler(channel)) +} + +export function createBrowserAssistantWindow( + opt?: Electron.BrowserWindowConstructorOptions +): BrowserWindow { + // Create the browser window. + if (browserAssistantWindow) { + browserAssistantWindow!.close() + } + browserAssistantWindow = new BrowserWindow({ + width: 800, + minWidth: 800, + height: 400, + resizable: true, + show: false, + autoHideMenuBar: true, + webPreferences: { + preload: path.join(__dirname, '../preload/index.js'), + sandbox: false + }, + ...opt + }) + + browserAssistantWindow.on('ready-to-show', () => { + browserAssistantWindow!.show() + }) + + // HMR for renderer base on electron-vite cli. + // Load the remote URL for development or the local html file for production. + if (process.env.NODE_ENV === 'development' && process.env['ELECTRON_RENDERER_URL']) { + browserAssistantWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '#/browserAssistant') + } else { + browserAssistantWindow.loadURL( + 'file://' + path.join(__dirname, '../renderer/index.html') + '#/browserAssistant' + ) + } + + browserAssistantWindow!.once('closed', () => { + browserAssistantWindow = null + }) + + registerHandleWithWindow( + browserAssistantWindow, + 'get-any-available-puppeteer-executable', + async (_, { ignoreCached, noSave } = {}) => { + return await getAnyAvailablePuppeteerExecutable({ ignoreCached, noSave }) + } + ) + + registerHandleWithWindow( + browserAssistantWindow, + 'get-last-used-and-available-browser', + async () => { + return await getLastUsedAndAvailableBrowser() + } + ) + + registerHandleWithWindow( + browserAssistantWindow, + 'save-last-used-and-available-browser-info', + async (_, payload) => { + return await saveLastUsedAndAvailableBrowserInfo(payload) + } + ) + + let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null + registerHandleWithWindow(browserAssistantWindow, 'setup-dependencies', async () => { + if (subProcessOfCheckAndDownloadDependencies) { + return + } + subProcessOfCheckAndDownloadDependencies = childProcess.spawn( + process.argv[0], + [process.argv[1], `--mode=checkAndDownloadDependenciesForInit`], + { + stdio: [null, null, null, 'pipe', 'ipc'] + } + ) + return new Promise((resolve, reject) => { + subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on( + 'data', + (raw) => { + const data = raw + switch (data.type) { + case 'NEED_RESETUP_DEPENDENCIES': + case 'PUPPETEER_DOWNLOAD_PROGRESS': { + browserAssistantWindow?.webContents.send(data.type, data) + break + } + case 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR': { + console.error(data) + break + } + default: { + return + } + } + } + ) + subProcessOfCheckAndDownloadDependencies!.once('exit', (exitCode) => { + switch (exitCode) { + case 0: { + resolve(exitCode) + break + } + default: { + reject('PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR') + break + } + } + subProcessOfCheckAndDownloadDependencies = null + }) + }) + }) + + const killHandler = async () => { + try { + subProcessOfCheckAndDownloadDependencies?.kill() + } catch { + // + } finally { + subProcessOfCheckAndDownloadDependencies = null + } + } + browserAssistantWindow.once('closed', () => { + killHandler() + }) + + return browserAssistantWindow! +} diff --git a/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue b/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue index 422fe6c..edd25a2 100644 --- a/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue +++ b/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue @@ -27,25 +27,7 @@ const router = useRouter() onMounted(async () => { gtagRenderer('bootstrap_mounted') - // checkDependenciesResult.value = await electron.ipcRenderer.invoke('check-dependencies') - // downloadProcessWaitee.value = Promise.withResolvers() - - // if (Object.values(checkDependenciesResult.value).includes(false)) { - // gtagRenderer('dependencies_need_download') - // router.replace('/downloadingDependencies') - // } else { - // downloadProcessWaitee.value!.resolve() - // } - - // downloadProcessWaitee.value!.promise.then(async () => { - // const isCookieFileValid = await electron.ipcRenderer.invoke('check-boss-zhipin-cookie-file') - // if (!isCookieFileValid) { - // gtagRenderer('found_cookie_invalid_when_bootstrap') - // router.replace('/cookieAssistant') - // } else { await sleep(2000) router.replace('/main-layout') - // } - // }) }) diff --git a/packages/ui/src/renderer/src/page/BrowserAssistant/index.vue b/packages/ui/src/renderer/src/page/BrowserAssistant/index.vue index 1ab6a6b..d07399d 100644 --- a/packages/ui/src/renderer/src/page/BrowserAssistant/index.vue +++ b/packages/ui/src/renderer/src/page/BrowserAssistant/index.vue @@ -1,58 +1,200 @@ + + diff --git a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue index f497b0f..3402c8a 100644 --- a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue +++ b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss/index.vue @@ -10,16 +10,27 @@
- -
-
BOSS直聘 Cookie
- 编辑Cookie -
-
+
+ +
+
BOSS直聘 Cookie
+ 编辑Cookie +
+
+
+ +
+
浏览器
+ 编辑浏览器设置 +
+
+
-
+
摸鱼模式
-
+
- - 编辑Cookie - +
+ + 编辑Cookie + +
+ + 编辑浏览器设置 + +
@@ -538,6 +546,18 @@ const handleClickLaunchLogin = async () => { // } } +const handleClickBrowserSetting = async () => { + gtagRenderer('browser_setting_clicked') + try { + await electron.ipcRenderer.invoke('config-with-browser-assistant') + ElMessage({ + type: 'success', + message: '浏览器设置保存成功' + }) + } catch { + // + } +} const currentStamp = ref(new Date()) let timer = 0 diff --git a/packages/ui/src/renderer/src/page/MainLayout/index.vue b/packages/ui/src/renderer/src/page/MainLayout/index.vue index c9f4b31..2a7c84d 100644 --- a/packages/ui/src/renderer/src/page/MainLayout/index.vue +++ b/packages/ui/src/renderer/src/page/MainLayout/index.vue @@ -146,7 +146,6 @@