This commit is contained in:
lincube
2026-02-13 23:21:17 +08:00
parent ef1ccd439b
commit aa0154db25
9 changed files with 3855 additions and 601 deletions

View File

@@ -3,8 +3,8 @@ const electron = require("electron");
const path = require("path");
const utils = require("@electron-toolkit/utils");
const elysia = require("elysia");
const fs = require("fs");
const child_process = require("child_process");
const fs = require("fs");
const util = require("util");
const node = require("@elysiajs/node");
const icon = path.join(__dirname, "../../resources/icon.png");
@@ -20,7 +20,7 @@ function getStartMenuRoots() {
const { userProgramsPath, commonProgramsPath } = getStartMenuPaths();
return [userProgramsPath, commonProgramsPath].filter((p) => Boolean(p));
}
const execFileAsync$1 = util.promisify(child_process.execFile);
const execFileAsync$2 = util.promisify(child_process.execFile);
function getWindowsPowerShellExe() {
const systemRoot = process.env["SystemRoot"] ?? process.env["WINDIR"] ?? "C:\\Windows";
return path.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
@@ -124,7 +124,7 @@ async function listWindowsStartMenuApps() {
const roots = getStartMenuRoots();
const script = buildPowerShellScript(roots);
const powershellExe = getWindowsPowerShellExe();
const { stdout } = await execFileAsync$1(
const { stdout } = await execFileAsync$2(
powershellExe,
["-NoProfile", "-NonInteractive", "-Sta", "-ExecutionPolicy", "Bypass", "-Command", script],
{ windowsHide: true, maxBuffer: 50 * 1024 * 1024, timeout: 6e4 }
@@ -157,7 +157,7 @@ async function listWindowsStartMenuApps() {
result.sort((a, b) => a.name.localeCompare(b.name, "zh-CN"));
return result;
}
const execFileAsync = util.promisify(child_process.execFile);
const execFileAsync$1 = util.promisify(child_process.execFile);
function isUnderRoot(filePath, root) {
const normalizedFile = path.resolve(filePath).toLowerCase();
const normalizedRoot = path.resolve(root).toLowerCase();
@@ -166,7 +166,7 @@ function isUnderRoot(filePath, root) {
async function launchStartMenuEntry(filePath) {
if (process.platform !== "win32") return;
if (filePath.startsWith("shell:AppsFolder\\")) {
await execFileAsync("explorer.exe", [filePath], { windowsHide: true });
await execFileAsync$1("explorer.exe", [filePath], { windowsHide: true });
return;
}
const roots = getStartMenuRoots();
@@ -179,6 +179,7 @@ async function launchStartMenuEntry(filePath) {
throw new Error(result);
}
}
const execFileAsync = util.promisify(child_process.execFile);
function createEiysiaApp(deps) {
const iconCache = /* @__PURE__ */ new Map();
const appsCacheFilePath = path.join(electron.app.getPath("userData"), "apps-cache.json");
@@ -328,6 +329,27 @@ function createEiysiaApp(deps) {
if (message === "PathNotAllowed") return new Response("Forbidden", { status: 403 });
return new Response("LaunchFailed", { status: 500 });
}
}).post("/open/external", async ({ body }) => {
const payload = body;
if (typeof payload.url !== "string") {
return new Response("BadRequest", { status: 400 });
}
const url = payload.url.trim();
if (!url) return new Response("BadRequest", { status: 400 });
const lower = url.toLowerCase();
if (lower.startsWith("javascript:") || lower.startsWith("data:") || lower.startsWith("file:")) {
return new Response("Forbidden", { status: 403 });
}
try {
if (process.platform === "win32" && lower.startsWith("shell:")) {
await execFileAsync("explorer.exe", [url], { windowsHide: true });
return { ok: true };
}
await electron.shell.openExternal(url);
return { ok: true };
} catch {
return new Response("OpenFailed", { status: 500 });
}
}).get("/backend/port", () => ({
port: deps.getHttpPort()
})).post("/app/minimize", () => {

File diff suppressed because it is too large Load Diff

View File

@@ -1,450 +0,0 @@
:root {
--ev-c-white: #ffffff;
--ev-c-white-soft: #f8f8f8;
--ev-c-white-mute: #f2f2f2;
--ev-c-black: #1b1b1f;
--ev-c-black-soft: #222222;
--ev-c-black-mute: #282828;
--ev-c-gray-1: #515c67;
--ev-c-gray-2: #414853;
--ev-c-gray-3: #32363f;
--ev-c-text-1: rgba(255, 255, 245, 0.86);
--ev-c-text-2: rgba(235, 235, 245, 0.6);
--ev-c-text-3: rgba(235, 235, 245, 0.38);
--ev-button-alt-border: transparent;
--ev-button-alt-text: var(--ev-c-text-1);
--ev-button-alt-bg: var(--ev-c-gray-3);
--ev-button-alt-hover-border: transparent;
--ev-button-alt-hover-text: var(--ev-c-text-1);
--ev-button-alt-hover-bg: var(--ev-c-gray-2);
}
:root {
--color-background: var(--ev-c-black);
--color-background-soft: var(--ev-c-black-soft);
--color-background-mute: var(--ev-c-black-mute);
--color-text: var(--ev-c-text-1);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
ul {
list-style: none;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
line-height: 1.6;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
margin: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
background-image: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201422%20800'%20opacity='0.3'%3e%3cdefs%3e%3clinearGradient%20x1='50%25'%20y1='0%25'%20x2='50%25'%20y2='100%25'%20id='oooscillate-grad'%3e%3cstop%20stop-color='hsl(206,%2075%25,%2049%25)'%20stop-opacity='1'%20offset='0%25'%3e%3c/stop%3e%3cstop%20stop-color='hsl(331,%2090%25,%2056%25)'%20stop-opacity='1'%20offset='100%25'%3e%3c/stop%3e%3c/linearGradient%3e%3c/defs%3e%3cg%20stroke-width='1'%20stroke='url(%23oooscillate-grad)'%20fill='none'%20stroke-linecap='round'%3e%3cpath%20d='M%200%20448%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20448'%20opacity='0.05'%3e%3c/path%3e%3cpath%20d='M%200%20420%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20420'%20opacity='0.11'%3e%3c/path%3e%3cpath%20d='M%200%20392%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20392'%20opacity='0.18'%3e%3c/path%3e%3cpath%20d='M%200%20364%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20364'%20opacity='0.24'%3e%3c/path%3e%3cpath%20d='M%200%20336%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20336'%20opacity='0.30'%3e%3c/path%3e%3cpath%20d='M%200%20308%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20308'%20opacity='0.37'%3e%3c/path%3e%3cpath%20d='M%200%20280%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20280'%20opacity='0.43'%3e%3c/path%3e%3cpath%20d='M%200%20252%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20252'%20opacity='0.49'%3e%3c/path%3e%3cpath%20d='M%200%20224%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20224'%20opacity='0.56'%3e%3c/path%3e%3cpath%20d='M%200%20196%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20196'%20opacity='0.62'%3e%3c/path%3e%3cpath%20d='M%200%20168%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20168'%20opacity='0.68'%3e%3c/path%3e%3cpath%20d='M%200%20140%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20140'%20opacity='0.75'%3e%3c/path%3e%3cpath%20d='M%200%20112%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%20112'%20opacity='0.81'%3e%3c/path%3e%3cpath%20d='M%200%2084%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%2084'%20opacity='0.87'%3e%3c/path%3e%3cpath%20d='M%200%2056%20Q%20355.5%20-100%20711%20400%20Q%201066.5%20900%201422%2056'%20opacity='0.94'%3e%3c/path%3e%3c/g%3e%3c/svg%3e");
background-size: cover;
user-select: none;
}
#root {
width: 100%;
height: 100%;
}
.screen {
width: 100%;
height: 100%;
}
.touchButton {
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
.launcher {
position: fixed;
left: 16px;
top: 84px;
width: 520px;
height: calc(100vh - 168px);
padding: 12px;
background: rgba(0, 0, 0, 0.28);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 14px;
backdrop-filter: blur(12px);
box-sizing: border-box;
}
.home {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.openAppsButton {
cursor: pointer;
border-radius: 18px;
padding: 20px 28px;
border: 1px solid rgba(255, 255, 255, 0.16);
color: var(--ev-c-text-1);
background: rgba(0, 0, 0, 0.35);
backdrop-filter: blur(12px);
font-size: 22px;
line-height: 26px;
font-weight: 800;
}
.openAppsButton:hover {
border-color: rgba(255, 255, 255, 0.26);
background: rgba(0, 0, 0, 0.45);
}
.appsPage {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding: 16px;
box-sizing: border-box;
}
.backButton {
cursor: pointer;
border-radius: 16px;
padding: 0 18px;
border: 1px solid rgba(255, 255, 255, 0.12);
color: var(--ev-c-text-1);
background: rgba(0, 0, 0, 0.35);
font-size: 18px;
line-height: 22px;
font-weight: 800;
height: 72px;
min-width: 120px;
}
.backButton:hover {
border-color: rgba(255, 255, 255, 0.22);
background: rgba(0, 0, 0, 0.45);
}
.appsTilesArea {
position: fixed;
left: 16px;
right: 16px;
top: 88px;
bottom: 120px;
padding: 12px;
background: rgba(0, 0, 0, 0.28);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 14px;
backdrop-filter: blur(12px);
box-sizing: border-box;
overflow: hidden;
}
.appsList {
height: 100%;
overflow-x: auto;
overflow-y: hidden;
padding: 4px 6px;
box-sizing: border-box;
columns: 6 280px;
column-gap: 14px;
column-fill: auto;
touch-action: pan-x;
-webkit-overflow-scrolling: touch;
overscroll-behavior-x: contain;
scrollbar-width: none;
-ms-overflow-style: none;
}
.appsList::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
.appsLoading {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 700;
opacity: 0.9;
}
.appsBottomBar {
position: fixed;
left: 16px;
right: 16px;
bottom: 16px;
height: 92px;
padding: 10px 12px;
display: grid;
grid-template-columns: 140px 1fr 140px;
gap: 12px;
align-items: center;
background: rgba(0, 0, 0, 0.35);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 16px;
backdrop-filter: blur(12px);
box-sizing: border-box;
}
.appsSearch {
width: 100%;
height: 72px;
border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(0, 0, 0, 0.35);
color: var(--ev-c-text-1);
padding: 0 16px;
box-sizing: border-box;
outline: none;
font-size: 20px;
line-height: 24px;
user-select: text;
}
.appsExitButton {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
cursor: pointer;
border-radius: 16px;
padding: 0 18px;
border: 1px solid rgba(255, 255, 255, 0.12);
color: var(--ev-c-text-1);
background: rgba(0, 0, 0, 0.35);
font-size: 18px;
line-height: 22px;
font-weight: 800;
height: 72px;
min-width: 120px;
}
.appsExitButton:hover {
border-color: rgba(255, 255, 255, 0.22);
background: rgba(0, 0, 0, 0.45);
}
.search {
width: 100%;
height: 38px;
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(0, 0, 0, 0.35);
color: var(--ev-c-text-1);
padding: 0 12px;
box-sizing: border-box;
outline: none;
}
.error {
margin-top: 10px;
padding: 10px 12px;
border-radius: 12px;
border: 1px solid rgba(255, 120, 120, 0.25);
background: rgba(120, 0, 0, 0.18);
color: var(--ev-c-text-1);
font-size: 12px;
line-height: 16px;
user-select: text;
white-space: pre-wrap;
word-break: break-word;
}
.errorHeader {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-bottom: 8px;
}
.errorTitle {
font-weight: 700;
font-size: 12px;
line-height: 16px;
}
.errorBody {
white-space: pre-wrap;
word-break: break-word;
}
.copyButton {
cursor: pointer;
border-radius: 10px;
padding: 6px 10px;
border: 1px solid rgba(255, 255, 255, 0.16);
background: rgba(0, 0, 0, 0.25);
color: var(--ev-c-text-1);
font-size: 12px;
line-height: 14px;
}
.copyButton:hover {
border-color: rgba(255, 255, 255, 0.26);
background: rgba(0, 0, 0, 0.35);
}
.list {
margin-top: 12px;
height: calc(100% - 50px);
overflow: auto;
display: grid;
gap: 10px;
}
.groupHeader {
display: inline-block;
width: 100%;
box-sizing: border-box;
margin: 0 0 10px;
padding: 6px 10px;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(0, 0, 0, 0.2);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.4px;
opacity: 0.9;
break-inside: avoid;
-webkit-column-break-inside: avoid;
}
.item {
display: inline-flex;
align-items: center;
gap: 10px;
text-align: left;
cursor: pointer;
width: 100%;
box-sizing: border-box;
min-height: 72px;
padding: 12px 14px;
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(0, 0, 0, 0.25);
color: var(--ev-c-text-1);
margin: 0 0 10px;
break-inside: avoid;
-webkit-column-break-inside: avoid;
}
.item:hover {
border-color: rgba(255, 255, 255, 0.22);
background: rgba(0, 0, 0, 0.35);
}
.item:active {
border-color: rgba(255, 255, 255, 0.26);
background: rgba(0, 0, 0, 0.5);
}
.name {
font-weight: 700;
font-size: 18px;
line-height: 22px;
}
.icon {
width: 48px;
height: 48px;
border-radius: 10px;
flex: 0 0 auto;
}
.path {
margin-top: 4px;
font-size: 12px;
line-height: 16px;
opacity: 0.75;
word-break: break-all;
}
.clock {
position: fixed;
left: 16px;
top: 16px;
padding: 10px 12px;
font-size: 28px;
line-height: 28px;
font-weight: 700;
color: var(--ev-c-text-1);
background: rgba(0, 0, 0, 0.35);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 12px;
backdrop-filter: blur(12px);
}
.exitButton {
position: fixed;
right: 16px;
bottom: 16px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
cursor: pointer;
text-align: center;
font-weight: 600;
border-radius: 14px;
padding: 10px 16px;
line-height: 20px;
font-size: 14px;
border: 1px solid rgba(255, 255, 255, 0.12);
color: var(--ev-c-text-1);
background: rgba(0, 0, 0, 0.35);
backdrop-filter: blur(12px);
}
.buttonIcon {
width: 20px;
height: 20px;
flex: 0 0 auto;
}
.exitButton:hover {
border-color: rgba(255, 255, 255, 0.22);
background: rgba(0, 0, 0, 0.45);
}

View File

@@ -8,8 +8,8 @@
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
/>
<script type="module" crossorigin src="./assets/index-C9aAt2YI.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-DAQiHmWm.css">
<script type="module" crossorigin src="./assets/index-CkK6wThO.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BOqh2SqZ.css">
</head>
<body>