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:
bossgeekgo
2024-02-15 11:31:54 +08:00
parent 78118751b1
commit 15369014e9
8 changed files with 153 additions and 14 deletions

View File

@@ -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",

View File

@@ -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,

View File

@@ -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'
}
})

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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>

View File

@@ -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
View File

@@ -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: