mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-05-31 05:00:53 +08:00
add browserDownloadProgress relevant logic
This commit is contained in:
4
packages/ui/src/main/constant.ts
Normal file
4
packages/ui/src/main/constant.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import path from 'node:path'
|
||||
import os from 'node:os'
|
||||
|
||||
export const cacheDir = path.join(os.homedir(), '.geekgeekrun', 'cache')
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import {
|
||||
createBrowserDownloadProgressWindow,
|
||||
browserDownloadProgressWindow
|
||||
} from '../window/browserDownloadProgressWindow'
|
||||
|
||||
export async function openBrowserDownloadWindow({ windowOption } = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
createBrowserDownloadProgressWindow({ ...windowOption })
|
||||
|
||||
let processDone = false
|
||||
let pathOfDownloadedBrowser = null
|
||||
function handler(_, executablePath) {
|
||||
pathOfDownloadedBrowser = executablePath
|
||||
processDone = true
|
||||
browserDownloadProgressWindow.close()
|
||||
}
|
||||
ipcMain.once('browser-download-done', handler)
|
||||
browserDownloadProgressWindow.once('closed', () => {
|
||||
ipcMain.off('browser-download-done', handler)
|
||||
if (processDone) {
|
||||
resolve(pathOfDownloadedBrowser)
|
||||
} else {
|
||||
reject(new Error('USER_CANCELLED_CONFIG_BROWSER'))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -9,7 +9,7 @@ export enum DOWNLOAD_ERROR_EXIT_CODE {
|
||||
DOWNLOAD_ERROR = 80
|
||||
}
|
||||
|
||||
export const checkAndDownloadDependenciesForInit = async () => {
|
||||
export const downloadDependenciesForInit = async () => {
|
||||
process.on('disconnect', () => app.exit())
|
||||
process.on('uncaughtException', () => app.exit(DOWNLOAD_ERROR_EXIT_CODE.DOWNLOAD_ERROR))
|
||||
app.dock?.hide()
|
||||
@@ -50,7 +50,7 @@ export const checkAndDownloadDependenciesForInit = async () => {
|
||||
timeoutTimer = setTimeout(() => {
|
||||
// will encounter this when network disconnected when downloading
|
||||
promiseWithResolver.reject(new Error('PROGRESS_NOT_CHANGED_TOO_LONG'))
|
||||
}, 5 * 1000)
|
||||
}, 10 * 1000)
|
||||
} else {
|
||||
clearTimeout(throttleProgressTimer)
|
||||
throttleProgressTimer = null
|
||||
@@ -73,7 +73,7 @@ export const checkAndDownloadDependenciesForInit = async () => {
|
||||
)
|
||||
throttleProgressTimer = setTimeout(() => {
|
||||
throttleProgressTimer = null
|
||||
}, 2500)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -94,11 +94,13 @@ export const checkAndDownloadDependenciesForInit = async () => {
|
||||
pipe,
|
||||
JSON.stringify({
|
||||
type: 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR',
|
||||
...err instanceof Error ? {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
stack: err.stack
|
||||
} : null
|
||||
...(err instanceof Error
|
||||
? {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
stack: err.stack
|
||||
}
|
||||
: null)
|
||||
}) + '\r\n'
|
||||
)
|
||||
await sleep(1000)
|
||||
@@ -1,5 +1,3 @@
|
||||
import * as path from 'node:path'
|
||||
import * as os from 'node:os'
|
||||
import * as fs from 'node:fs'
|
||||
import type { InstalledBrowser } from '@puppeteer/browsers'
|
||||
import {
|
||||
@@ -10,6 +8,7 @@ import {
|
||||
} from '../browser-history'
|
||||
import gtag from '../../../../utils/gtag'
|
||||
import { EXPECT_CHROMIUM_BUILD_ID } from '../../../../../common/constant'
|
||||
import { cacheDir } from '../../../../constant'
|
||||
|
||||
const getPuppeteerManagerModule = async () => {
|
||||
const puppeteerManager = await import('@puppeteer/browsers')
|
||||
@@ -17,7 +16,6 @@ const getPuppeteerManagerModule = async () => {
|
||||
return puppeteerManager
|
||||
}
|
||||
|
||||
const cacheDir = path.join(os.homedir(), '.geekgeekrun', 'cache')
|
||||
|
||||
const getExpectCachedPuppeteerExecutable = async (): Promise<BrowserInfo> => {
|
||||
const puppeteerManager = await getPuppeteerManagerModule()
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
getPublicDbFilePath
|
||||
} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||
// import { pipeWriteRegardlessError } from '../utils/pipe'
|
||||
import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||
import { getAnyAvailablePuppeteerExecutable } from '../DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||
import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat'
|
||||
import attachListenerForKillSelfOnParentExited from '../../utils/attachListenerForKillSelfOnParentExited'
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { ChildProcess } from 'child_process'
|
||||
import * as JSONStream from 'JSONStream'
|
||||
import { checkCookieListFormat } from '../../../../common/utils/cookie'
|
||||
import { getAnyAvailablePuppeteerExecutable } from '../../../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable/index'
|
||||
import { getAnyAvailablePuppeteerExecutable } from '../../DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable/index'
|
||||
import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../../common/enums/auto-start-chat'
|
||||
import { mainWindow } from '../../../window/mainWindow'
|
||||
import {
|
||||
|
||||
@@ -34,7 +34,7 @@ import cheerio from 'cheerio'
|
||||
import { connectToDaemon, sendToDaemon } from '../OPEN_SETTING_WINDOW/connect-to-daemon'
|
||||
// import { pushCurrentPageScreenshot, SCREENSHOT_INTERVAL_MS } from '../../utils/screenshot'
|
||||
import { checkShouldExit } from '../../utils/worker'
|
||||
import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||
import { getAnyAvailablePuppeteerExecutable } from '../DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||
import minimist from 'minimist'
|
||||
import { checkCookieListFormat } from '../../../common/utils/cookie'
|
||||
import { loginWithCookieAssistant } from '../../features/login-with-cookie-assistant'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import minimist from 'minimist'
|
||||
import { runCommon } from './features/run-common';
|
||||
import { launchDaemon } from './flow/OPEN_SETTING_WINDOW/launch-daemon';
|
||||
import { app } from 'electron';
|
||||
import { runCommon } from './features/run-common'
|
||||
import { launchDaemon } from './flow/OPEN_SETTING_WINDOW/launch-daemon'
|
||||
import { app } from 'electron'
|
||||
|
||||
// 捕获未处理的 EPIPE 错误
|
||||
process.on('uncaughtException', (err) => {
|
||||
@@ -9,13 +9,13 @@ process.on('uncaughtException', (err) => {
|
||||
return
|
||||
}
|
||||
throw err
|
||||
});
|
||||
})
|
||||
|
||||
const isUiDev = process.env.NODE_ENV === 'development'
|
||||
const commandlineArgs = minimist(isUiDev ? process.argv.slice(2) : process.argv.slice(1))
|
||||
console.log(commandlineArgs)
|
||||
|
||||
const runMode = commandlineArgs['mode'];
|
||||
const runMode = commandlineArgs['mode']
|
||||
|
||||
;(async () => {
|
||||
switch (runMode) {
|
||||
@@ -27,11 +27,9 @@ const runMode = commandlineArgs['mode'];
|
||||
waitForProcessHandShakeAndRunAutoChat()
|
||||
break
|
||||
}
|
||||
case 'checkAndDownloadDependenciesForInit': {
|
||||
const { checkAndDownloadDependenciesForInit } = await import(
|
||||
'./flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/index'
|
||||
)
|
||||
checkAndDownloadDependenciesForInit()
|
||||
case 'downloadDependenciesForInit': {
|
||||
const { downloadDependenciesForInit } = await import('./flow/DOWNLOAD_DEPENDENCIES/index')
|
||||
downloadDependenciesForInit()
|
||||
break
|
||||
}
|
||||
case 'launchBossZhipinLoginPageWithPreloadExtension': {
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
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 { getAnyAvailablePuppeteerExecutable } from '../flow/DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||
import {
|
||||
getLastUsedAndAvailableBrowser,
|
||||
saveLastUsedAndAvailableBrowserInfo
|
||||
} from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/browser-history'
|
||||
} from '../flow/DOWNLOAD_DEPENDENCIES/utils/browser-history'
|
||||
import { openBrowserDownloadWindow } from '../features/open-browser-download-window'
|
||||
|
||||
export let browserAssistantWindow: BrowserWindow | null = null
|
||||
|
||||
@@ -83,67 +81,15 @@ export function createBrowserAssistantWindow(
|
||||
}
|
||||
)
|
||||
|
||||
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']
|
||||
registerHandleWithWindow(browserAssistantWindow, 'download-browser-with-downloader', async () => {
|
||||
return await openBrowserDownloadWindow({
|
||||
windowOption: {
|
||||
parent: browserAssistantWindow!,
|
||||
modal: true,
|
||||
show: true
|
||||
}
|
||||
)
|
||||
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!
|
||||
}
|
||||
|
||||
124
packages/ui/src/main/window/browserDownloadProgressWindow.ts
Normal file
124
packages/ui/src/main/window/browserDownloadProgressWindow.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import { ChildProcess } from 'child_process'
|
||||
import { BrowserWindow, ipcMain } from 'electron'
|
||||
import path from 'path'
|
||||
import * as childProcess from 'node:child_process'
|
||||
import * as JSONStream from 'JSONStream'
|
||||
import * as fs from 'node:fs'
|
||||
import { cacheDir } from '../constant'
|
||||
import { EXPECT_CHROMIUM_BUILD_ID } from '../../common/constant'
|
||||
import * as puppeteerManager from '@puppeteer/browsers'
|
||||
|
||||
export let browserDownloadProgressWindow: BrowserWindow | null = null
|
||||
|
||||
const registerHandleWithWindow = (
|
||||
win: BrowserWindow,
|
||||
...args: Parameters<typeof ipcMain.handle>
|
||||
) => {
|
||||
const [channel, handler] = args
|
||||
ipcMain.handle(channel, handler)
|
||||
win.once('closed', () => ipcMain.removeHandler(channel))
|
||||
}
|
||||
|
||||
export function createBrowserDownloadProgressWindow(
|
||||
opt?: Electron.BrowserWindowConstructorOptions
|
||||
): BrowserWindow {
|
||||
// Create the browser window.
|
||||
if (browserDownloadProgressWindow) {
|
||||
browserDownloadProgressWindow!.close()
|
||||
}
|
||||
browserDownloadProgressWindow = new BrowserWindow({
|
||||
width: 600,
|
||||
height: 200,
|
||||
resizable: false,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, '../preload/index.js'),
|
||||
sandbox: false
|
||||
},
|
||||
...opt
|
||||
})
|
||||
|
||||
browserDownloadProgressWindow.on('ready-to-show', () => {
|
||||
browserDownloadProgressWindow!.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']) {
|
||||
browserDownloadProgressWindow.loadURL(
|
||||
process.env['ELECTRON_RENDERER_URL'] + '#/browserDownloadProgress'
|
||||
)
|
||||
} else {
|
||||
browserDownloadProgressWindow.loadURL(
|
||||
'file://' + path.join(__dirname, '../renderer/index.html') + '#/browserDownloadProgress'
|
||||
)
|
||||
}
|
||||
|
||||
let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null
|
||||
registerHandleWithWindow(browserDownloadProgressWindow, 'setup-dependencies', async () => {
|
||||
if (subProcessOfCheckAndDownloadDependencies) {
|
||||
return
|
||||
}
|
||||
subProcessOfCheckAndDownloadDependencies = childProcess.spawn(
|
||||
process.argv[0],
|
||||
[process.argv[1], `--mode=downloadDependenciesForInit`],
|
||||
{
|
||||
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': {
|
||||
browserDownloadProgressWindow?.webContents.send(data.type, data)
|
||||
break
|
||||
}
|
||||
case 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR': {
|
||||
console.error(data)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
subProcessOfCheckAndDownloadDependencies!.once('exit', (exitCode) => {
|
||||
const executablePath = puppeteerManager.computeExecutablePath({
|
||||
browser: puppeteerManager.Browser.CHROME,
|
||||
cacheDir,
|
||||
buildId: EXPECT_CHROMIUM_BUILD_ID
|
||||
})
|
||||
if (exitCode === 0 && fs.existsSync(executablePath)) {
|
||||
resolve(executablePath)
|
||||
} else {
|
||||
reject('PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR')
|
||||
}
|
||||
subProcessOfCheckAndDownloadDependencies = null
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const killHandler = async () => {
|
||||
try {
|
||||
subProcessOfCheckAndDownloadDependencies?.kill()
|
||||
} catch {
|
||||
//
|
||||
} finally {
|
||||
subProcessOfCheckAndDownloadDependencies = null
|
||||
}
|
||||
}
|
||||
browserDownloadProgressWindow.once('closed', () => {
|
||||
killHandler()
|
||||
})
|
||||
browserDownloadProgressWindow.once('closed', () => {
|
||||
browserDownloadProgressWindow = null
|
||||
})
|
||||
|
||||
return browserDownloadProgressWindow!
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
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 { getAnyAvailablePuppeteerExecutable } from '../flow/DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable'
|
||||
import * as childProcess from 'node:child_process'
|
||||
import * as JSONStream from 'JSONStream'
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
<li>
|
||||
方案一:通过本程序下载 Google Chrome for Testing
|
||||
{{ EXPECT_CHROMIUM_BUILD_ID }} -
|
||||
<a href="javascript:;">点击此处</a
|
||||
>即可下载;这个浏览器由本程序独占,不会影响到当前的 Google Chrome
|
||||
<a href="javascript:;" @click="handleClickLaunchBrowserDownloader">点击此处</a
|
||||
>即可下载;这个浏览器仅供本程序使用,不会影响到当前 Google Chrome
|
||||
安装。本程序开发过程中主要是使用这个浏览器测试的,<span color-orange
|
||||
>可以保证兼容性</span
|
||||
>。但网络波动,有一定概率下载失败。如多次尝试后确实不能下载成功,请尝试方案二。<span
|
||||
>。网络波动,有一定概率下载失败;如多次尝试后确实不能下载成功,请尝试方案二。<span
|
||||
color-orange
|
||||
>(推荐)</span
|
||||
>
|
||||
@@ -54,7 +54,7 @@
|
||||
>浏览器升级后某些功能不兼容导致本程序不能正确运行</span
|
||||
>的问题。您可以<a href="javascript:;" @click="handleFeedbackClick"
|
||||
>提交 Issue</a
|
||||
>来反馈新版本浏览器不能正常运行的问题,同时请再尝试方法一。
|
||||
>来反馈新版本浏览器不能正常运行的问题,同时请再尝试方案一。
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -142,13 +142,19 @@ async function autoDetectPuppeteerExecutable() {
|
||||
noSave: true
|
||||
})
|
||||
if (!result) {
|
||||
ElMessage.warning({
|
||||
ElMessage({
|
||||
message: '未检测到可用浏览器的可执行文件',
|
||||
type: 'warning'
|
||||
type: 'warning',
|
||||
grouping: true
|
||||
})
|
||||
return
|
||||
}
|
||||
formData.value.browserPath = result.executablePath
|
||||
ElMessage({
|
||||
message: '已找到可用浏览器,可执行文件路径已填入输入框',
|
||||
type: 'success',
|
||||
grouping: true
|
||||
})
|
||||
}
|
||||
|
||||
async function browserExecutableFile() {
|
||||
@@ -177,7 +183,9 @@ function handleCancel() {
|
||||
gtagRenderer('cancel_clicked')
|
||||
window.close()
|
||||
}
|
||||
const formRef = ref()
|
||||
async function handleSave() {
|
||||
await formRef.value.validate()
|
||||
await ipcRenderer.invoke('save-last-used-and-available-browser-info', {
|
||||
executablePath: formData.value.browserPath,
|
||||
browser: ''
|
||||
@@ -188,6 +196,18 @@ const handleFeedbackClick = () => {
|
||||
gtagRenderer('goto_feedback_for_ba_clicked')
|
||||
electron.ipcRenderer.send('send-feed-back-to-github-issue')
|
||||
}
|
||||
const handleClickLaunchBrowserDownloader = async () => {
|
||||
gtagRenderer('launch_browser_downloader_clicked')
|
||||
const downloadedBrowserPath = await electron.ipcRenderer.invoke('download-browser-with-downloader')
|
||||
if (downloadedBrowserPath) {
|
||||
formData.value.browserPath = downloadedBrowserPath
|
||||
ElMessage({
|
||||
message: '浏览器下载成功,可执行文件路径已填入输入框',
|
||||
type: 'success',
|
||||
grouping: true
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<div class="flex flex-col flex-items-start flex-justify-start" v-if="!dependenciesStatus.puppeteerExecutableAvailable">
|
||||
<div mb14px>正在下载兼容的浏览器</div>
|
||||
<el-progress
|
||||
:percentage="browserDownloadPercentage"
|
||||
:format="(n) => `${n.toFixed(1)}%`"
|
||||
:stroke-width="10"
|
||||
class="w400px"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onUnmounted, PropType, h } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { gtagRenderer } from '@renderer/utils/gtag'
|
||||
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||
import FailMessage from './FailMessage.vue'
|
||||
|
||||
const props = defineProps({
|
||||
dependenciesStatus: {
|
||||
type: Object as PropType<Record<string, boolean>>,
|
||||
default: () => ({})
|
||||
},
|
||||
processWaitee: Object
|
||||
})
|
||||
|
||||
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', handleBrowserDownloadProgress)
|
||||
)
|
||||
const downloadProcessExitCode = ref(0)
|
||||
|
||||
const processDownloadBrowser = async () => {
|
||||
downloadProcessExitCode.value = 0
|
||||
browserDownloadPercentage.value = 0
|
||||
let restRetriedTime = 2
|
||||
while (restRetriedTime > 0) {
|
||||
try {
|
||||
try {
|
||||
await electron.ipcRenderer.invoke('setup-dependencies')
|
||||
browserDownloadPercentage.value = 100
|
||||
} catch (err) {
|
||||
downloadProcessExitCode.value = 1
|
||||
throw err
|
||||
}
|
||||
break
|
||||
} catch (err) {
|
||||
restRetriedTime--
|
||||
if (restRetriedTime === 0) {
|
||||
throw err
|
||||
}
|
||||
await sleep(5000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const promiseList: Array<Promise<void>> = []
|
||||
const processTasks = async () => {
|
||||
if (!props.dependenciesStatus.puppeteerExecutableAvailable) {
|
||||
gtagRenderer('start_download_puppeteer')
|
||||
const p = processDownloadBrowser()
|
||||
promiseList.push(p)
|
||||
p.then(() => {
|
||||
gtagRenderer('puppeteer_download_success')
|
||||
props.dependenciesStatus.puppeteerExecutableAvailable = true
|
||||
})
|
||||
}
|
||||
|
||||
while (promiseList.length) {
|
||||
const p = promiseList.shift()!
|
||||
try {
|
||||
p.then(() => {
|
||||
if (!promiseList.length) {
|
||||
props.processWaitee?.resolve?.()
|
||||
}
|
||||
})
|
||||
await p
|
||||
} catch {
|
||||
gtagRenderer('encounter_error_when_download_deps')
|
||||
await ElMessageBox.confirm(h(FailMessage), {
|
||||
closeOnClickModal: false,
|
||||
closeOnPressEscape: false,
|
||||
showClose: false,
|
||||
type: 'error',
|
||||
cancelButtonText: '退出程序',
|
||||
confirmButtonText: '重试'
|
||||
})
|
||||
.then(() => {
|
||||
gtagRenderer('start_retry_download_deps')
|
||||
processTasks()
|
||||
})
|
||||
.catch(() => {
|
||||
gtagRenderer('cancel_download_deps_and_exit')
|
||||
promiseList.length = 0
|
||||
electron.ipcRenderer.invoke('exit-app-immediately')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processTasks()
|
||||
</script>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>核心组件下载失败,请重试。</p>
|
||||
<br />
|
||||
<p>浏览器下载失败,请重试,或使用其他方式下载</p>
|
||||
<!-- <br />
|
||||
<br />
|
||||
<p>
|
||||
<b text-orange>提示:</b>由于网络颠簸,如果多次重试仍然失败,请 <el-button
|
||||
@@ -12,23 +12,23 @@
|
||||
>点击此处</el-button
|
||||
> 下载最新版本 Google Chrome
|
||||
浏览器,安装完毕后,重新打开本程序,程序会自动检测该浏览器并使用它。
|
||||
</p>
|
||||
</p> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { gtagRenderer } from '@renderer/utils/gtag'
|
||||
import debounce from 'lodash/debounce'
|
||||
const { ipcRenderer } = electron
|
||||
// import { gtagRenderer } from '@renderer/utils/gtag'
|
||||
// import debounce from 'lodash/debounce'
|
||||
// const { ipcRenderer } = electron
|
||||
|
||||
const handleOpenChromeDownloadPage = debounce(
|
||||
async () => {
|
||||
gtagRenderer('open_chrome_download_page_clicked')
|
||||
ipcRenderer.send('open-external-link', 'https://www.google.cn/chrome/')
|
||||
},
|
||||
1000,
|
||||
{ leading: true, trailing: false }
|
||||
)
|
||||
// const handleOpenChromeDownloadPage = debounce(
|
||||
// async () => {
|
||||
// gtagRenderer('open_chrome_download_page_clicked')
|
||||
// ipcRenderer.send('open-external-link', 'https://www.google.cn/chrome/')
|
||||
// },
|
||||
// 1000,
|
||||
// { leading: true, trailing: false }
|
||||
// )
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<!-- flex-items- -->
|
||||
<div class="flex flex-col flex-justify-center w500px h-full ml-auto mr-auto">
|
||||
<div font-size-14px>正在下载 Google Chrome for Testing {{ EXPECT_CHROMIUM_BUILD_ID }}</div>
|
||||
<el-progress
|
||||
:percentage="browserDownloadPercentage"
|
||||
:format="(n) => `${n.toFixed(1)}%`"
|
||||
:stroke-width="10"
|
||||
class="w500px"
|
||||
mt10px
|
||||
/>
|
||||
<div mt10px>
|
||||
<el-button @click="handleCancelDownload">取消下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onUnmounted, h } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { gtagRenderer } from '@renderer/utils/gtag'
|
||||
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||
import FailMessage from './FailMessage.vue'
|
||||
import { EXPECT_CHROMIUM_BUILD_ID } from '../../../../common/constant'
|
||||
|
||||
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', handleBrowserDownloadProgress)
|
||||
)
|
||||
const downloadProcessExitCode = ref(0)
|
||||
|
||||
let executablePath
|
||||
const processDownloadBrowser = async () => {
|
||||
downloadProcessExitCode.value = 0
|
||||
browserDownloadPercentage.value = 0
|
||||
let restRetriedTime = 2
|
||||
while (restRetriedTime > 0) {
|
||||
try {
|
||||
try {
|
||||
executablePath = await electron.ipcRenderer.invoke('setup-dependencies')
|
||||
browserDownloadPercentage.value = 100
|
||||
} catch (err) {
|
||||
downloadProcessExitCode.value = 1
|
||||
throw err
|
||||
}
|
||||
break
|
||||
} catch (err) {
|
||||
restRetriedTime--
|
||||
if (restRetriedTime === 0) {
|
||||
throw err
|
||||
}
|
||||
await sleep(5000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const processTasks = async () => {
|
||||
try {
|
||||
await processDownloadBrowser()
|
||||
electron.ipcRenderer.send('browser-download-done', executablePath)
|
||||
} catch (err) {
|
||||
gtagRenderer('encounter_error_when_download_deps')
|
||||
await ElMessageBox.confirm(h(FailMessage), {
|
||||
closeOnClickModal: false,
|
||||
closeOnPressEscape: false,
|
||||
showClose: false,
|
||||
type: 'error',
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonText: '重试'
|
||||
})
|
||||
.then(() => {
|
||||
gtagRenderer('start_retry_download_deps')
|
||||
processTasks()
|
||||
})
|
||||
.catch(() => {
|
||||
gtagRenderer('cancel_download_deps_from_err_dialog')
|
||||
window.close()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
processTasks()
|
||||
|
||||
function handleCancelDownload() {
|
||||
gtagRenderer('cancel_download_deps_from_cancel_btn')
|
||||
window.close()
|
||||
}
|
||||
</script>
|
||||
@@ -22,16 +22,14 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@renderer/page/BrowserAssistant/index.vue'),
|
||||
meta: {
|
||||
title: '浏览器助手'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/downloadingDependencies',
|
||||
component: () => import('@renderer/page/BrowserAssistant/page/DownloadingDependencies.vue'),
|
||||
meta: {
|
||||
title: '正在下载核心组件'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/browserDownloadProgress',
|
||||
component: () => import('@renderer/page/BrowserDownloadProgress/index.vue'),
|
||||
meta: {
|
||||
title: '正在下载浏览器'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/llmConfig',
|
||||
|
||||
Reference in New Issue
Block a user