mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-05-31 21:21:15 +08:00
add the ui for dedicate download progress of puppeteer; use JSONParse to parse the download progress; finish the logic to pass the progress to ui
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
"@electron-toolkit/preload": "^3.0.0",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@puppeteer/browsers": "^2.0.0",
|
||||
"JSONStream": "^1.3.5",
|
||||
"electron-updater": "^6.1.7",
|
||||
"element-plus": "^2.5.5",
|
||||
"normalize.css": "^8.0.1",
|
||||
|
||||
@@ -28,13 +28,23 @@ export const getExpectPuppeteerExecutablePath = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
const checkAndDownloadPuppeteer = async (options: {
|
||||
downloadProgressCallback?: (downloadedBytes: number, totalBytes: number) => void
|
||||
}) => {
|
||||
const puppeteerManager = await getPuppeteerManagerModule()
|
||||
export const checkPuppeteerExecutable = async () => {
|
||||
const executablePath = await getExpectPuppeteerExecutablePath()
|
||||
return fs.existsSync(executablePath)
|
||||
}
|
||||
|
||||
const checkAndDownloadPuppeteer = async (options: {
|
||||
downloadProgressCallback?: (downloadedBytes: number, totalBytes: number) => void,
|
||||
confirmContinuePromise?: Promise<void>
|
||||
} = {}) => {
|
||||
const puppeteerManager = await getPuppeteerManagerModule()
|
||||
let installedBrowser: InstalledBrowser
|
||||
if (!fs.existsSync(executablePath)) {
|
||||
if (!(await checkPuppeteerExecutable())) {
|
||||
try {
|
||||
await options.confirmContinuePromise
|
||||
} catch {
|
||||
throw new Error('USER_CANCEL_DOWNLOAD_PUPPETEER')
|
||||
}
|
||||
// maybe the exist installation is broken.
|
||||
await puppeteerManager.uninstall({
|
||||
cacheDir,
|
||||
|
||||
@@ -1,9 +1,29 @@
|
||||
import checkAndDownloadPuppeteer from './check-and-download-puppeteer'
|
||||
import * as net from 'net'
|
||||
|
||||
export const checkAndDownloadDependenciesForInit = async () => {
|
||||
let pipe: null | net.Socket = null
|
||||
try {
|
||||
pipe = new net.Socket({ fd: 3 })
|
||||
} catch {
|
||||
console.warn('pipe is not available')
|
||||
}
|
||||
|
||||
pipe?.write(
|
||||
JSON.stringify({
|
||||
type: 'NEED_WARMING_UP_DEPENDENCIES'
|
||||
}) + '\r\n'
|
||||
)
|
||||
|
||||
const browser = await checkAndDownloadPuppeteer({
|
||||
downloadProgressCallback(downloadedBytes: number, totalBytes: number) {
|
||||
console.log(`${downloadedBytes} / ${totalBytes}`)
|
||||
pipe?.write(
|
||||
JSON.stringify({
|
||||
type: 'PUPPETEER_DOWNLOAD_PROGRESS',
|
||||
totalBytes,
|
||||
downloadedBytes
|
||||
})
|
||||
) + '\r\n'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@ import { app } from 'electron'
|
||||
import { SyncHook, AsyncSeriesHook } from 'tapable'
|
||||
import { readConfigFile } from '@bossgeekgo/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||
import * as net from 'net'
|
||||
import {
|
||||
checkPuppeteerExecutable,
|
||||
getExpectPuppeteerExecutablePath
|
||||
} from './CHECK_AND_DOWNLOAD_DEPENDENCIES/check-and-download-puppeteer'
|
||||
import * as childProcess from 'node:child_process'
|
||||
import * as JSONStream from 'JSONStream'
|
||||
|
||||
const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json')
|
||||
|
||||
@@ -20,26 +26,69 @@ export const runAutoChat = async () => {
|
||||
pipe?.write(
|
||||
JSON.stringify({
|
||||
type: 'INITIALIZE_PUPPETEER'
|
||||
})
|
||||
}) + '\r\n'
|
||||
)
|
||||
try {
|
||||
await (await import('@bossgeekgo/geek-auto-start-chat-with-boss/index.mjs')).initPuppeteer()
|
||||
pipe?.write(
|
||||
JSON.stringify({
|
||||
type: 'PUPPETEER_INITIALIZE_SUCCESSFULLY'
|
||||
})
|
||||
}) + '\r\n'
|
||||
)
|
||||
} catch {
|
||||
console.error(new Error('PUPPETEER_MAY_NOT_INSTALLED'))
|
||||
pipe?.write(
|
||||
JSON.stringify({
|
||||
type: 'PUPPETEER_MAY_NOT_INSTALLED'
|
||||
})
|
||||
}) + '\r\n'
|
||||
)
|
||||
app.exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
const isPuppeteerExecutable = await checkPuppeteerExecutable()
|
||||
if (!isPuppeteerExecutable) {
|
||||
const subProcessEnv = {
|
||||
...process.env,
|
||||
MAIN_BOSSGEEKGO_UI_RUN_MODE: 'checkAndDownloadDependenciesForInit',
|
||||
PUPPETEER_EXECUTABLE_PATH: await getExpectPuppeteerExecutablePath()
|
||||
}
|
||||
const subProcessOfCheckAndDownloadDependencies = childProcess.spawn(
|
||||
process.argv[0],
|
||||
process.argv.slice(1),
|
||||
{
|
||||
env: subProcessEnv,
|
||||
stdio: [null, null, null, 'pipe']
|
||||
}
|
||||
)
|
||||
|
||||
await new Promise((resolve) => {
|
||||
subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on(
|
||||
'data',
|
||||
(raw) => {
|
||||
const data = raw
|
||||
switch (data.type) {
|
||||
case 'NEED_WARMING_UP_DEPENDENCIES': {
|
||||
pipe?.write(JSON.stringify(data) + '\r\n')
|
||||
break
|
||||
}
|
||||
case 'PUPPETEER_DOWNLOAD_PROGRESS': {
|
||||
pipe?.write(JSON.stringify(data) + '\r\n')
|
||||
break
|
||||
}
|
||||
case 'PUPPETEER_MAY_NOT_INSTALLED': {
|
||||
resolve(data)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const mainLoop = (await import('@bossgeekgo/geek-auto-start-chat-with-boss/index.mjs')).mainLoop
|
||||
const hooks = {
|
||||
puppeteerLaunched: new SyncHook(),
|
||||
@@ -55,7 +104,7 @@ export const runAutoChat = async () => {
|
||||
pipe?.write(
|
||||
JSON.stringify({
|
||||
type: 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED' //geek-auto-start-chat-with-boss-started
|
||||
})
|
||||
}) + '\r\n'
|
||||
)
|
||||
while (true) {
|
||||
try {
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '@bossgeekgo/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||
import { ChildProcess } from 'child_process'
|
||||
import { getExpectPuppeteerExecutablePath } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/check-and-download-puppeteer'
|
||||
import * as JSONStream from 'JSONStream'
|
||||
let mainWindow: BrowserWindow
|
||||
|
||||
export function createMainWindow(): void {
|
||||
@@ -103,14 +104,22 @@ export function createMainWindow(): void {
|
||||
})
|
||||
console.log(subProcessOfPuppeteer)
|
||||
return new Promise((resolve) => {
|
||||
subProcessOfPuppeteer!.stdio[3]!.on('data', (raw) => {
|
||||
const data = JSON.parse(raw.toString())
|
||||
subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', (raw) => {
|
||||
const data = raw
|
||||
switch (data.type) {
|
||||
case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED':
|
||||
case 'PUPPETEER_MAY_NOT_INSTALLED': {
|
||||
resolve(data)
|
||||
break
|
||||
}
|
||||
case 'NEED_WARMING_UP_DEPENDENCIES': {
|
||||
mainWindow.webContents.send('NEED_WARMING_UP_DEPENDENCIES', data)
|
||||
break
|
||||
}
|
||||
case 'PUPPETEER_DOWNLOAD_PROGRESS': {
|
||||
mainWindow.webContents.send('PUPPETEER_DOWNLOAD_PROGRESS', data)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
import { log } from 'console';
|
||||
|
||||
import { onUnmounted } from 'vue';
|
||||
<template>
|
||||
<el-dialog v-bind="$attrs" @open="percentage = 0">
|
||||
<el-progress :percentage="percentage" :format="(n) => `${n.toFixed(1)}%`" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onUnmounted } from 'vue'
|
||||
|
||||
const percentage = ref(0)
|
||||
const handleProgress = (ev, { downloadedBytes, totalBytes }) => {
|
||||
percentage.value = ((downloadedBytes / totalBytes) * 100)
|
||||
}
|
||||
electron.ipcRenderer.on('PUPPETEER_DOWNLOAD_PROGRESS', handleProgress)
|
||||
onUnmounted(
|
||||
() => electron.ipcRenderer.off('PUPPETEER_DOWNLOAD_PROGRESS', handleProgress)
|
||||
)
|
||||
</script>
|
||||
@@ -27,14 +27,16 @@
|
||||
<el-button type="primary" @click="handleSubmit"> I'm ready, geekgeekgo! </el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<dependencies-warming-up-dialog v-model="shouldShowDependenciesWarmingUpDialog" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { onUnmounted, ref } from 'vue'
|
||||
import JSON5 from 'json5'
|
||||
import { ElForm, ElMessage, ElMessageBox } from 'element-plus'
|
||||
import router from '../../router/index'
|
||||
import DependenciesWarmingUpDialog from '../../features/DependenciesWarmingUpDialog.vue'
|
||||
|
||||
const formContent = ref({
|
||||
bossZhipinCookies: '',
|
||||
@@ -99,7 +101,7 @@ const handleSubmit = async () => {
|
||||
electron.ipcRenderer.emit('open-project-homepage-on-github')
|
||||
})
|
||||
.catch(() => {})
|
||||
return
|
||||
return
|
||||
}
|
||||
}
|
||||
const handleSave = async () => {
|
||||
@@ -115,6 +117,16 @@ const handleExpectCompaniesInputBlur = (event) => {
|
||||
.filter(Boolean)
|
||||
.join(',')
|
||||
}
|
||||
|
||||
const shouldShowDependenciesWarmingUpDialog = ref(false)
|
||||
|
||||
const needWarmingUpDenpendenciesHandler = () => {
|
||||
shouldShowDependenciesWarmingUpDialog.value = true
|
||||
}
|
||||
electron.ipcRenderer.on('NEED_WARMING_UP_DEPENDENCIES', needWarmingUpDenpendenciesHandler)
|
||||
onUnmounted(
|
||||
() => electron.ipcRenderer.off('NEED_WARMING_UP_DEPENDENCIES', needWarmingUpDenpendenciesHandler)
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -64,6 +64,9 @@ importers:
|
||||
'@puppeteer/browsers':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
JSONStream:
|
||||
specifier: ^1.3.5
|
||||
version: 1.3.5
|
||||
electron-updater:
|
||||
specifier: ^6.1.7
|
||||
version: 6.1.7
|
||||
@@ -1490,6 +1493,14 @@ packages:
|
||||
engines: {node: '>=10.0.0'}
|
||||
dev: true
|
||||
|
||||
/JSONStream@1.3.5:
|
||||
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
jsonparse: 1.3.1
|
||||
through: 2.3.8
|
||||
dev: false
|
||||
|
||||
/acorn-jsx@5.3.2(acorn@8.11.3):
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
@@ -3177,6 +3188,11 @@ packages:
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
/jsonparse@1.3.1:
|
||||
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
|
||||
engines: {'0': node >= 0.2.0}
|
||||
dev: false
|
||||
|
||||
/keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user