feat: deliver the redesigned desktop workspace

Rebuild downloads, link collection, settings, history, and statistics around a responsive desktop shell with compact account and queue tables, contextual navigation, persistent update affordances, unified overlays, and accessible keyboard interactions.

Add safe history-folder reveal IPC, responsive 2560/1920/1366/1120 coverage, deterministic visual fixtures, focused component regressions, and release-tree exclusions for internal working files. Bump the public application version to 2.0.13.
This commit is contained in:
Sucukdeluxe
2026-08-10 14:15:57 +02:00
parent d844b33501
commit 069babfd54
77 changed files with 17442 additions and 3333 deletions
+104
View File
@@ -0,0 +1,104 @@
import { win32 } from "node:path";
import type { HistoryEntry, HistoryRevealResult } from "../shared/types";
export interface HistoryRevealRequest {
entryId: unknown;
}
export interface HistoryRevealStat {
isDirectory: () => boolean;
}
export interface HistoryRevealDependencies {
loadHistory: () => HistoryEntry[] | Promise<HistoryEntry[]>;
stat: (directory: string) => Promise<HistoryRevealStat>;
openPath: (directory: string) => Promise<string>;
}
function normalizeHistoryDirectory(value: unknown): string | null {
if (typeof value !== "string" || value.length === 0 || /[\u0000-\u001f\u007f]/.test(value)) {
return null;
}
const candidate = value.replaceAll("/", "\\");
const lower = candidate.toLocaleLowerCase("en-US");
if (
lower.startsWith("\\\\.\\")
|| lower.startsWith("\\\\?\\")
|| lower.startsWith("\\??\\")
|| lower.startsWith("\\\\globalroot\\")
|| lower.startsWith("\\\\device\\")
) {
return null;
}
const driveAbsolute = /^[A-Za-z]:\\/.test(candidate);
const uncMatch = /^\\\\([^\\]+)\\([^\\]+)(?:\\.*)?$/.exec(candidate);
if (!driveAbsolute && !uncMatch) {
return null;
}
if (driveAbsolute) {
if (candidate.slice(2).includes(":")) {
return null;
}
} else if (candidate.includes(":")) {
return null;
}
if (/[<>|"?*]/.test(driveAbsolute ? candidate.slice(3) : candidate.slice(2))) {
return null;
}
if (uncMatch) {
const server = uncMatch[1].toLocaleLowerCase("en-US");
const share = uncMatch[2].toLocaleLowerCase("en-US");
if ([".", "..", "?", "globalroot", "device"].includes(server) || share === "." || share === "..") {
return null;
}
}
const normalized = win32.normalize(candidate);
if (/^[A-Za-z]:\\/.test(normalized)) {
return normalized;
}
if (/^\\\\[^\\]+\\[^\\]+(?:\\.*)?$/.test(normalized)) {
return normalized;
}
return null;
}
export async function revealHistoryEntry(
request: HistoryRevealRequest,
dependencies: HistoryRevealDependencies
): Promise<HistoryRevealResult> {
if (
typeof request.entryId !== "string"
|| request.entryId.length === 0
|| request.entryId.length > 256
|| request.entryId.trim() !== request.entryId
) {
return { ok: false, reason: "entry-not-found" };
}
const entries = await dependencies.loadHistory();
const entry = entries.find((candidate) => candidate.id === request.entryId);
if (!entry) {
return { ok: false, reason: "entry-not-found" };
}
const normalizedDirectory = normalizeHistoryDirectory(entry.outputDir);
if (!normalizedDirectory) {
return { ok: false, reason: "invalid-output-dir" };
}
let stat: HistoryRevealStat;
try {
stat = await dependencies.stat(normalizedDirectory);
} catch (error) {
const code = typeof error === "object" && error !== null && "code" in error
? (error as { code?: unknown }).code
: undefined;
return { ok: false, reason: code === "ENOENT" || code === "ENOTDIR" ? "output-dir-missing" : "open-failed" };
}
if (!stat.isDirectory()) {
return { ok: false, reason: "output-dir-not-directory" };
}
try {
const error = await dependencies.openPath(normalizedDirectory);
return error === "" ? { ok: true } : { ok: false, reason: "open-failed" };
} catch {
return { ok: false, reason: "open-failed" };
}
}
+13 -5
View File
@@ -9,7 +9,8 @@ import { getRecentErrors } from "./error-ring";
import { sendNotification } from "./notify";
import { APP_NAME } from "./constants";
import { extractHttpLinksFromText } from "./utils";
import { cleanupStaleSubstDrives, shutdownDaemon } from "./extractor";
import { cleanupStaleSubstDrives, shutdownDaemon } from "./extractor";
import { revealHistoryEntry } from "./history-reveal";
function validateString(value: unknown, name: string): string {
if (typeof value !== "string") {
@@ -506,10 +507,17 @@ function registerIpcHandlers(): void {
});
ipcMain.handle(IPC_CHANNELS.GET_HISTORY, () => controller.getHistory());
ipcMain.handle(IPC_CHANNELS.CLEAR_HISTORY, () => controller.clearHistory());
ipcMain.handle(IPC_CHANNELS.REMOVE_HISTORY_ENTRY, (_event: IpcMainInvokeEvent, entryId: string) => {
validateString(entryId, "entryId");
return controller.removeHistoryEntry(entryId);
});
ipcMain.handle(IPC_CHANNELS.REMOVE_HISTORY_ENTRY, (_event: IpcMainInvokeEvent, entryId: string) => {
validateString(entryId, "entryId");
return controller.removeHistoryEntry(entryId);
});
ipcMain.handle(IPC_CHANNELS.REVEAL_HISTORY_ENTRY, (_event: IpcMainInvokeEvent, entryId: unknown) => {
return revealHistoryEntry({ entryId }, {
loadHistory: () => controller.getHistory(),
stat: (directory) => fs.promises.stat(directory),
openPath: (directory) => shell.openPath(directory)
});
});
ipcMain.handle(IPC_CHANNELS.EXPORT_QUEUE, async () => {
const options = {
defaultPath: `rd-queue-export.json`,