mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 01:10:16 +08:00
新增更新中心模块,支持管理 APM 和传统 deb 软件更新任务 - 添加更新任务队列管理、状态跟踪和日志记录功能 - 实现更新项忽略配置持久化存储 - 新增更新确认对话框和迁移提示 - 优化主窗口关闭时的任务保护机制 - 添加单元测试覆盖核心逻辑
159 lines
3.8 KiB
TypeScript
159 lines
3.8 KiB
TypeScript
import type { UpdateCenterItem } from "./types";
|
|
|
|
export type UpdateCenterTaskStatus =
|
|
| "queued"
|
|
| "downloading"
|
|
| "installing"
|
|
| "completed"
|
|
| "failed"
|
|
| "cancelled";
|
|
|
|
export interface UpdateCenterTaskLog {
|
|
time: number;
|
|
message: string;
|
|
}
|
|
|
|
export interface UpdateCenterTask {
|
|
id: number;
|
|
pkgname: string;
|
|
item: UpdateCenterItem;
|
|
status: UpdateCenterTaskStatus;
|
|
progress: number;
|
|
logs: UpdateCenterTaskLog[];
|
|
error?: string;
|
|
}
|
|
|
|
export interface UpdateCenterQueueSnapshot {
|
|
items: UpdateCenterItem[];
|
|
tasks: UpdateCenterTask[];
|
|
warnings: string[];
|
|
hasRunningTasks: boolean;
|
|
}
|
|
|
|
export interface UpdateCenterQueue {
|
|
setItems: (items: UpdateCenterItem[]) => void;
|
|
startRefresh: () => void;
|
|
finishRefresh: (warnings?: string[]) => void;
|
|
enqueueItem: (item: UpdateCenterItem) => UpdateCenterTask;
|
|
markActiveTask: (
|
|
taskId: number,
|
|
status: Extract<UpdateCenterTaskStatus, "downloading" | "installing">,
|
|
) => void;
|
|
updateTaskProgress: (taskId: number, progress: number) => void;
|
|
appendTaskLog: (taskId: number, message: string, time?: number) => void;
|
|
finishTask: (
|
|
taskId: number,
|
|
status: Extract<
|
|
UpdateCenterTaskStatus,
|
|
"completed" | "failed" | "cancelled"
|
|
>,
|
|
error?: string,
|
|
) => void;
|
|
getNextQueuedTask: () => UpdateCenterTask | undefined;
|
|
getSnapshot: () => UpdateCenterQueueSnapshot;
|
|
}
|
|
|
|
const clampProgress = (progress: number): number => {
|
|
if (!Number.isFinite(progress)) {
|
|
return 0;
|
|
}
|
|
|
|
return Math.max(0, Math.min(100, Math.round(progress)));
|
|
};
|
|
|
|
const createSnapshot = (
|
|
items: UpdateCenterItem[],
|
|
tasks: UpdateCenterTask[],
|
|
warnings: string[],
|
|
refreshing: boolean,
|
|
): UpdateCenterQueueSnapshot => ({
|
|
items: items.map((item) => ({ ...item })),
|
|
tasks: tasks.map((task) => ({
|
|
...task,
|
|
item: { ...task.item },
|
|
logs: task.logs.map((log) => ({ ...log })),
|
|
})),
|
|
warnings: [...warnings],
|
|
hasRunningTasks:
|
|
refreshing ||
|
|
tasks.some((task) =>
|
|
["queued", "downloading", "installing"].includes(task.status),
|
|
),
|
|
});
|
|
|
|
export const createUpdateCenterQueue = (): UpdateCenterQueue => {
|
|
let items: UpdateCenterItem[] = [];
|
|
let tasks: UpdateCenterTask[] = [];
|
|
let warnings: string[] = [];
|
|
let refreshing = false;
|
|
let nextTaskId = 1;
|
|
|
|
const getTask = (taskId: number): UpdateCenterTask | undefined =>
|
|
tasks.find((task) => task.id === taskId);
|
|
|
|
return {
|
|
setItems: (nextItems) => {
|
|
items = nextItems.map((item) => ({ ...item }));
|
|
},
|
|
startRefresh: () => {
|
|
refreshing = true;
|
|
},
|
|
finishRefresh: (nextWarnings = []) => {
|
|
refreshing = false;
|
|
warnings = [...nextWarnings];
|
|
},
|
|
enqueueItem: (item) => {
|
|
const task: UpdateCenterTask = {
|
|
id: nextTaskId,
|
|
pkgname: item.pkgname,
|
|
item: { ...item },
|
|
status: "queued",
|
|
progress: 0,
|
|
logs: [],
|
|
};
|
|
|
|
nextTaskId += 1;
|
|
tasks = [...tasks, task];
|
|
return task;
|
|
},
|
|
markActiveTask: (taskId, status) => {
|
|
const task = getTask(taskId);
|
|
if (!task) {
|
|
return;
|
|
}
|
|
|
|
task.status = status;
|
|
},
|
|
updateTaskProgress: (taskId, progress) => {
|
|
const task = getTask(taskId);
|
|
if (!task) {
|
|
return;
|
|
}
|
|
|
|
task.progress = clampProgress(progress);
|
|
},
|
|
appendTaskLog: (taskId, message, time = Date.now()) => {
|
|
const task = getTask(taskId);
|
|
if (!task) {
|
|
return;
|
|
}
|
|
|
|
task.logs = [...task.logs, { time, message }];
|
|
},
|
|
finishTask: (taskId, status, error) => {
|
|
const task = getTask(taskId);
|
|
if (!task) {
|
|
return;
|
|
}
|
|
|
|
task.status = status;
|
|
task.error = error;
|
|
if (status === "completed") {
|
|
task.progress = 100;
|
|
}
|
|
},
|
|
getNextQueuedTask: () => tasks.find((task) => task.status === "queued"),
|
|
getSnapshot: () => createSnapshot(items, tasks, warnings, refreshing),
|
|
};
|
|
};
|