Upload via GUI (85 Dateien)
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; script-src 'self'">
|
||||
<title>Git Manager</title>
|
||||
<style>
|
||||
html, body { margin: 0; height: 100%; overflow: hidden; background: transparent; user-select: none; cursor: default; }
|
||||
body { font-family: "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif; }
|
||||
|
||||
/* Logo und Schriftzug in der Mitte */
|
||||
.marke {
|
||||
position: fixed; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
|
||||
transition: opacity .28s ease, transform .32s ease;
|
||||
}
|
||||
.buehne { perspective: 700px; animation: rein .45s cubic-bezier(.2, .9, .3, 1.2) both; }
|
||||
.logo {
|
||||
width: 132px; height: 132px; display: block; object-fit: contain;
|
||||
filter: drop-shadow(0 10px 26px rgba(0, 0, 0, .55)) drop-shadow(0 0 22px rgba(90, 160, 255, .35));
|
||||
animation: drehen 1.3s cubic-bezier(.45, .05, .25, 1) .15s infinite;
|
||||
}
|
||||
.name {
|
||||
font-size: 34px; font-weight: 600; letter-spacing: .06em;
|
||||
background: linear-gradient(90deg, #7fe3ff, #6c9cff); -webkit-background-clip: text; background-clip: text; color: transparent;
|
||||
filter: drop-shadow(0 2px 8px rgba(0, 0, 0, .8));
|
||||
animation: schrift .5s ease .25s both;
|
||||
}
|
||||
@keyframes rein { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
|
||||
@keyframes drehen { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } }
|
||||
@keyframes schrift { from { opacity: 0; transform: translateY(8px); letter-spacing: .3em; } to { opacity: 1; transform: none; letter-spacing: .06em; } }
|
||||
|
||||
/* das fertige Fenster als Bild, wächst von der Mitte nach außen */
|
||||
#fenster { position: fixed; inset: 0; width: 100%; height: 100%; visibility: hidden; }
|
||||
body.aufbau .marke { opacity: 0; transform: scale(.82); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="marke">
|
||||
<div class="buehne"><img class="logo" src="./icon.png" alt=""></div>
|
||||
<div class="name">Git Manager</div>
|
||||
</div>
|
||||
<img id="fenster" alt="">
|
||||
<script src="./splash.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,19 @@
|
||||
// Vom Hauptprozess aufgerufen: das Bild des fertigen Fensters von der Mitte aus aufziehen.
|
||||
// Liefert true, wenn die Animation durchgelaufen ist, sonst false.
|
||||
window.aufbauen = (bildAdresse) => new Promise((fertig) => {
|
||||
const bild = document.getElementById('fenster');
|
||||
bild.onerror = () => fertig(false);
|
||||
bild.onload = () => {
|
||||
const v = Math.max(0, innerHeight / 2 - 66);
|
||||
const h = Math.max(0, innerWidth / 2 - 66);
|
||||
bild.style.visibility = 'visible';
|
||||
document.body.classList.add('aufbau');
|
||||
bild.animate([
|
||||
{ clipPath: `inset(${v}px ${h}px round 30px)`, opacity: 0.2 },
|
||||
{ opacity: 1, offset: 0.25 },
|
||||
{ clipPath: 'inset(0px 0px round 0px)', opacity: 1 }
|
||||
], { duration: 560, easing: 'cubic-bezier(.2, .8, .2, 1)', fill: 'forwards' })
|
||||
.finished.then(() => fertig(true), () => fertig(false));
|
||||
};
|
||||
bild.src = bildAdresse;
|
||||
});
|
||||
@@ -4576,3 +4576,7 @@ select option:checked { background: #2d4ea4; color: #ffffff; }
|
||||
color: #04101f !important;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
.upload-history-row { padding: 6px 8px; border-radius: 8px; cursor: pointer; }
|
||||
.upload-history-row:hover { background: rgba(88, 213, 255, 0.14); }
|
||||
.upload-history-err { opacity: 0.75; padding-left: 22px; }
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; script-src 'self'">
|
||||
<title>Git Manager Menü</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0f1a2e;
|
||||
--fg: #e8eefc;
|
||||
--muted: #8fa0c0;
|
||||
--hover: rgba(88, 213, 255, 0.16);
|
||||
--border: rgba(88, 213, 255, 0.24);
|
||||
--sep: rgba(138, 164, 214, 0.22);
|
||||
--accent: #67e8f9;
|
||||
}
|
||||
body.light {
|
||||
--bg: #f7f9fd;
|
||||
--fg: #16233d;
|
||||
--muted: #6a7a99;
|
||||
--hover: rgba(40, 110, 220, 0.12);
|
||||
--border: rgba(30, 60, 110, 0.2);
|
||||
--sep: rgba(30, 60, 110, 0.14);
|
||||
--accent: #1d6fe0;
|
||||
}
|
||||
html, body {
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
color: var(--fg);
|
||||
font: 13px "Segoe UI Variable Text", "Segoe UI", Arial, sans-serif;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
body { padding: 8px; }
|
||||
#menu {
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 6px;
|
||||
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
.header { font-weight: 700; padding: 8px 12px 2px; }
|
||||
.status { color: var(--muted); font-size: 12px; padding: 2px 12px; }
|
||||
.sep { height: 1px; background: var(--sep); margin: 6px 4px; }
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
cursor: default;
|
||||
outline: none;
|
||||
}
|
||||
.item:hover:not(:disabled), .item.active:not(:disabled) { background: var(--hover); }
|
||||
.item:disabled { color: var(--muted); opacity: 0.6; }
|
||||
.check { width: 14px; flex: 0 0 14px; text-align: center; color: var(--accent); font-weight: 700; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="menu" role="menu"></div>
|
||||
<script src="./tray-menu.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,80 @@
|
||||
// Zeichnet das Tray-Menü aus dem Zustand, den der Hauptprozess schickt.
|
||||
// Ohne Electron (Seite direkt im Browser geöffnet) greift ein Stub, damit sich die Optik prüfen lässt.
|
||||
(function () {
|
||||
const api = window.trayApi || {
|
||||
onState: () => {},
|
||||
action: (id) => console.log('action', id),
|
||||
resize: () => {},
|
||||
close: () => {}
|
||||
};
|
||||
|
||||
const menu = document.getElementById('menu');
|
||||
let buttons = [];
|
||||
let activeIndex = -1;
|
||||
|
||||
function setActive(index) {
|
||||
activeIndex = index;
|
||||
buttons.forEach((b, i) => b.classList.toggle('active', i === index));
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.body.classList.toggle('light', state && state.dark === false);
|
||||
menu.textContent = '';
|
||||
buttons = [];
|
||||
activeIndex = -1;
|
||||
|
||||
for (const item of (state && state.items) || []) {
|
||||
if (item.type === 'separator') {
|
||||
const sep = document.createElement('div');
|
||||
sep.className = 'sep';
|
||||
menu.appendChild(sep);
|
||||
continue;
|
||||
}
|
||||
if (item.id === 'header' || item.id === 'status' || item.id === 'queue') {
|
||||
const line = document.createElement('div');
|
||||
line.className = item.id === 'header' ? 'header' : 'status';
|
||||
line.textContent = item.label;
|
||||
menu.appendChild(line);
|
||||
continue;
|
||||
}
|
||||
const button = document.createElement('button');
|
||||
button.className = 'item';
|
||||
button.disabled = item.enabled === false;
|
||||
button.setAttribute('role', item.type === 'checkbox' ? 'menuitemcheckbox' : 'menuitem');
|
||||
if (item.type === 'checkbox') button.setAttribute('aria-checked', String(!!item.checked));
|
||||
|
||||
const check = document.createElement('span');
|
||||
check.className = 'check';
|
||||
check.textContent = item.type === 'checkbox' && item.checked ? '✓' : '';
|
||||
const label = document.createElement('span');
|
||||
label.textContent = item.label;
|
||||
button.append(check, label);
|
||||
|
||||
button.addEventListener('click', () => api.action(item.id));
|
||||
button.addEventListener('mouseenter', () => { if (!button.disabled) setActive(buttons.indexOf(button)); });
|
||||
button.addEventListener('mouseleave', () => setActive(-1));
|
||||
menu.appendChild(button);
|
||||
buttons.push(button);
|
||||
}
|
||||
|
||||
api.resize(Math.ceil(document.body.scrollHeight));
|
||||
}
|
||||
|
||||
function move(step) {
|
||||
const enabled = buttons.map((b, i) => (b.disabled ? -1 : i)).filter((i) => i >= 0);
|
||||
if (enabled.length === 0) return;
|
||||
const pos = enabled.indexOf(activeIndex);
|
||||
const next = pos < 0 ? (step > 0 ? 0 : enabled.length - 1) : (pos + step + enabled.length) % enabled.length;
|
||||
setActive(enabled[next]);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') api.close();
|
||||
else if (e.key === 'ArrowDown') { e.preventDefault(); move(1); }
|
||||
else if (e.key === 'ArrowUp') { e.preventDefault(); move(-1); }
|
||||
else if ((e.key === 'Enter' || e.key === ' ') && buttons[activeIndex]) { e.preventDefault(); buttons[activeIndex].click(); }
|
||||
});
|
||||
|
||||
window.__renderTray = render;
|
||||
api.onState(render);
|
||||
})();
|
||||
Reference in New Issue
Block a user