From 20bef0c97f9fa924ccca6c8626e9417607e1915f Mon Sep 17 00:00:00 2001 From: geekgeekrun Date: Tue, 8 Oct 2024 09:54:21 +0800 Subject: [PATCH] use unified chrome instance to handle `open-site-with-boss-cookie` - for `handleLaunchBossSite` and `handleViewJobOnlineButtonClick` in ui --- .../src/main/flow/LAUNCH_BOSS_SITE/index.ts | 42 ++++++++- .../flow/OPEN_SETTING_WINDOW/ipc/index.ts | 93 ++++++++++++------- .../page/Configuration/StartChatRecord.vue | 9 +- .../renderer/src/page/Configuration/index.vue | 13 ++- 4 files changed, 112 insertions(+), 45 deletions(-) diff --git a/packages/ui/src/main/flow/LAUNCH_BOSS_SITE/index.ts b/packages/ui/src/main/flow/LAUNCH_BOSS_SITE/index.ts index 097ba38..cf41573 100644 --- a/packages/ui/src/main/flow/LAUNCH_BOSS_SITE/index.ts +++ b/packages/ui/src/main/flow/LAUNCH_BOSS_SITE/index.ts @@ -16,6 +16,8 @@ import path from 'node:path' import url from 'url' import packageJson from '@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension/package.json' assert { type: 'json' } import { Target } from 'puppeteer' +import { pipeWriteRegardlessError } from '../utils/pipe' +import * as JSONStream from 'JSONStream' const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) const isRunFromUi = Boolean(process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE) @@ -125,6 +127,35 @@ export async function launchBossSite() { const localStoragePageUrl = `https://www.zhipin.com/desktop/` await setDomainLocalStorage(browser, localStoragePageUrl, bossLocalStorage) + //#region pipe + let pipeForWrite: null | fs.WriteStream = null + let pipeForRead: null | fs.ReadStream = null + try { + pipeForWrite = fs.createWriteStream(null, { fd: 3 }) + } catch { + console.warn('pipeForWrite is not available') + } + try { + pipeForRead = fs.createReadStream(null, { fd: 3 }) + } catch { + console.warn('pipeForRead is not available') + } + pipeForRead?.pipe(JSONStream.parse())?.on('data', async function handler(data) { + if (data.type !== 'NEW_WINDOW') { + return + } + const page = await browser.newPage() + await page.goto(data.url) + }) + + pipeWriteRegardlessError( + pipeForWrite, + JSON.stringify({ + type: 'SUB_PROCESS_OF_OPEN_BOSS_SITE_READY' + }) + ) + //#endregion + browser.on('targetcreated', (target) => { attachRequestsListener(target) }) @@ -135,11 +166,16 @@ export async function launchBossSite() { } const cp = browser.process() cp.kill() + pipeWriteRegardlessError( + pipeForWrite, + JSON.stringify({ + type: 'SUB_PROCESS_OF_OPEN_BOSS_SITE_CAN_BE_KILLED' + }) + ) process.exit(0) }) - const newPage = await await browser.newPage() + const tempPage = await browser.newPage() await page.close() - page = newPage - await page.goto('https://www.zhipin.com/web/user/') + page = tempPage } 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 aab7cc8..b725427 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 @@ -24,6 +24,8 @@ import { getJobLibrary } from '../utils/db/index' import { PageReq } from '../../../../common/types/pagination' +import { pipeWriteRegardlessError } from '../../utils/pipe' +import { WriteStream } from 'node:fs' export default function initIpc() { ipcMain.on('open-external-link', (_, link) => { @@ -286,42 +288,65 @@ export default function initIpc() { return a }) - let subProcessOfOpenBossSite: ChildProcess | undefined - let subProcessOfOpenBossSiteLaunching = false - ipcMain.handle('open-boss-site', async () => { - if (subProcessOfOpenBossSiteLaunching) { - return - } - subProcessOfOpenBossSiteLaunching = true - const defer = Promise.withResolvers() - if (subProcessOfOpenBossSite) { - subProcessOfOpenBossSite.once('exit', defer.resolve) - subProcessOfOpenBossSite.once('error', console.error) - try { - process.kill(subProcessOfOpenBossSite.pid!) - await sleep(500) - process.kill(subProcessOfOpenBossSite.pid!, 'SIGKILL') - } catch { - defer.resolve(undefined) + let subProcessOfOpenBossSiteDefer: null | PromiseWithResolvers = null + let subProcessOfOpenBossSite: null | ChildProcess = null + ipcMain.handle('open-site-with-boss-cookie', async (_, data) => { + const url = data.url + if ( + !subProcessOfOpenBossSiteDefer || + !subProcessOfOpenBossSite || + subProcessOfOpenBossSite.killed + ) { + subProcessOfOpenBossSiteDefer = Promise.withResolvers() + const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable() + const subProcessEnv = { + ...process.env, + MAIN_BOSSGEEKGO_UI_RUN_MODE: 'launchBossSite', + PUPPETEER_EXECUTABLE_PATH: puppeteerExecutable!.executablePath } - } else { - defer.resolve(undefined) + subProcessOfOpenBossSite = childProcess.spawn(process.argv[0], process.argv.slice(1), { + env: subProcessEnv, + stdio: [null, null, null, 'pipe'] + }) + subProcessOfOpenBossSite.once('exit', () => { + subProcessOfOpenBossSiteDefer = null + }) + subProcessOfOpenBossSite.stdio[3]!.pipe(JSONStream.parse()).on( + 'data', + async function handler(data) { + switch (data?.type) { + case 'SUB_PROCESS_OF_OPEN_BOSS_SITE_READY': { + subProcessOfOpenBossSiteDefer!.resolve(subProcessOfOpenBossSite as ChildProcess) + break + } + case 'SUB_PROCESS_OF_OPEN_BOSS_SITE_CAN_BE_KILLED': { + try { + subProcessOfOpenBossSite && + !subProcessOfOpenBossSite.killed && + subProcessOfOpenBossSite.pid && + process.kill(subProcessOfOpenBossSite.pid) + } catch { + // + } finally { + subProcessOfOpenBossSiteDefer = null + subProcessOfOpenBossSite = null + } + break + } + } + } + ) } - defer.promise.then(() => { - subProcessOfOpenBossSite = undefined - }) - await defer.promise - const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable() - const subProcessEnv = { - ...process.env, - MAIN_BOSSGEEKGO_UI_RUN_MODE: 'launchBossSite', - PUPPETEER_EXECUTABLE_PATH: puppeteerExecutable!.executablePath - } - subProcessOfOpenBossSite = childProcess.spawn(process.argv[0], process.argv.slice(1), { - env: subProcessEnv, - stdio: [null, null, null] - }) - subProcessOfOpenBossSiteLaunching = false + + await subProcessOfOpenBossSiteDefer.promise + + pipeWriteRegardlessError( + subProcessOfOpenBossSite!.stdio[3]! as WriteStream, + JSON.stringify({ + type: 'NEW_WINDOW', + url: url ?? 'about:blank' + }) + ) }) ipcMain.handle('exit-app-immediately', () => { diff --git a/packages/ui/src/renderer/src/page/Configuration/StartChatRecord.vue b/packages/ui/src/renderer/src/page/Configuration/StartChatRecord.vue index 090dbf8..fe292e2 100644 --- a/packages/ui/src/renderer/src/page/Configuration/StartChatRecord.vue +++ b/packages/ui/src/renderer/src/page/Configuration/StartChatRecord.vue @@ -137,11 +137,10 @@ onMounted(() => { }) }) -function handleViewJobOnlineButtonClick(encryptJobId: string) { - electron.ipcRenderer.send( - 'open-external-link', - `https://www.zhipin.com/job_detail/${encryptJobId}.html` - ) +async function handleViewJobOnlineButtonClick(encryptJobId: string) { + return await electron.ipcRenderer.invoke('open-site-with-boss-cookie', { + url: `https://www.zhipin.com/job_detail/${encryptJobId}.html` + }) } const drawVisibleModelValue = ref(false) diff --git a/packages/ui/src/renderer/src/page/Configuration/index.vue b/packages/ui/src/renderer/src/page/Configuration/index.vue index 21141be..82feec0 100644 --- a/packages/ui/src/renderer/src/page/Configuration/index.vue +++ b/packages/ui/src/renderer/src/page/Configuration/index.vue @@ -36,6 +36,7 @@ import { useRouter } from 'vue-router' import { ElIcon } from 'element-plus' import { TopRight } from '@element-plus/icons-vue' import useBuildInfo from '@renderer/hooks/useBuildInfo' +import { debounce } from 'lodash-es' const router = useRouter() const unmountedCbs: Array> = [] onUnmounted(() => { @@ -94,9 +95,15 @@ const handleGotoProjectPageClick = () => { electron.ipcRenderer.send('open-external-link', 'https://github.com/geekgeekrun/geekgeekrun') } -const handleLaunchBossSite = async () => { - await electron.ipcRenderer.invoke('open-boss-site') -} +const handleLaunchBossSite = debounce( + async () => { + return await electron.ipcRenderer.invoke('open-site-with-boss-cookie', { + url: `https://www.zhipin.com/` + }) + }, + 1000, + { leading: true, trailing: false } +)