mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 09:20:18 +08:00
fix(install-manager): 优化已安装应用列表获取逻辑并改进安装成功提示
使用 `apm list --installed` 命令替代直接读取文件系统来获取已安装应用列表,提高可靠性 改进安装成功提示信息,更清晰地说明重启和立即使用的选项
This commit is contained in:
@@ -240,7 +240,7 @@ ipcMain.on("queue-install", async (event, download_json) => {
|
|||||||
title: "APM 安装成功",
|
title: "APM 安装成功",
|
||||||
message: "恭喜您,APM 已成功安装",
|
message: "恭喜您,APM 已成功安装",
|
||||||
detail:
|
detail:
|
||||||
"APM 应用需重启后方可展示和使用,若完成安装后无法在应用列表中展示,请重启电脑后继续。",
|
"恭喜您,APM 已成功安装!您的应用已在安装中~\n首次安装APM后,需要重启电脑后方可在启动器展示应用。您可在应用安装完毕后择机重启电脑\n若您需要立即使用应用,可在应用安装后先在应用商店中打开您的应用。",
|
||||||
buttons: ["确定"],
|
buttons: ["确定"],
|
||||||
defaultId: 0,
|
defaultId: 0,
|
||||||
});
|
});
|
||||||
@@ -763,16 +763,21 @@ ipcMain.handle("list-installed", async () => {
|
|||||||
const apmBasePath = "/var/lib/apm/apm/files/ace-env/var/lib/apm";
|
const apmBasePath = "/var/lib/apm/apm/files/ace-env/var/lib/apm";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(apmBasePath)) {
|
// 使用 apm list --installed 获取所有已安装应用
|
||||||
logger.warn(`APM base path not found: ${apmBasePath}`);
|
const { code, stdout } = await runCommandCapture("apm", [
|
||||||
|
"list",
|
||||||
|
"--installed",
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (code !== 0) {
|
||||||
|
logger.warn(`Failed to list installed packages: ${stdout}`);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "APM base path not found",
|
message: "Failed to list installed packages",
|
||||||
apps: [],
|
apps: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const packages = fs.readdirSync(apmBasePath, { withFileTypes: true });
|
|
||||||
const installedApps: Array<{
|
const installedApps: Array<{
|
||||||
pkgname: string;
|
pkgname: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -784,52 +789,40 @@ ipcMain.handle("list-installed", async () => {
|
|||||||
isDependency: boolean;
|
isDependency: boolean;
|
||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
for (const pkg of packages) {
|
const cleanStdout = stdout.replace(
|
||||||
if (!pkg.isDirectory()) continue;
|
// eslint-disable-next-line no-control-regex
|
||||||
|
/\x1b\[[0-9;]*m/g,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
const lines = cleanStdout.split("\n");
|
||||||
|
|
||||||
const pkgname = pkg.name;
|
for (const line of lines) {
|
||||||
const pkgPath = path.join(apmBasePath, pkgname);
|
const trimmed = line.trim();
|
||||||
|
if (
|
||||||
const { code, stdout } = await runCommandCapture("apm", [
|
!trimmed ||
|
||||||
"list",
|
trimmed.startsWith("Listing") ||
|
||||||
pkgname,
|
trimmed.startsWith("[INFO]") ||
|
||||||
]);
|
trimmed.startsWith("警告")
|
||||||
if (code !== 0) {
|
)
|
||||||
logger.warn(`Failed to list package ${pkgname}: ${stdout}`);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
const cleanStdout = stdout.replace(
|
// 解析格式: pkgname/repo,section version arch [flags]
|
||||||
// eslint-disable-next-line no-control-regex
|
const match = trimmed.match(
|
||||||
/\x1b\[[0-9;]*m/g,
|
/^(\S+)\/\S+,\S+\s+(\S+)\s+(\S+)\s+\[(.+)\]$/,
|
||||||
"",
|
|
||||||
);
|
);
|
||||||
const lines = cleanStdout.split("\n");
|
if (!match) continue;
|
||||||
|
|
||||||
for (const line of lines) {
|
const [, pkgname, version, arch, flags] = match;
|
||||||
const trimmed = line.trim();
|
|
||||||
if (
|
|
||||||
!trimmed ||
|
|
||||||
trimmed.startsWith("Listing") ||
|
|
||||||
trimmed.startsWith("[INFO]") ||
|
|
||||||
trimmed.startsWith("警告")
|
|
||||||
)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const match = trimmed.match(
|
// 从桌面文件获取应用名称和图标
|
||||||
/^(\S+)\/\S+,\S+\s+(\S+)\s+(\S+)\s+\[(.+)\]$/,
|
let appName = pkgname;
|
||||||
);
|
let icon = "";
|
||||||
if (!match) continue;
|
const pkgPath = path.join(apmBasePath, pkgname);
|
||||||
|
const entriesPath = path.join(pkgPath, "entries", "applications");
|
||||||
|
const hasEntries = fs.existsSync(entriesPath);
|
||||||
|
|
||||||
const [, listedPkgname, version, arch, flags] = match;
|
if (hasEntries) {
|
||||||
if (listedPkgname !== pkgname) continue;
|
try {
|
||||||
|
|
||||||
let appName = pkgname;
|
|
||||||
let icon = "";
|
|
||||||
const entriesPath = path.join(pkgPath, "entries", "applications");
|
|
||||||
const hasEntries = fs.existsSync(entriesPath);
|
|
||||||
|
|
||||||
if (hasEntries) {
|
|
||||||
const desktopFiles = fs.readdirSync(entriesPath);
|
const desktopFiles = fs.readdirSync(entriesPath);
|
||||||
for (const file of desktopFiles) {
|
for (const file of desktopFiles) {
|
||||||
if (file.endsWith(".desktop")) {
|
if (file.endsWith(".desktop")) {
|
||||||
@@ -842,19 +835,21 @@ ipcMain.handle("list-installed", async () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.warn(`Failed to read desktop file for ${pkgname}: ${e}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
installedApps.push({
|
|
||||||
pkgname,
|
|
||||||
name: appName,
|
|
||||||
version,
|
|
||||||
arch,
|
|
||||||
flags,
|
|
||||||
origin: "apm",
|
|
||||||
icon: icon || undefined,
|
|
||||||
isDependency: !hasEntries,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
installedApps.push({
|
||||||
|
pkgname,
|
||||||
|
name: appName,
|
||||||
|
version,
|
||||||
|
arch,
|
||||||
|
flags,
|
||||||
|
origin: "apm",
|
||||||
|
icon: icon || undefined,
|
||||||
|
isDependency: !hasEntries,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
installedApps.sort((a, b) => {
|
installedApps.sort((a, b) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user