diff --git a/electron/main/backend/install-manager.ts b/electron/main/backend/install-manager.ts index f9db98c9..949f123f 100644 --- a/electron/main/backend/install-manager.ts +++ b/electron/main/backend/install-manager.ts @@ -412,27 +412,41 @@ ipcMain.handle("check-installed", async (_event, pkgname: string) => { const checkScript = "/opt/spark-store/extras/check-is-installed"; let isInstalled = false; - const child = spawn(checkScript, [pkgname], { - shell: false, - env: process.env, - }); - - await new Promise((resolve) => { - child.on("error", (err) => { - logger.error(`check-installed 执行失败: ${err?.message || err}`); - resolve(); + // 首先尝试使用内置脚本 + if (fs.existsSync(checkScript)) { + const child = spawn(checkScript, [pkgname], { + shell: false, + env: process.env, }); - child.on("close", (code) => { - if (code === 0) { - isInstalled = true; - logger.info(`应用已安装: ${pkgname}`); - } else { - logger.info(`应用未安装: ${pkgname} (exit ${code})`); - } - resolve(); + await new Promise((resolve) => { + child.on("error", (err) => { + logger.error(`check-installed 脚本执行失败: ${err?.message || err}`); + resolve(); + }); + + child.on("close", (code) => { + if (code === 0) { + isInstalled = true; + logger.info(`应用已安装 (脚本检测): ${pkgname}`); + } + resolve(); + }); }); - }); + + if (isInstalled) return true; + } + + // 如果脚本不存在或检测不到,使用 dpkg-query 作为后备 + logger.info(`尝试使用 dpkg-query 检测: ${pkgname}`); + const { code } = await runCommandCapture("dpkg-query", ["-W", "-f='${Status}'", pkgname]); + + if (code === 0) { + isInstalled = true; + logger.info(`应用已安装 (dpkg-query 检测): ${pkgname}`); + } else { + logger.info(`应用未安装: ${pkgname}`); + } return isInstalled; }); @@ -456,7 +470,7 @@ ipcMain.on("remove-installed", async (_event, pkgname: string) => { } const child = spawn( execCommand, - [...execParams, "aptss", "remove", pkgname ], + [...execParams, "aptss", "remove", pkgname], { shell: true, env: process.env, @@ -579,8 +593,8 @@ ipcMain.handle("launch-app", async (_event, pkgname: string) => { logger.warn("No pkgname provided for launch-app"); } - const execCommand = "/opt/spark-store/extras/host-spawn"; - const execParams = ["/opt/spark-store/extras/app-launcher", "launch", pkgname]; + const execCommand = "/opt/spark-store/extras/app-launcher"; + const execParams = ["start", pkgname]; logger.info( `Launching app: ${pkgname} with command: ${execCommand} ${execParams.join(" ")}`, diff --git a/src/App.vue b/src/App.vue index 736c4b7e..16616fad 100644 --- a/src/App.vue +++ b/src/App.vue @@ -633,8 +633,8 @@ const onUninstallSuccess = () => { } }; -const installCompleteCallback = () => { - if (currentApp.value) { +const installCompleteCallback = (pkgname?: string) => { + if (currentApp.value && (!pkgname || currentApp.value.pkgname === pkgname)) { checkAppInstalled(currentApp.value); } }; diff --git a/src/components/AppDetailModal.vue b/src/components/AppDetailModal.vue index a910cd08..7017bd67 100644 --- a/src/components/AppDetailModal.vue +++ b/src/components/AppDetailModal.vue @@ -236,8 +236,10 @@ const activeDownload = computed(() => { const { installFeedback } = useInstallFeedback(appPkgname); const { isCompleted } = useDownloadItemStatus(appPkgname); const installBtnText = computed(() => { + if (props.isinstalled) { + return "已安装"; + } if (isCompleted.value) { - // TODO: 似乎有一个时间差,安装好了之后并不是立马就可以从已安装列表看见 return "已安装"; } if (installFeedback.value) { diff --git a/src/global/downloadStatus.ts b/src/global/downloadStatus.ts index 1d32c7ca..202333bc 100644 --- a/src/global/downloadStatus.ts +++ b/src/global/downloadStatus.ts @@ -12,7 +12,7 @@ export function removeDownloadItem(pkgname: string) { } } -export function watchDownloadsChange(cb: () => void) { +export function watchDownloadsChange(cb: (pkgname: string) => void) { const statusById = new Map(); for (const item of downloads.value) { @@ -25,7 +25,7 @@ export function watchDownloadsChange(cb: () => void) { for (const item of list) { const prevStatus = statusById.get(item.id); if (item.status === "completed" && prevStatus !== "completed") { - cb(); + cb(item.pkgname); } statusById.set(item.id, item.status); }