mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 09:20:18 +08:00
优化启动速度
This commit is contained in:
@@ -138,7 +138,7 @@ const parseUpgradableList = (output: string) => {
|
|||||||
// Listen for download requests from renderer process
|
// Listen for download requests from renderer process
|
||||||
ipcMain.on("queue-install", async (event, download_json) => {
|
ipcMain.on("queue-install", async (event, download_json) => {
|
||||||
const download = JSON.parse(download_json);
|
const download = JSON.parse(download_json);
|
||||||
const { id, pkgname, metalinkUrl, filename } = download || {};
|
const { id, pkgname, metalinkUrl, filename, upgradeOnly } = download || {};
|
||||||
|
|
||||||
if (!id || !pkgname) {
|
if (!id || !pkgname) {
|
||||||
logger.warn("passed arguments missing id or pkgname");
|
logger.warn("passed arguments missing id or pkgname");
|
||||||
@@ -172,17 +172,28 @@ ipcMain.on("queue-install", async (event, download_json) => {
|
|||||||
const execParams = [];
|
const execParams = [];
|
||||||
const downloadDir = `/tmp/spark-store/download/${pkgname}`;
|
const downloadDir = `/tmp/spark-store/download/${pkgname}`;
|
||||||
|
|
||||||
if (superUserCmd.length > 0) {
|
// 升级操作:使用 spark-update-tool
|
||||||
|
if (upgradeOnly) {
|
||||||
|
execCommand = "pkexec";
|
||||||
|
execParams.push("spark-update-tool", pkgname);
|
||||||
|
logger.info(`升级模式: 使用 spark-update-tool 升级 ${pkgname}`);
|
||||||
|
} else if (superUserCmd.length > 0) {
|
||||||
execCommand = superUserCmd;
|
execCommand = superUserCmd;
|
||||||
execParams.push(SHELL_CALLER_PATH);
|
execParams.push(SHELL_CALLER_PATH);
|
||||||
|
|
||||||
|
if (metalinkUrl && filename) {
|
||||||
|
execParams.push("ssinstall", `${downloadDir}/${filename}`, "--delete-after-install");
|
||||||
|
} else {
|
||||||
|
execParams.push("aptss", "install", "-y", pkgname);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
execCommand = SHELL_CALLER_PATH;
|
execCommand = SHELL_CALLER_PATH;
|
||||||
}
|
|
||||||
|
|
||||||
if (metalinkUrl && filename) {
|
if (metalinkUrl && filename) {
|
||||||
execParams.push("ssinstall", `${downloadDir}/${filename}` , "--delete-after-install");
|
execParams.push("ssinstall", `${downloadDir}/${filename}`, "--delete-after-install");
|
||||||
} else {
|
} else {
|
||||||
execParams.push("aptss", "install", "-y", pkgname);
|
execParams.push("aptss", "install", "-y", pkgname);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const task: InstallTask = {
|
const task: InstallTask = {
|
||||||
|
|||||||
@@ -140,6 +140,26 @@ ipcMain.on("set-theme-source", (event, theme: "system" | "light" | "dark") => {
|
|||||||
nativeTheme.themeSource = theme;
|
nativeTheme.themeSource = theme;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 启动系统更新工具(使用 pkexec 提升权限)
|
||||||
|
ipcMain.handle("run-update-tool", async () => {
|
||||||
|
try {
|
||||||
|
const { spawn } = await import("node:child_process");
|
||||||
|
const pkexecPath = "/usr/bin/pkexec";
|
||||||
|
const args = ["spark-update-tool"];
|
||||||
|
const child = spawn(pkexecPath, args, {
|
||||||
|
detached: true,
|
||||||
|
stdio: "ignore",
|
||||||
|
});
|
||||||
|
// 让子进程在后台运行且不影响主进程退出
|
||||||
|
child.unref();
|
||||||
|
logger.info("Launched pkexec spark-update-tool");
|
||||||
|
return { success: true };
|
||||||
|
} catch (err) {
|
||||||
|
logger.error({ err }, "Failed to launch spark-update-tool");
|
||||||
|
return { success: false, message: (err as Error)?.message || String(err) };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
// Set User-Agent for client
|
// Set User-Agent for client
|
||||||
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||||
|
|||||||
106
src/App.vue
106
src/App.vue
@@ -346,8 +346,15 @@ const nextScreen = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = async () => {
|
||||||
openUpdateModal();
|
try {
|
||||||
|
const result = await window.ipcRenderer.invoke("run-update-tool");
|
||||||
|
if (!result || !result.success) {
|
||||||
|
logger.warn(`启动更新工具失败: ${result?.message || "未知错误"}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`调用更新工具时出错: ${error}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleList = () => {
|
const handleList = () => {
|
||||||
@@ -639,54 +646,58 @@ const loadCategories = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadApps = async () => {
|
const loadApps = async (onFirstBatch?: () => void) => {
|
||||||
loading.value = true;
|
|
||||||
try {
|
try {
|
||||||
logger.info("开始加载应用数据...");
|
logger.info("开始加载应用数据(并发分批)...");
|
||||||
|
|
||||||
// 改为顺序加载,避免同时发送过多请求
|
const categoriesList = Object.keys(categories.value || {});
|
||||||
for (const category of Object.keys(categories.value)) {
|
const concurrency = 4; // 同时并发请求数量,可根据网络条件调整
|
||||||
try {
|
|
||||||
logger.info(`加载分类: ${category}`);
|
|
||||||
const response = await axiosInstance.get<AppJson[]>(
|
|
||||||
cacheBuster(`/${window.apm_store.arch}/${category}/applist.json`),
|
|
||||||
);
|
|
||||||
|
|
||||||
const categoryApps = response.status === 200 ? response.data : [];
|
for (let i = 0; i < categoriesList.length; i += concurrency) {
|
||||||
categoryApps.forEach((appJson) => {
|
const batch = categoriesList.slice(i, i + concurrency);
|
||||||
// Convert AppJson to App here
|
await Promise.all(
|
||||||
const normalizedApp: App = {
|
batch.map(async (category) => {
|
||||||
name: appJson.Name,
|
try {
|
||||||
pkgname: appJson.Pkgname,
|
logger.info(`加载分类: ${category}`);
|
||||||
version: appJson.Version,
|
const response = await axiosInstance.get<AppJson[]>(
|
||||||
filename: appJson.Filename,
|
cacheBuster(`/${window.apm_store.arch}/${category}/applist.json`),
|
||||||
torrent_address: appJson.Torrent_address,
|
);
|
||||||
author: appJson.Author,
|
const categoryApps = response.status === 200 ? response.data : [];
|
||||||
contributor: appJson.Contributor,
|
categoryApps.forEach((appJson) => {
|
||||||
website: appJson.Website,
|
const normalizedApp: App = {
|
||||||
update: appJson.Update,
|
name: appJson.Name,
|
||||||
size: appJson.Size,
|
pkgname: appJson.Pkgname,
|
||||||
more: appJson.More,
|
version: appJson.Version,
|
||||||
tags: appJson.Tags,
|
filename: appJson.Filename,
|
||||||
img_urls:
|
torrent_address: appJson.Torrent_address,
|
||||||
typeof appJson.img_urls === "string"
|
author: appJson.Author,
|
||||||
? JSON.parse(appJson.img_urls)
|
contributor: appJson.Contributor,
|
||||||
: appJson.img_urls,
|
website: appJson.Website,
|
||||||
icons: appJson.icons,
|
update: appJson.Update,
|
||||||
category: category,
|
size: appJson.Size,
|
||||||
currentStatus: "not-installed",
|
more: appJson.More,
|
||||||
};
|
tags: appJson.Tags,
|
||||||
apps.value.push(normalizedApp);
|
img_urls:
|
||||||
});
|
typeof appJson.img_urls === "string"
|
||||||
} catch (error) {
|
? JSON.parse(appJson.img_urls)
|
||||||
logger.warn(`加载分类 ${category} 失败: ${error}`);
|
: appJson.img_urls,
|
||||||
// 继续加载其他分类
|
icons: appJson.icons,
|
||||||
}
|
category: category,
|
||||||
|
currentStatus: "not-installed",
|
||||||
|
};
|
||||||
|
apps.value.push(normalizedApp);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn(`加载分类 ${category} 失败: ${error}`);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 首批完成回调(用于隐藏首屏 loading)
|
||||||
|
if (i === 0 && typeof onFirstBatch === "function") onFirstBatch();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`加载应用数据失败: ${error}`);
|
logger.error(`加载应用数据失败: ${error}`);
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -699,7 +710,12 @@ onMounted(async () => {
|
|||||||
initTheme();
|
initTheme();
|
||||||
|
|
||||||
await loadCategories();
|
await loadCategories();
|
||||||
await loadApps();
|
// 先显示 loading,并异步开始分批加载应用列表。
|
||||||
|
loading.value = true;
|
||||||
|
loadApps(() => {
|
||||||
|
// 当第一批分类加载完成后,隐藏首屏 loading
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
// 设置键盘导航
|
// 设置键盘导航
|
||||||
document.addEventListener("keydown", (e) => {
|
document.addEventListener("keydown", (e) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user