make DependenciesSetupProgressIndicatorDialog support execute more than 1 tasks (pervious support download puppeteer only)

This commit is contained in:
bossgeekgo
2024-02-20 01:35:17 +08:00
parent 001a903259
commit 831dbadc74
6 changed files with 89 additions and 42 deletions

View File

@@ -12,10 +12,8 @@ const cacheDir = path.join(
)
const getPuppeteerManagerModule = async () => {
const runtimeDependencies = await import(
path.join(os.homedir(), '.bossgeekgo', 'external-node-runtime-dependencies/index.mjs')
)
return runtimeDependencies.puppeteerManager
const puppeteerManager = await import('@puppeteer/browsers')
return puppeteerManager
}
export const getExpectPuppeteerExecutablePath = async () => {
@@ -29,14 +27,21 @@ export const getExpectPuppeteerExecutablePath = async () => {
}
export const checkPuppeteerExecutable = async () => {
const executablePath = await getExpectPuppeteerExecutablePath()
return fs.existsSync(executablePath)
try {
const executablePath = await getExpectPuppeteerExecutablePath()
return fs.existsSync(executablePath)
} catch {
// should limit [ERR_MODULE_NOT_FOUND]
return false
}
}
const checkAndDownloadPuppeteer = async (options: {
downloadProgressCallback?: (downloadedBytes: number, totalBytes: number) => void,
confirmContinuePromise?: Promise<void>
} = {}) => {
const checkAndDownloadPuppeteer = async (
options: {
downloadProgressCallback?: (downloadedBytes: number, totalBytes: number) => void
confirmContinuePromise?: Promise<void>
} = {}
) => {
const puppeteerManager = await getPuppeteerManagerModule()
let installedBrowser: InstalledBrowser
if (!(await checkPuppeteerExecutable())) {

View File

@@ -130,7 +130,10 @@ export function createMainWindow(): void {
})
ipcMain.handle('check-dependencies', async () => {
return await checkPuppeteerExecutable()
const [puppeteerExecutableAvailable] = await Promise.all([checkPuppeteerExecutable()])
return {
puppeteerExecutableAvailable
}
})
let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null

View File

@@ -1,46 +1,84 @@
<template>
<el-dialog v-bind="$attrs" @open="percentage = 0">
<div>Downloading the necessary dependencies...</div>
<el-progress :percentage="percentage" :format="(n) => `${n.toFixed(1)}%`" />
<el-dialog v-bind="$attrs" @open="handleDialogOpen">
<template v-if="!copiedDependenciesStatus.puppeteerExecutableAvailable">
<div>Downloading Dedicate Browser</div>
<el-progress :percentage="browserDownloadPercentage" :format="(n) => `${n.toFixed(1)}%`" />
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, onUnmounted, onMounted } from 'vue'
import { ElMessageBox } from 'element-plus';
import { ref, onUnmounted, PropType } from 'vue'
import { ElMessageBox } from 'element-plus'
const props = defineProps({
dispose: Function
dispose: Function,
dependenciesStatus: {
type: Object as PropType<Record<string, boolean>>,
default: () => ({})
}
})
const percentage = ref(0)
const handleProgress = (ev, { downloadedBytes, totalBytes }) => {
percentage.value = (downloadedBytes / totalBytes) * 100
// shallow copy
const copiedDependenciesStatus = {
...props.dependenciesStatus
}
electron.ipcRenderer.on('PUPPETEER_DOWNLOAD_PROGRESS', handleProgress)
const handleDialogOpen = () => {
browserDownloadPercentage.value = 0
}
const browserDownloadPercentage = ref(0)
const handleBrowserDownloadProgress = (ev, { downloadedBytes, totalBytes }) => {
browserDownloadPercentage.value = (downloadedBytes / totalBytes) * 100
}
electron.ipcRenderer.on('PUPPETEER_DOWNLOAD_PROGRESS', handleBrowserDownloadProgress)
onUnmounted(() =>
electron.ipcRenderer.removeListener('PUPPETEER_DOWNLOAD_PROGRESS', handleProgress)
electron.ipcRenderer.removeListener('PUPPETEER_DOWNLOAD_PROGRESS', handleBrowserDownloadProgress)
)
const downloadProcessExitCode = ref(0)
const processDownload = async () => {
const processDownloadBrowser = async () => {
downloadProcessExitCode.value = 0
percentage.value = 0
browserDownloadPercentage.value = 0
try {
await electron.ipcRenderer.invoke('setup-dependencies')
props.dispose?.()
} catch(err) {
browserDownloadPercentage.value = 100
} catch (err) {
downloadProcessExitCode.value = 1
ElMessageBox.confirm('Encounter error while setup dependencies. Retry?')
.then(() => {
processDownload()
})
.catch(() => {
// FIXME: should exit app here
props.dispose?.()
})
throw err
}
}
processDownload()
const promiseList: Array<Promise<void>> = []
const processTasks = async () => {
if (!copiedDependenciesStatus.puppeteerExecutableAvailable) {
const p = processDownloadBrowser()
promiseList.push(p)
p.then(() => {
copiedDependenciesStatus.puppeteerExecutableAvailable = true
}).finally(() => {
const idx = promiseList.indexOf(p)
idx >= 0 && promiseList.splice(idx, 1)
})
}
while (promiseList.length) {
try {
await promiseList[0]
} catch {
ElMessageBox.confirm('Encounter error while setup dependencies. Retry?')
.then(() => {
processTasks()
})
.catch(() => {
// FIXME: should exit app here
promiseList.length = 0
props.dispose?.()
})
}
}
}
processTasks()
</script>

View File

@@ -2,7 +2,7 @@ import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import DependenciesSetupProgressIndicatorDialog from './index.vue'
export const mountGlobalDialog = () => {
export const mountGlobalDialog = (dependenciesStatus: Record<string, boolean>) => {
const containerElId = `elForDependenciesSetupProgressIndicatorDialog`
if (document.getElementById(containerElId)) {
@@ -27,7 +27,8 @@ export const mountGlobalDialog = () => {
onClosed() {
dispose()
},
dispose
dispose,
dependenciesStatus
}).use(ElementPlus)
app.mount(containerEl)

View File

@@ -95,8 +95,8 @@ const handleSubmit = async () => {
message: `Some dependencies might be corrupt. I'm trying to check and fix them.`
})
const checkDependenciesResult = await electron.ipcRenderer.invoke('check-dependencies')
if (!checkDependenciesResult) {
mountDependenciesSetupProgressIndicatorDialog()
if (Object.values(checkDependenciesResult).includes(false)) {
mountDependenciesSetupProgressIndicatorDialog(checkDependenciesResult)
// TODO: should continue interrupted task
}
}

View File

@@ -15,8 +15,8 @@ onUnmounted(() => {
})
;(async () => {
const checkDependenciesResult = await electron.ipcRenderer.invoke('check-dependencies')
if (!checkDependenciesResult) {
mountDependenciesSetupProgressIndicatorDialog()
if (Object.values(checkDependenciesResult).includes(false)) {
mountDependenciesSetupProgressIndicatorDialog(checkDependenciesResult)
}
})()
</script>