Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c143053319 | ||
|
|
58709e09f2 | ||
|
|
27091ab5d1 | ||
|
|
6a6971e1cb | ||
|
|
edea4ce0d2 | ||
|
|
b431428260 | ||
|
|
aeb6c590db | ||
|
|
428e74b2d8 |
@@ -5,6 +5,7 @@ import android.view.View;
|
|||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
|
||||||
import androidx.activity.OnBackPressedCallback;
|
import androidx.activity.OnBackPressedCallback;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
@@ -25,13 +26,19 @@ public class MainActivity extends BridgeActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Edge-to-Edge: Bei offener Tastatur den WebView um die Tastaturhöhe verkleinern,
|
// Edge-to-Edge: Ränder für Status- und Navigationsleiste setzt diese Ansicht. Den Platz für die Tastatur
|
||||||
// damit Terminal und Zusatztasten sichtbar bleiben
|
// schafft Android/WebView selbst – hier nur melden, ob sie offen ist (sonst würde doppelt verkleinert).
|
||||||
View parent = (View) web.getParent();
|
View parent = (View) web.getParent();
|
||||||
|
parent.setBackgroundColor(0xFF14161D);
|
||||||
|
final boolean[] imeOpen = { false };
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(parent, (v, insets) -> {
|
ViewCompat.setOnApplyWindowInsetsListener(parent, (v, insets) -> {
|
||||||
int ime = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
|
Insets bars = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
||||||
v.setPadding(0, 0, 0, ime);
|
boolean open = insets.isVisible(WindowInsetsCompat.Type.ime());
|
||||||
web.evaluateJavascript("window.mrtermIme && window.mrtermIme(" + (ime > 0) + ")", null);
|
v.setPadding(bars.left, bars.top, bars.right, open ? 0 : bars.bottom);
|
||||||
|
if (open != imeOpen[0]) {
|
||||||
|
imeOpen[0] = open;
|
||||||
|
web.evaluateJavascript("window.mrtermIme && window.mrtermIme(" + open + ")", null);
|
||||||
|
}
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,6 +216,23 @@ public class MrTermNative extends Plugin {
|
|||||||
call.resolve();
|
call.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Design: Hintergrund hinter Status-/Navigationsleiste und dunkle bzw. helle Symbole
|
||||||
|
@PluginMethod
|
||||||
|
public void bars(PluginCall call) {
|
||||||
|
final boolean light = Boolean.TRUE.equals(call.getBoolean("light", false));
|
||||||
|
final String color = call.getString("color", "#14161d");
|
||||||
|
getActivity().runOnUiThread(() -> {
|
||||||
|
try {
|
||||||
|
android.view.View parent = (android.view.View) getBridge().getWebView().getParent();
|
||||||
|
parent.setBackgroundColor(android.graphics.Color.parseColor(color));
|
||||||
|
androidx.core.view.WindowInsetsControllerCompat c = androidx.core.view.WindowCompat.getInsetsController(getActivity().getWindow(), parent);
|
||||||
|
c.setAppearanceLightStatusBars(light);
|
||||||
|
c.setAppearanceLightNavigationBars(light);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
});
|
||||||
|
call.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
@PluginMethod
|
@PluginMethod
|
||||||
public void background(PluginCall call) {
|
public void background(PluginCall call) {
|
||||||
getActivity().runOnUiThread(() -> getActivity().moveTaskToBack(true));
|
getActivity().runOnUiThread(() -> getActivity().moveTaskToBack(true));
|
||||||
|
|||||||
@@ -53,8 +53,10 @@ function buildWeb() {
|
|||||||
copy(path.join(nm, 'xterm', 'lib', 'xterm.js'), path.join(WWW, 'lib', 'xterm.js'));
|
copy(path.join(nm, 'xterm', 'lib', 'xterm.js'), path.join(WWW, 'lib', 'xterm.js'));
|
||||||
copy(path.join(nm, 'xterm', 'css', 'xterm.css'), path.join(WWW, 'lib', 'xterm.css'));
|
copy(path.join(nm, 'xterm', 'css', 'xterm.css'), path.join(WWW, 'lib', 'xterm.css'));
|
||||||
copy(path.join(nm, 'addon-fit', 'lib', 'addon-fit.js'), path.join(WWW, 'lib', 'addon-fit.js'));
|
copy(path.join(nm, 'addon-fit', 'lib', 'addon-fit.js'), path.join(WWW, 'lib', 'addon-fit.js'));
|
||||||
|
copy(path.join(__dirname, 'node_modules', '@capacitor', 'core', 'dist', 'capacitor.js'), path.join(WWW, 'lib', 'capacitor.js'));
|
||||||
copy(path.join(ROOT, 'src', 'i18n.js'), path.join(WWW, 'lib', 'i18n.js'));
|
copy(path.join(ROOT, 'src', 'i18n.js'), path.join(WWW, 'lib', 'i18n.js'));
|
||||||
copy(path.join(ROOT, 'src', 'renderer', 'themes.js'), path.join(WWW, 'lib', 'themes.js'));
|
copy(path.join(ROOT, 'src', 'renderer', 'themes.js'), path.join(WWW, 'lib', 'themes.js'));
|
||||||
|
copy(path.join(ROOT, 'src', 'renderer', 'app-themes.css'), path.join(WWW, 'lib', 'app-themes.css'));
|
||||||
copy(path.join(ROOT, 'src', 'renderer', 'logo.png'), path.join(WWW, 'logo.png'));
|
copy(path.join(ROOT, 'src', 'renderer', 'logo.png'), path.join(WWW, 'logo.png'));
|
||||||
|
|
||||||
// Node-Backend inkl. ssh2 in eine Datei bündeln (nodejs-mobile = Node 18)
|
// Node-Backend inkl. ssh2 in eine Datei bündeln (nodejs-mobile = Node 18)
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ contextBridge.exposeInMainWorld('DevBridge', {
|
|||||||
send: ({ eventName, args }) => ipcRenderer.send('dev:send', eventName, args),
|
send: ({ eventName, args }) => ipcRenderer.send('dev:send', eventName, args),
|
||||||
addListener: (name, fn) => { if (!listeners.has(name)) listeners.set(name, new Set()); listeners.get(name).add(fn); return { remove: () => listeners.get(name).delete(fn) }; },
|
addListener: (name, fn) => { if (!listeners.has(name)) listeners.set(name, new Set()); listeners.get(name).add(fn); return { remove: () => listeners.get(name).delete(fn) }; },
|
||||||
},
|
},
|
||||||
Native: Object.fromEntries(['vaultKey', 'info', 'bioAvailable', 'bioEnroll', 'bioUnlock', 'bioDisable', 'multicast', 'copy', 'paste', 'background'].map((m) => [m, native(m)])),
|
Native: Object.fromEntries(['vaultKey', 'info', 'bioAvailable', 'bioEnroll', 'bioUnlock', 'bioDisable', 'multicast', 'copy', 'paste', 'background', 'bars'].map((m) => [m, native(m)])),
|
||||||
});
|
});
|
||||||
|
|||||||
+51
-10
@@ -193,10 +193,12 @@ async function reload() {
|
|||||||
S.lock = await api.call('lock:status');
|
S.lock = await api.call('lock:status');
|
||||||
I18N.setLanguage(S.lock.meta.language || 'auto', S.info.locale);
|
I18N.setLanguage(S.lock.meta.language || 'auto', S.info.locale);
|
||||||
applyStatic();
|
applyStatic();
|
||||||
|
applyTheme(S.lock.meta);
|
||||||
if (S.lock.locked) return showLock();
|
if (S.lock.locked) return showLock();
|
||||||
S.vault = await api.call('vault:get');
|
S.vault = await api.call('vault:get');
|
||||||
I18N.setLanguage(settings().language || 'auto', S.info.locale);
|
I18N.setLanguage(settings().language || 'auto', S.info.locale);
|
||||||
applyStatic();
|
applyStatic();
|
||||||
|
applyTheme();
|
||||||
S.sync = await api.call('sync:status').catch(() => null);
|
S.sync = await api.call('sync:status').catch(() => null);
|
||||||
$('#main').hidden = false;
|
$('#main').hidden = false;
|
||||||
render();
|
render();
|
||||||
@@ -410,7 +412,33 @@ const KEYS = [
|
|||||||
];
|
];
|
||||||
const mods = { ctrl: 0, alt: 0 }; // 0 aus, 1 einmal, 2 festgestellt
|
const mods = { ctrl: 0, alt: 0 }; // 0 aus, 1 einmal, 2 festgestellt
|
||||||
|
|
||||||
function termTheme() { return TERM_THEMES[settings().terminalTheme] || TERM_THEMES.mrterm; }
|
function termTheme() {
|
||||||
|
const id = settings().terminalTheme;
|
||||||
|
if (!id || id === 'auto') return TERM_THEMES[(APP_THEMES[settings().appTheme] || APP_THEMES.midnight).term] || TERM_THEMES.mrterm;
|
||||||
|
return TERM_THEMES[id] || TERM_THEMES.mrterm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// App-Design (gemeinsam mit dem Desktop: lib/app-themes.css + APP_THEMES)
|
||||||
|
function applyTheme(st = settings()) {
|
||||||
|
const root = document.documentElement;
|
||||||
|
const t = APP_THEMES[st.appTheme] || APP_THEMES.midnight;
|
||||||
|
if (st.appTheme && st.appTheme !== 'midnight' && APP_THEMES[st.appTheme]) root.dataset.theme = st.appTheme; else delete root.dataset.theme;
|
||||||
|
if (st.accent) root.style.setProperty('--accent', st.accent); else root.style.removeProperty('--accent');
|
||||||
|
root.classList.toggle('light', !!t.light);
|
||||||
|
S.sessions?.forEach((x) => { x.term.options.theme = termTheme(); });
|
||||||
|
document.documentElement.style.setProperty('--term-bg', termTheme().background);
|
||||||
|
syncBars();
|
||||||
|
}
|
||||||
|
// Statusleiste passend zur sichtbaren Fläche (Terminal oder App)
|
||||||
|
function syncBars() {
|
||||||
|
const t = APP_THEMES[settings().appTheme] || APP_THEMES.midnight;
|
||||||
|
const inTerm = !$('#termScreen').hidden;
|
||||||
|
const bg = inTerm ? getComputedStyle(document.querySelector('.term-head')).backgroundColor : getComputedStyle(document.body).backgroundColor;
|
||||||
|
const rgb = bg.match(/\d+/g)?.map(Number) || [20, 22, 29];
|
||||||
|
const hex = '#' + rgb.slice(0, 3).map((n) => n.toString(16).padStart(2, '0')).join('');
|
||||||
|
const light = inTerm ? (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000 > 150 : !!t.light;
|
||||||
|
Native.bars?.({ light, color: hex }).catch(() => {});
|
||||||
|
}
|
||||||
const fontSize = () => Number(settings().mobileFontSize) || 12;
|
const fontSize = () => Number(settings().mobileFontSize) || 12;
|
||||||
|
|
||||||
class Session {
|
class Session {
|
||||||
@@ -537,6 +565,7 @@ function showSession(s) {
|
|||||||
$('#termScreen').hidden = false;
|
$('#termScreen').hidden = false;
|
||||||
$('#main').hidden = true;
|
$('#main').hidden = true;
|
||||||
document.documentElement.style.setProperty('--term-bg', termTheme().background);
|
document.documentElement.style.setProperty('--term-bg', termTheme().background);
|
||||||
|
syncBars();
|
||||||
updateTermHead();
|
updateTermHead();
|
||||||
drawKeybar();
|
drawKeybar();
|
||||||
requestAnimationFrame(() => { s.refit(); if (s.alive) s.term.focus(); });
|
requestAnimationFrame(() => { s.refit(); if (s.alive) s.term.focus(); });
|
||||||
@@ -548,6 +577,7 @@ function hideTerminal() {
|
|||||||
S.active?.term.blur();
|
S.active?.term.blur();
|
||||||
S.active = null;
|
S.active = null;
|
||||||
render();
|
render();
|
||||||
|
syncBars();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTermHead() {
|
function updateTermHead() {
|
||||||
@@ -723,20 +753,31 @@ function viewSettings(v) {
|
|||||||
v.append(h(`<div class="top"><h1>${esc(T('Settings'))}</h1></div>`));
|
v.append(h(`<div class="top"><h1>${esc(T('Settings'))}</h1></div>`));
|
||||||
const st = settings();
|
const st = settings();
|
||||||
|
|
||||||
// Sprache & Terminal
|
// Sprache, Design & Terminal
|
||||||
const gen = h(`<div class="card"><h3>${esc(T('General'))}</h3>
|
const gen = h(`<div class="card"><h3>${esc(T('General'))}</h3>
|
||||||
${field(T('Language'), 'language', st.language || 'auto', { type: 'select', options: [['auto', T('System language')], ...Object.entries(I18N.LANGUAGES)] })}
|
${field(T('Language'), 'language', st.language || 'auto', { type: 'select', options: [['auto', T('System language')], ...Object.entries(I18N.LANGUAGES)] })}
|
||||||
${field(T('Terminal color scheme'), 'terminalTheme', st.terminalTheme || 'mrterm', { type: 'select', options: Object.entries(TERM_THEMES).map(([id, t]) => [id, t.name]) })}
|
<div class="field"><label>Design</label><div class="theme-grid"></div></div>
|
||||||
|
<div class="field"><label>${esc(T('Accent color'))}</label><div class="colors"></div></div>
|
||||||
|
${field(T('Terminal color scheme'), 'terminalTheme', st.terminalTheme || 'auto', { type: 'select', options: [['auto', T('Match theme')], ...Object.entries(TERM_THEMES).map(([id, t]) => [id, t.name])] })}
|
||||||
${field(T('Font size'), 'mobileFontSize', fontSize(), { type: 'select', options: [8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20].map((n) => [n, `${n} px`]) })}
|
${field(T('Font size'), 'mobileFontSize', fontSize(), { type: 'select', options: [8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20].map((n) => [n, `${n} px`]) })}
|
||||||
</div>`);
|
</div>`);
|
||||||
$('[name=language]', gen).onchange = async (e) => { await call('vault:settings', { language: e.target.value }); await reload(); };
|
const save = async (patch) => { await call('vault:settings', patch); Object.assign(S.vault.settings, patch); };
|
||||||
$('[name=terminalTheme]', gen).onchange = async (e) => {
|
$('[name=language]', gen).onchange = async (e) => { await save({ language: e.target.value }); await reload(); };
|
||||||
await call('vault:settings', { terminalTheme: e.target.value }); S.vault.settings.terminalTheme = e.target.value;
|
for (const [id, t] of Object.entries(APP_THEMES)) {
|
||||||
S.sessions.forEach((s) => { s.term.options.theme = termTheme(); });
|
const p = h(`<button class="theme-prev ${(st.appTheme || 'midnight') === id ? 'active' : ''}" style="background:${t.bg};color:${t.text}">
|
||||||
};
|
<div class="dp"><i style="background:${t.side}"></i><div><b style="background:${t.card}"><s style="background:${t.accent}"></s></b><b style="background:${t.card}"></b></div></div>${esc(T(t.name))}</button>`);
|
||||||
|
p.onclick = async () => { await save({ appTheme: id }); applyTheme(); render(); };
|
||||||
|
$('.theme-grid', gen).append(p);
|
||||||
|
}
|
||||||
|
['', ...COLORS.slice(0, 6), '#21c7a8', '#cba6f7', '#fcee0a'].forEach((col) => {
|
||||||
|
const b = h(`<button title="${esc(col || T('Theme default'))}" class="${(st.accent || '') === col ? 'active' : ''}" style="background:${col || 'conic-gradient(#6e7bff,#21c7a8,#cba6f7,#ffb454,#6e7bff)'}"></button>`);
|
||||||
|
b.onclick = async () => { await save({ accent: col }); applyTheme(); render(); };
|
||||||
|
$('.colors', gen).append(b);
|
||||||
|
});
|
||||||
|
$('[name=terminalTheme]', gen).onchange = async (e) => { await save({ terminalTheme: e.target.value }); applyTheme(); };
|
||||||
$('[name=mobileFontSize]', gen).onchange = async (e) => {
|
$('[name=mobileFontSize]', gen).onchange = async (e) => {
|
||||||
const n = Number(e.target.value); await call('vault:settings', { mobileFontSize: n }); S.vault.settings.mobileFontSize = n;
|
const n = Number(e.target.value); await save({ mobileFontSize: n });
|
||||||
S.sessions.forEach((s) => { s.term.options.fontSize = n; });
|
S.sessions.forEach((x) => { x.term.options.fontSize = n; });
|
||||||
};
|
};
|
||||||
v.append(gen);
|
v.append(gen);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<meta name="color-scheme" content="dark" />
|
<meta name="color-scheme" content="dark" />
|
||||||
<title>MrTerm</title>
|
<title>MrTerm</title>
|
||||||
<link rel="stylesheet" href="lib/xterm.css" />
|
<link rel="stylesheet" href="lib/xterm.css" />
|
||||||
|
<link rel="stylesheet" href="lib/app-themes.css" />
|
||||||
<link rel="stylesheet" href="styles.css" />
|
<link rel="stylesheet" href="styles.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -38,6 +39,14 @@
|
|||||||
<div id="layer"></div>
|
<div id="layer"></div>
|
||||||
<div id="toasts"></div>
|
<div id="toasts"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Fehler beim Laden sichtbar machen statt endlos den Ladekreis zu zeigen
|
||||||
|
window.addEventListener('error', (e) => {
|
||||||
|
const b = document.getElementById('boot');
|
||||||
|
if (b && !b.hidden) b.innerHTML = '<div style="color:#ff5f6d;padding:24px;text-align:center;font:14px system-ui">' + String(e.message || e.error).replace(/</g, '<') + '</div>';
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<script src="lib/capacitor.js"></script>
|
||||||
<script src="lib/i18n.js"></script>
|
<script src="lib/i18n.js"></script>
|
||||||
<script src="lib/themes.js"></script>
|
<script src="lib/themes.js"></script>
|
||||||
<script src="lib/xterm.js"></script>
|
<script src="lib/xterm.js"></script>
|
||||||
|
|||||||
+58
-25
@@ -1,25 +1,19 @@
|
|||||||
:root {
|
:root {
|
||||||
--bg: #14161d;
|
/* Farben kommen aus lib/app-themes.css (gemeinsam mit dem Desktop, Auswahl über data-theme) */
|
||||||
--surface: #1c1f29;
|
--surface: var(--card);
|
||||||
--surface2: #252936;
|
--surface2: var(--card-hover);
|
||||||
--line: #2c3040;
|
--line: var(--border);
|
||||||
--text: #e6e8ef;
|
--accent-soft: color-mix(in srgb, var(--accent) 16%, transparent);
|
||||||
--muted: #9aa0b4;
|
--r: calc(var(--r) + 4px);
|
||||||
--faint: #5d6377;
|
/* Status-/Navigationsleiste rechnet MainActivity als Rand um den WebView heraus */
|
||||||
--accent: #6e7bff;
|
--top: 0px;
|
||||||
--accent-soft: #6e7bff26;
|
--bottom: 0px;
|
||||||
--green: #3ecf8e;
|
|
||||||
--red: #ff5f6d;
|
|
||||||
--orange: #ffb347;
|
|
||||||
--radius: 14px;
|
|
||||||
/* Capacitor setzt --safe-area-inset-* bei Edge-to-Edge; env() als Rückfall */
|
|
||||||
--top: max(env(safe-area-inset-top, 0px), var(--safe-area-inset-top, 0px));
|
|
||||||
--bottom: max(env(safe-area-inset-bottom, 0px), var(--safe-area-inset-bottom, 0px));
|
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
|
:root.light { color-scheme: light; }
|
||||||
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
|
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
|
||||||
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text); overflow: hidden; }
|
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text); overflow: hidden; }
|
||||||
body { font: 15px/1.4 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; -webkit-user-select: none; user-select: none; overscroll-behavior: none; }
|
body { font: 15px/1.4 var(--font); font-family: var(--font), system-ui, Roboto, sans-serif; -webkit-user-select: none; user-select: none; overscroll-behavior: none; }
|
||||||
[hidden] { display: none !important; }
|
[hidden] { display: none !important; }
|
||||||
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
|
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
|
||||||
input, select, textarea { font: inherit; color: var(--text); -webkit-user-select: text; user-select: text; }
|
input, select, textarea { font: inherit; color: var(--text); -webkit-user-select: text; user-select: text; }
|
||||||
@@ -54,7 +48,7 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
|
|||||||
.section .count { background: var(--surface2); border-radius: 8px; padding: 1px 7px; font-size: 11px; color: var(--faint); }
|
.section .count { background: var(--surface2); border-radius: 8px; padding: 1px 7px; font-size: 11px; color: var(--faint); }
|
||||||
.section svg { width: 16px; height: 16px; }
|
.section svg { width: 16px; height: 16px; }
|
||||||
|
|
||||||
.list { background: var(--surface); border-radius: var(--radius); overflow: hidden; }
|
.list { background: var(--surface); border-radius: var(--r); overflow: hidden; }
|
||||||
.item { display: flex; align-items: center; gap: 12px; padding: 12px 14px; min-height: 62px; position: relative; }
|
.item { display: flex; align-items: center; gap: 12px; padding: 12px 14px; min-height: 62px; position: relative; }
|
||||||
.item + .item::before { content: ''; position: absolute; top: 0; left: 64px; right: 0; border-top: 1px solid var(--line); }
|
.item + .item::before { content: ''; position: absolute; top: 0; left: 64px; right: 0; border-top: 1px solid var(--line); }
|
||||||
.item:active { background: var(--surface2); }
|
.item:active { background: var(--surface2); }
|
||||||
@@ -79,11 +73,11 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
|
|||||||
.empty .avatar svg { width: 28px; height: 28px; }
|
.empty .avatar svg { width: 28px; height: 28px; }
|
||||||
.empty h3 { color: var(--text); margin: 0 0 6px; }
|
.empty h3 { color: var(--text); margin: 0 0 6px; }
|
||||||
|
|
||||||
.fab { position: fixed; right: 18px; bottom: calc(76px + var(--bottom)); width: 58px; height: 58px; border-radius: 18px; background: var(--accent); color: #fff; display: grid; place-items: center; box-shadow: 0 8px 24px #0008; }
|
.fab { position: fixed; right: 18px; bottom: calc(76px + var(--bottom)); width: 58px; height: 58px; border-radius: calc(var(--radius) + 8px); background: var(--accent); color: var(--on-accent); display: grid; place-items: center; box-shadow: 0 8px 24px #0008; }
|
||||||
.fab svg { width: 26px; height: 26px; }
|
.fab svg { width: 26px; height: 26px; }
|
||||||
|
|
||||||
/* ---------- Karten / Einstellungen ---------- */
|
/* ---------- Karten / Einstellungen ---------- */
|
||||||
.card { background: var(--surface); border-radius: var(--radius); padding: 14px 16px; margin-bottom: 14px; }
|
.card { background: var(--surface); border-radius: var(--r); padding: 14px 16px; margin-bottom: 14px; }
|
||||||
.card h3 { margin: 0 0 4px; font-size: 16px; }
|
.card h3 { margin: 0 0 4px; font-size: 16px; }
|
||||||
.card p, .hint { color: var(--muted); font-size: 13.5px; margin: 4px 0 10px; }
|
.card p, .hint { color: var(--muted); font-size: 13.5px; margin: 4px 0 10px; }
|
||||||
.row { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
|
.row { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
|
||||||
@@ -92,9 +86,9 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
|
|||||||
.row .sub { color: var(--muted); font-size: 13px; }
|
.row .sub { color: var(--muted); font-size: 13px; }
|
||||||
.btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
|
.btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
|
||||||
|
|
||||||
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 16px; border-radius: 12px; background: var(--surface2); font-weight: 600; }
|
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 16px; border-radius: 12px; background: var(--surface2); border: 1px solid var(--line); font-weight: 600; }
|
||||||
.btn svg { width: 18px; height: 18px; }
|
.btn svg { width: 18px; height: 18px; }
|
||||||
.btn.primary { background: var(--accent); color: #fff; }
|
.btn.primary { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
|
||||||
.btn.danger { color: var(--red); }
|
.btn.danger { color: var(--red); }
|
||||||
.btn.block { width: 100%; }
|
.btn.block { width: 100%; }
|
||||||
.btn:disabled { opacity: .5; }
|
.btn:disabled { opacity: .5; }
|
||||||
@@ -116,7 +110,7 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
|
|||||||
.switch span { position: absolute; inset: 0; background: var(--surface2); border-radius: 20px; transition: .2s; }
|
.switch span { position: absolute; inset: 0; background: var(--surface2); border-radius: 20px; transition: .2s; }
|
||||||
.switch span::after { content: ''; position: absolute; left: 3px; top: 3px; width: 24px; height: 24px; border-radius: 50%; background: var(--muted); transition: .2s; }
|
.switch span::after { content: ''; position: absolute; left: 3px; top: 3px; width: 24px; height: 24px; border-radius: 50%; background: var(--muted); transition: .2s; }
|
||||||
.switch input:checked + span { background: var(--accent); }
|
.switch input:checked + span { background: var(--accent); }
|
||||||
.switch input:checked + span::after { transform: translateX(20px); background: #fff; }
|
.switch input:checked + span::after { transform: translateX(20px); background: var(--on-accent); }
|
||||||
|
|
||||||
.warn-box { border: 1px solid #ffb34755; background: #ffb34712; border-radius: 12px; padding: 10px 12px; color: var(--orange); font-size: 13px; margin: 8px 0; }
|
.warn-box { border: 1px solid #ffb34755; background: #ffb34712; border-radius: 12px; padding: 10px 12px; color: var(--orange); font-size: 13px; margin: 8px 0; }
|
||||||
|
|
||||||
@@ -184,7 +178,46 @@ svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width:
|
|||||||
#keybar::-webkit-scrollbar { display: none; }
|
#keybar::-webkit-scrollbar { display: none; }
|
||||||
#keybar button { flex: none; min-width: 44px; height: 40px; padding: 0 10px; border-radius: 10px; background: var(--surface2); font: 600 14px ui-monospace, monospace; color: var(--text); display: grid; place-items: center; }
|
#keybar button { flex: none; min-width: 44px; height: 40px; padding: 0 10px; border-radius: 10px; background: var(--surface2); font: 600 14px ui-monospace, monospace; color: var(--text); display: grid; place-items: center; }
|
||||||
#keybar button svg { width: 18px; height: 18px; }
|
#keybar button svg { width: 18px; height: 18px; }
|
||||||
#keybar button.on { background: var(--accent); color: #fff; }
|
#keybar button.on { background: var(--accent); color: var(--on-accent); }
|
||||||
#keybar button.lock { box-shadow: inset 0 0 0 2px #fff; }
|
#keybar button.lock { box-shadow: inset 0 0 0 2px var(--on-accent); }
|
||||||
body.kbd-open #keybar { padding-bottom: 6px; }
|
body.kbd-open #keybar { padding-bottom: 6px; }
|
||||||
body.kbd-open #tabs, body.kbd-open .fab { display: none; }
|
body.kbd-open #tabs, body.kbd-open .fab { display: none; }
|
||||||
|
|
||||||
|
/* Design-Extras */
|
||||||
|
[data-theme='xp'] .page-head, [data-theme='xp'] .term-head { background: linear-gradient(#0a5fdc, #0846b8 55%, #0a3f9f); color: #fff; border-color: #0a3f9f; }
|
||||||
|
[data-theme='xp'] .page-head .icon, [data-theme='xp'] .term-head .icon, [data-theme='xp'] .term-title svg { color: #fff; }
|
||||||
|
[data-theme='xp'] #tabs { background: linear-gradient(#3168d5, #1d4fbf); border-color: #0a3f9f; }
|
||||||
|
[data-theme='xp'] #tabs button { color: #c7d8ff; }
|
||||||
|
[data-theme='xp'] #tabs button.active { color: #fff; }
|
||||||
|
[data-theme='xp'] .btn.primary, [data-theme='xp'] .fab { background: linear-gradient(#3d86e8, #2159b8); }
|
||||||
|
[data-theme='cyberpunk'] .btn.primary, [data-theme='cyberpunk'] .fab { clip-path: polygon(0 0, 100% 0, 100% 70%, calc(100% - 12px) 100%, 0 100%); }
|
||||||
|
[data-theme='cyberpunk'] .btn.primary { text-transform: uppercase; letter-spacing: .6px; }
|
||||||
|
[data-theme='cyberpunk'] .top h1 { text-transform: uppercase; letter-spacing: 1px; text-shadow: 2px 0 #ff003c88, -2px 0 #00f0ff88; }
|
||||||
|
[data-theme='cyberpunk'] .list, [data-theme='cyberpunk'] .card { border-left: 2px solid var(--accent); }
|
||||||
|
[data-theme='cyberpunk'] #tabs button.active { color: var(--accent); text-shadow: 0 0 8px #fcee0a88; }
|
||||||
|
.theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 6px 0 14px; }
|
||||||
|
.theme-prev { border-radius: 12px; padding: 8px; border: 2px solid var(--line); font-size: 12px; font-weight: 600; text-align: left; }
|
||||||
|
.theme-prev.active { border-color: var(--accent); }
|
||||||
|
.theme-prev .dp { display: flex; gap: 4px; height: 40px; margin-bottom: 6px; }
|
||||||
|
.theme-prev .dp i { width: 12px; border-radius: 3px; }
|
||||||
|
.theme-prev .dp div { flex: 1; display: flex; flex-direction: column; gap: 4px; }
|
||||||
|
.theme-prev .dp b { flex: 1; border-radius: 3px; position: relative; }
|
||||||
|
.theme-prev .dp s { position: absolute; left: 4px; top: 4px; width: 14px; height: 6px; border-radius: 2px; }
|
||||||
|
.colors { display: flex; flex-wrap: wrap; gap: 10px; }
|
||||||
|
.colors button { width: 34px; height: 34px; border-radius: 50%; border: 3px solid transparent; }
|
||||||
|
.colors button.active { border-color: var(--text); }
|
||||||
|
|
||||||
|
/* macOS Liquid Glass */
|
||||||
|
[data-theme='macos'] #main, [data-theme='macos'] #view { background: transparent; }
|
||||||
|
[data-theme='macos'] :is(.list, .card, .search, #tabs, .page-head, .term-head, .sheet, .dialog, .toast, .chip, .btn, .fab, .field input, .field select, .field textarea, #keybar) {
|
||||||
|
-webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
|
||||||
|
}
|
||||||
|
[data-theme='macos'] :is(.list, .card, .search, .sheet, .dialog, .toast, .chip) { border: 1px solid var(--border); box-shadow: var(--glass-edge); }
|
||||||
|
[data-theme='macos'] .page, [data-theme='macos'] #lockScreen { background: var(--wallpaper); }
|
||||||
|
[data-theme='macos'] .page-body { background: transparent; }
|
||||||
|
[data-theme='macos'] #tabs, [data-theme='macos'] .page-head { background: rgba(255, 255, 255, .42); border-color: rgba(255, 255, 255, .7); }
|
||||||
|
[data-theme='macos'] .btn { border-radius: 999px; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9); }
|
||||||
|
[data-theme='macos'] .btn.primary, [data-theme='macos'] .fab { background: linear-gradient(rgba(40, 145, 255, .92), rgba(0, 110, 240, .92)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55), 0 6px 18px rgba(0, 122, 255, .3); }
|
||||||
|
[data-theme='macos'] .fab { border-radius: 50%; }
|
||||||
|
[data-theme='macos'] .scrim { background: rgba(30, 40, 70, .18); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
|
||||||
|
[data-theme='macos'] .sheet, [data-theme='macos'] .dialog { background: rgba(255, 255, 255, .62); }
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "mrterm",
|
"name": "mrterm",
|
||||||
"version": "0.11.1",
|
"version": "0.12.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "mrterm",
|
"name": "mrterm",
|
||||||
"version": "0.11.1",
|
"version": "0.12.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xterm/addon-fit": "^0.11.0",
|
"@xterm/addon-fit": "^0.11.0",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mrterm",
|
"name": "mrterm",
|
||||||
"productName": "MrTerm",
|
"productName": "MrTerm",
|
||||||
"version": "0.11.1",
|
"version": "0.12.0",
|
||||||
"description": "Moderner SSH-, SFTP- und RDP-Client",
|
"description": "Moderner SSH-, SFTP- und RDP-Client",
|
||||||
"main": "src/main/main.js",
|
"main": "src/main/main.js",
|
||||||
"author": "MrBlake",
|
"author": "MrBlake",
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/* App-Designs: gemeinsame Farbvariablen für Desktop (src/renderer) und Android-App (mobile/web) */
|
||||||
|
:root {
|
||||||
|
--bg: #13151c;
|
||||||
|
--bg-2: #181b24;
|
||||||
|
--panel: #1c1f2a;
|
||||||
|
--card: #212533;
|
||||||
|
--card-hover: #282d3d;
|
||||||
|
--border: #2b3040;
|
||||||
|
--text: #e6e8ef;
|
||||||
|
--muted: #8b91a5;
|
||||||
|
--faint: #5d6377;
|
||||||
|
--accent: #6e7bff;
|
||||||
|
--accent-2: #8b95ff;
|
||||||
|
--green: #3ecf8e;
|
||||||
|
--red: #ff5f6d;
|
||||||
|
--orange: #ffb454;
|
||||||
|
--accent-3: #b36bff;
|
||||||
|
--chrome: #0f1117;
|
||||||
|
--chrome-line: #1f2330;
|
||||||
|
--hover: #1a1d27;
|
||||||
|
--nav-active: #1f2233;
|
||||||
|
--icon-bg: #2a2f45;
|
||||||
|
--folder: #6ea8ff;
|
||||||
|
--row-line: #1c1f29;
|
||||||
|
--overlay: #13151ce6;
|
||||||
|
--tint: 255 255 255;
|
||||||
|
--radius: 10px;
|
||||||
|
--on-accent: #ffffff;
|
||||||
|
--font: 'Inter', 'Segoe UI', system-ui, -apple-system, 'Noto Sans', sans-serif;
|
||||||
|
}
|
||||||
|
:root { --accent-2: color-mix(in srgb, var(--accent) 78%, white); }
|
||||||
|
[data-theme='navy'] {
|
||||||
|
--bg: #141729; --bg-2: #181c33; --panel: #1c2139; --card: #212742; --card-hover: #29304f; --border: #2e3657;
|
||||||
|
--text: #e8eaf6; --muted: #8e95b8; --faint: #5f6690; --accent: #21c7a8; --accent-3: #3a8dff;
|
||||||
|
--chrome: #0f1122; --chrome-line: #20264a; --hover: #1b2040; --nav-active: #232a52; --icon-bg: #2a3260; --row-line: #1c2140; --overlay: #141729e6;
|
||||||
|
}
|
||||||
|
[data-theme='nord'] {
|
||||||
|
--bg: #2e3440; --bg-2: #323846; --panel: #3b4252; --card: #3b4252; --card-hover: #434c5e; --border: #4c566a;
|
||||||
|
--text: #eceff4; --muted: #b5bdcc; --faint: #7b8598; --accent: #88c0d0; --accent-3: #81a1c1; --green: #a3be8c; --red: #bf616a; --orange: #d08770;
|
||||||
|
--chrome: #272c36; --chrome-line: #3b4252; --hover: #3b4252; --nav-active: #434c5e; --icon-bg: #4c566a; --folder: #81a1c1; --row-line: #3b4252; --overlay: #2e3440e6;
|
||||||
|
}
|
||||||
|
[data-theme='dracula'] {
|
||||||
|
--bg: #282a36; --bg-2: #2c2e3b; --panel: #313343; --card: #343746; --card-hover: #3e4153; --border: #44475a;
|
||||||
|
--text: #f8f8f2; --muted: #b3b6c8; --faint: #6272a4; --accent: #bd93f9; --accent-3: #ff79c6; --green: #50fa7b; --red: #ff5555; --orange: #ffb86c;
|
||||||
|
--chrome: #21222c; --chrome-line: #343746; --hover: #2f3140; --nav-active: #383a4c; --icon-bg: #44475a; --folder: #8be9fd; --row-line: #313343; --overlay: #282a36e6;
|
||||||
|
}
|
||||||
|
[data-theme='mocha'] {
|
||||||
|
--bg: #1e1e2e; --bg-2: #232334; --panel: #28283b; --card: #2a2a3d; --card-hover: #313244; --border: #3b3b52;
|
||||||
|
--text: #cdd6f4; --muted: #a6adc8; --faint: #6c7086; --accent: #cba6f7; --accent-3: #f5c2e7; --green: #a6e3a1; --red: #f38ba8; --orange: #fab387;
|
||||||
|
--chrome: #181825; --chrome-line: #292939; --hover: #252536; --nav-active: #313244; --icon-bg: #3a3a55; --folder: #89b4fa; --row-line: #28283b; --overlay: #1e1e2ee6;
|
||||||
|
}
|
||||||
|
[data-theme='forest'] {
|
||||||
|
--bg: #141a17; --bg-2: #18201c; --panel: #1c2621; --card: #1f2a24; --card-hover: #26342c; --border: #2d3d34;
|
||||||
|
--text: #e3ece6; --muted: #92a69a; --faint: #5e7266; --accent: #4cc38a; --accent-3: #b5e655; --folder: #7cc6a5;
|
||||||
|
--chrome: #0f1411; --chrome-line: #1f2a24; --hover: #1a231e; --nav-active: #213029; --icon-bg: #294034; --row-line: #1c2621; --overlay: #141a17e6;
|
||||||
|
}
|
||||||
|
[data-theme='light'] {
|
||||||
|
--bg: #f6f7fb; --bg-2: #eef0f6; --panel: #ffffff; --card: #ffffff; --card-hover: #f0f2fa; --border: #dde1ec;
|
||||||
|
--text: #1f2330; --muted: #5d6477; --faint: #9097aa; --accent: #5b67f1; --accent-3: #9b59f5; --green: #1f9d63; --red: #d63a4a; --orange: #c97a00;
|
||||||
|
--chrome: #e9ecf4; --chrome-line: #d8dce8; --hover: #dfe3ee; --nav-active: #d9ddf5; --icon-bg: #e6e9f7; --folder: #3d7de0; --row-line: #eceef5; --overlay: #f6f7fbe6;
|
||||||
|
--tint: 0 0 0;
|
||||||
|
--accent-2: color-mix(in srgb, var(--accent) 85%, black);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Windows XP (Luna) */
|
||||||
|
[data-theme='xp'] {
|
||||||
|
--bg: #ece9d8; --bg-2: #e3dfcb; --panel: #ffffff; --card: #ffffff; --card-hover: #f1efe2; --border: #aca899;
|
||||||
|
--text: #000000; --muted: #4a4a4a; --faint: #7f7f7f; --accent: #316ac5; --accent-3: #3a9a3a; --green: #2b8a2b; --red: #c81e1e; --orange: #d87400;
|
||||||
|
--chrome: #d6dff7; --chrome-line: #7a96df; --hover: #e8eefc; --nav-active: #c1d2ee; --icon-bg: #dde7f8; --folder: #e0a92a; --row-line: #ece9d8; --overlay: #ece9d8e6;
|
||||||
|
--tint: 0 0 0; --radius: 3px; --font: Tahoma, Verdana, 'Segoe UI', sans-serif;
|
||||||
|
--accent-2: color-mix(in srgb, var(--accent) 85%, black);
|
||||||
|
}
|
||||||
|
/* Windows 11 (hell, Mica) */
|
||||||
|
[data-theme='win11'] {
|
||||||
|
--bg: #f3f3f3; --bg-2: #eeeeee; --panel: #fbfbfb; --card: #ffffff; --card-hover: #f6f6f6; --border: #e5e5e5;
|
||||||
|
--text: #1b1b1b; --muted: #5f5f5f; --faint: #8a8a8a; --accent: #0067c0; --accent-3: #8764b8; --green: #0f7b0f; --red: #c42b1c; --orange: #9d5d00;
|
||||||
|
--chrome: #ebebeb; --chrome-line: #e0e0e0; --hover: #eaeaea; --nav-active: #e0e0e0; --icon-bg: #e6eef8; --folder: #e8a33d; --row-line: #efefef; --overlay: #f3f3f3e6;
|
||||||
|
--tint: 0 0 0; --radius: 8px; --font: 'Segoe UI Variable', 'Segoe UI', system-ui, sans-serif;
|
||||||
|
--accent-2: color-mix(in srgb, var(--accent) 85%, black);
|
||||||
|
}
|
||||||
|
/* macOS 26 „Liquid Glass“: milchige, durchscheinende Flächen über einem farbigen Hintergrund */
|
||||||
|
[data-theme='macos'] {
|
||||||
|
--bg: rgba(255, 255, 255, .34); --bg-2: rgba(255, 255, 255, .28); --panel: rgba(255, 255, 255, .55); --card: rgba(255, 255, 255, .48);
|
||||||
|
--card-hover: rgba(255, 255, 255, .68); --border: rgba(255, 255, 255, .7);
|
||||||
|
--text: #1d1d1f; --muted: #55555c; --faint: #8a8a92; --accent: #007aff; --accent-3: #af52de; --green: #248a3d; --red: #e0352b; --orange: #c96b00;
|
||||||
|
--chrome: rgba(255, 255, 255, .3); --chrome-line: rgba(255, 255, 255, .55); --hover: rgba(255, 255, 255, .45); --nav-active: rgba(255, 255, 255, .72);
|
||||||
|
--icon-bg: rgba(0, 122, 255, .12); --folder: #1a8cff; --row-line: rgba(255, 255, 255, .5); --overlay: rgba(240, 242, 250, .55);
|
||||||
|
--tint: 0 0 0; --radius: 14px; --font: -apple-system, 'SF Pro Text', 'Helvetica Neue', 'Inter', system-ui, sans-serif;
|
||||||
|
--accent-2: color-mix(in srgb, var(--accent) 85%, black);
|
||||||
|
--glass-blur: blur(26px) saturate(185%);
|
||||||
|
--glass-edge: inset 0 1px 0 rgba(255, 255, 255, .95), inset 0 -1px 0 rgba(255, 255, 255, .3), 0 10px 30px rgba(30, 40, 80, .10);
|
||||||
|
}
|
||||||
|
/* Hintergrund, durch den das Glas schimmert */
|
||||||
|
[data-theme='macos'] {
|
||||||
|
--wallpaper:
|
||||||
|
radial-gradient(at 12% 18%, #9cc2ff 0, transparent 46%),
|
||||||
|
radial-gradient(at 88% 12%, #f7b6dd 0, transparent 42%),
|
||||||
|
radial-gradient(at 72% 88%, #98e2d2 0, transparent 46%),
|
||||||
|
radial-gradient(at 18% 92%, #ffd6a0 0, transparent 42%),
|
||||||
|
#eef1f8;
|
||||||
|
}
|
||||||
|
html[data-theme='macos'], html[data-theme='macos'] body { background: var(--wallpaper); background-attachment: fixed; }
|
||||||
|
/* Cyberpunk 2077 */
|
||||||
|
[data-theme='cyberpunk'] {
|
||||||
|
--bg: #0a0a0f; --bg-2: #0e0e15; --panel: #111119; --card: #15151f; --card-hover: #1e1c10; --border: #3d3a14;
|
||||||
|
--text: #eafcff; --muted: #8fb8c8; --faint: #5a7680; --accent: #fcee0a; --accent-3: #00f0ff; --green: #00ff9f; --red: #ff003c; --orange: #ff9e00;
|
||||||
|
--chrome: #07070b; --chrome-line: #2a2808; --hover: #17161b; --nav-active: #232008; --icon-bg: #26240b; --folder: #00f0ff; --row-line: #17161f; --overlay: #0a0a0fe6;
|
||||||
|
--radius: 2px; --on-accent: #0a0a0f; --font: 'Rajdhani', 'Orbitron', 'Bahnschrift', 'DIN Alternate', 'Segoe UI', system-ui, sans-serif;
|
||||||
|
--accent-2: #fff45c;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:" />
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:" />
|
||||||
<title>MrTerm</title>
|
<title>MrTerm</title>
|
||||||
<link rel="stylesheet" href="../../node_modules/@xterm/xterm/css/xterm.css" />
|
<link rel="stylesheet" href="../../node_modules/@xterm/xterm/css/xterm.css" />
|
||||||
|
<link rel="stylesheet" href="app-themes.css" />
|
||||||
<link rel="stylesheet" href="styles.css" />
|
<link rel="stylesheet" href="styles.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
+28
-65
@@ -1,71 +1,12 @@
|
|||||||
:root {
|
:root {
|
||||||
--bg: #13151c;
|
|
||||||
--bg-2: #181b24;
|
|
||||||
--panel: #1c1f2a;
|
|
||||||
--card: #212533;
|
|
||||||
--card-hover: #282d3d;
|
|
||||||
--border: #2b3040;
|
|
||||||
--text: #e6e8ef;
|
|
||||||
--muted: #8b91a5;
|
|
||||||
--faint: #5d6377;
|
|
||||||
--accent: #6e7bff;
|
|
||||||
--accent-2: #8b95ff;
|
|
||||||
--green: #3ecf8e;
|
|
||||||
--red: #ff5f6d;
|
|
||||||
--orange: #ffb454;
|
|
||||||
--accent-3: #b36bff;
|
|
||||||
--chrome: #0f1117;
|
|
||||||
--chrome-line: #1f2330;
|
|
||||||
--hover: #1a1d27;
|
|
||||||
--nav-active: #1f2233;
|
|
||||||
--icon-bg: #2a2f45;
|
|
||||||
--folder: #6ea8ff;
|
|
||||||
--row-line: #1c1f29;
|
|
||||||
--overlay: #13151ce6;
|
|
||||||
--tint: 255 255 255;
|
|
||||||
--radius: 10px;
|
|
||||||
--titlebar: 42px;
|
--titlebar: 42px;
|
||||||
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, 'Noto Sans', sans-serif;
|
font-family: var(--font);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
}
|
}
|
||||||
/* ---------- App-Designs ---------- */
|
[data-theme='light'] .card, [data-theme='xp'] .card, [data-theme='win11'] .card, [data-theme='macos'] .card { border-color: var(--border); }
|
||||||
:root { --accent-2: color-mix(in srgb, var(--accent) 78%, white); }
|
[data-theme='light'] .avatar .proto, [data-theme='xp'] .avatar .proto, [data-theme='win11'] .avatar .proto, [data-theme='macos'] .avatar .proto { background: var(--panel); }
|
||||||
[data-theme='navy'] {
|
[data-theme='light'] ::-webkit-scrollbar-thumb, [data-theme='xp'] ::-webkit-scrollbar-thumb, [data-theme='win11'] ::-webkit-scrollbar-thumb, [data-theme='macos'] ::-webkit-scrollbar-thumb { background: #c5cad8; background-clip: padding-box; }
|
||||||
--bg: #141729; --bg-2: #181c33; --panel: #1c2139; --card: #212742; --card-hover: #29304f; --border: #2e3657;
|
|
||||||
--text: #e8eaf6; --muted: #8e95b8; --faint: #5f6690; --accent: #21c7a8; --accent-3: #3a8dff;
|
|
||||||
--chrome: #0f1122; --chrome-line: #20264a; --hover: #1b2040; --nav-active: #232a52; --icon-bg: #2a3260; --row-line: #1c2140; --overlay: #141729e6;
|
|
||||||
}
|
|
||||||
[data-theme='nord'] {
|
|
||||||
--bg: #2e3440; --bg-2: #323846; --panel: #3b4252; --card: #3b4252; --card-hover: #434c5e; --border: #4c566a;
|
|
||||||
--text: #eceff4; --muted: #b5bdcc; --faint: #7b8598; --accent: #88c0d0; --accent-3: #81a1c1; --green: #a3be8c; --red: #bf616a; --orange: #d08770;
|
|
||||||
--chrome: #272c36; --chrome-line: #3b4252; --hover: #3b4252; --nav-active: #434c5e; --icon-bg: #4c566a; --folder: #81a1c1; --row-line: #3b4252; --overlay: #2e3440e6;
|
|
||||||
}
|
|
||||||
[data-theme='dracula'] {
|
|
||||||
--bg: #282a36; --bg-2: #2c2e3b; --panel: #313343; --card: #343746; --card-hover: #3e4153; --border: #44475a;
|
|
||||||
--text: #f8f8f2; --muted: #b3b6c8; --faint: #6272a4; --accent: #bd93f9; --accent-3: #ff79c6; --green: #50fa7b; --red: #ff5555; --orange: #ffb86c;
|
|
||||||
--chrome: #21222c; --chrome-line: #343746; --hover: #2f3140; --nav-active: #383a4c; --icon-bg: #44475a; --folder: #8be9fd; --row-line: #313343; --overlay: #282a36e6;
|
|
||||||
}
|
|
||||||
[data-theme='mocha'] {
|
|
||||||
--bg: #1e1e2e; --bg-2: #232334; --panel: #28283b; --card: #2a2a3d; --card-hover: #313244; --border: #3b3b52;
|
|
||||||
--text: #cdd6f4; --muted: #a6adc8; --faint: #6c7086; --accent: #cba6f7; --accent-3: #f5c2e7; --green: #a6e3a1; --red: #f38ba8; --orange: #fab387;
|
|
||||||
--chrome: #181825; --chrome-line: #292939; --hover: #252536; --nav-active: #313244; --icon-bg: #3a3a55; --folder: #89b4fa; --row-line: #28283b; --overlay: #1e1e2ee6;
|
|
||||||
}
|
|
||||||
[data-theme='forest'] {
|
|
||||||
--bg: #141a17; --bg-2: #18201c; --panel: #1c2621; --card: #1f2a24; --card-hover: #26342c; --border: #2d3d34;
|
|
||||||
--text: #e3ece6; --muted: #92a69a; --faint: #5e7266; --accent: #4cc38a; --accent-3: #b5e655; --folder: #7cc6a5;
|
|
||||||
--chrome: #0f1411; --chrome-line: #1f2a24; --hover: #1a231e; --nav-active: #213029; --icon-bg: #294034; --row-line: #1c2621; --overlay: #141a17e6;
|
|
||||||
}
|
|
||||||
[data-theme='light'] {
|
|
||||||
--bg: #f6f7fb; --bg-2: #eef0f6; --panel: #ffffff; --card: #ffffff; --card-hover: #f0f2fa; --border: #dde1ec;
|
|
||||||
--text: #1f2330; --muted: #5d6477; --faint: #9097aa; --accent: #5b67f1; --accent-3: #9b59f5; --green: #1f9d63; --red: #d63a4a; --orange: #c97a00;
|
|
||||||
--chrome: #e9ecf4; --chrome-line: #d8dce8; --hover: #dfe3ee; --nav-active: #d9ddf5; --icon-bg: #e6e9f7; --folder: #3d7de0; --row-line: #eceef5; --overlay: #f6f7fbe6;
|
|
||||||
--tint: 0 0 0;
|
|
||||||
--accent-2: color-mix(in srgb, var(--accent) 85%, black);
|
|
||||||
}
|
|
||||||
[data-theme='light'] .card { border-color: var(--border); }
|
|
||||||
[data-theme='light'] .avatar .proto { background: var(--panel); }
|
|
||||||
[data-theme='light'] ::-webkit-scrollbar-thumb { background: #c5cad8; background-clip: padding-box; }
|
|
||||||
* { box-sizing: border-box; }
|
* { box-sizing: border-box; }
|
||||||
html, body { margin: 0; height: 100%; background: var(--bg); overflow: hidden; }
|
html, body { margin: 0; height: 100%; background: var(--bg); overflow: hidden; }
|
||||||
button { font: inherit; color: inherit; cursor: pointer; }
|
button { font: inherit; color: inherit; cursor: pointer; }
|
||||||
@@ -154,7 +95,7 @@ body.in-session #sidebar { display: none; }
|
|||||||
.search svg { color: var(--faint); }
|
.search svg { color: var(--faint); }
|
||||||
.btn { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 14px; border-radius: 8px; border: 1px solid var(--border); background: var(--panel); font-weight: 600; white-space: nowrap; }
|
.btn { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 14px; border-radius: 8px; border: 1px solid var(--border); background: var(--panel); font-weight: 600; white-space: nowrap; }
|
||||||
.btn:hover { background: var(--card-hover); }
|
.btn:hover { background: var(--card-hover); }
|
||||||
.btn.primary { background: var(--accent); border-color: var(--accent); color: white; }
|
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
|
||||||
.btn.primary:hover { background: var(--accent-2); }
|
.btn.primary:hover { background: var(--accent-2); }
|
||||||
.btn.danger { color: var(--red); }
|
.btn.danger { color: var(--red); }
|
||||||
.btn.danger:hover { background: color-mix(in srgb, var(--red) 10%, transparent); }
|
.btn.danger:hover { background: color-mix(in srgb, var(--red) 10%, transparent); }
|
||||||
@@ -221,7 +162,7 @@ body.in-session #sidebar { display: none; }
|
|||||||
.form h4 { margin: 20px 0 12px; font-size: 11px; text-transform: uppercase; letter-spacing: .6px; color: var(--accent-2); }
|
.form h4 { margin: 20px 0 12px; font-size: 11px; text-transform: uppercase; letter-spacing: .6px; color: var(--accent-2); }
|
||||||
.seg { display: flex; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 3px; gap: 3px; margin-bottom: 14px; }
|
.seg { display: flex; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 3px; gap: 3px; margin-bottom: 14px; }
|
||||||
.seg button { flex: 1; border: none; background: none; padding: 7px; border-radius: 6px; color: var(--muted); font-weight: 600; }
|
.seg button { flex: 1; border: none; background: none; padding: 7px; border-radius: 6px; color: var(--muted); font-weight: 600; }
|
||||||
.seg button.active { background: var(--accent); color: white; }
|
.seg button.active { background: var(--accent); color: var(--on-accent); }
|
||||||
.check { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; cursor: pointer; }
|
.check { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; cursor: pointer; }
|
||||||
.check input { accent-color: var(--accent); width: 16px; height: 16px; }
|
.check input { accent-color: var(--accent); width: 16px; height: 16px; }
|
||||||
.colors { display: flex; gap: 8px; flex-wrap: wrap; }
|
.colors { display: flex; gap: 8px; flex-wrap: wrap; }
|
||||||
@@ -443,3 +384,25 @@ kbd { background: var(--card); border: 1px solid var(--border); border-bottom-wi
|
|||||||
.fw-hint b { color: var(--text); }
|
.fw-hint b { color: var(--text); }
|
||||||
.fw-hint p { margin: 4px 0 8px; color: var(--muted); }
|
.fw-hint p { margin: 4px 0 8px; color: var(--muted); }
|
||||||
.fw-hint pre, .fw-pre { background: var(--bg); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; margin: 0 0 10px; color: var(--text); white-space: pre-wrap; user-select: text; }
|
.fw-hint pre, .fw-pre { background: var(--bg); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; margin: 0 0 10px; color: var(--text); white-space: pre-wrap; user-select: text; }
|
||||||
|
|
||||||
|
/* Design-Extras: XP-Titelleiste, Cyberpunk-Neon */
|
||||||
|
[data-theme='xp'] #titlebar { background: linear-gradient(#0a5fdc, #0846b8 55%, #0a3f9f); color: #fff; }
|
||||||
|
[data-theme='xp'] #titlebar .brand, [data-theme='xp'] #titlebar .win-ctrls button, [data-theme='xp'] #titlebar .tab:not(.active) { color: #fff; }
|
||||||
|
[data-theme='xp'] #titlebar .tab.active { color: var(--text); }
|
||||||
|
[data-theme='xp'] .btn.primary { background: linear-gradient(#3d86e8, #2159b8); border-color: #1b4a9a; }
|
||||||
|
[data-theme='cyberpunk'] .btn.primary { clip-path: polygon(0 0, 100% 0, 100% 70%, calc(100% - 10px) 100%, 0 100%); text-transform: uppercase; letter-spacing: .5px; }
|
||||||
|
[data-theme='cyberpunk'] #titlebar { border-bottom: 1px solid #fcee0a55; }
|
||||||
|
[data-theme='cyberpunk'] .card:hover { box-shadow: inset 2px 0 0 var(--accent-3); }
|
||||||
|
[data-theme='xp'] .brand-term, [data-theme='win11'] .brand-term, [data-theme='macos'] .brand-term { color: #14a37a; }
|
||||||
|
/* macOS Liquid Glass */
|
||||||
|
[data-theme='macos'] #main, [data-theme='macos'] .pane { background: transparent; }
|
||||||
|
[data-theme='macos'] :is(#titlebar, #sidebar, .toolbar, .card, .settings-card, .modal, .drawer, .ctx, .palette, .search, .toast, .net-card, .findbar, .pane th, .tab.active, .btn, .seg, .field input, .field select, .field textarea) {
|
||||||
|
-webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
|
||||||
|
}
|
||||||
|
[data-theme='macos'] :is(.card, .settings-card, .modal, .drawer, .ctx, .palette, .toast, .net-card, .search) { border: 1px solid var(--border); box-shadow: var(--glass-edge); }
|
||||||
|
[data-theme='macos'] #sidebar { border-right: 1px solid var(--chrome-line); box-shadow: inset -1px 0 0 rgba(255, 255, 255, .6); }
|
||||||
|
[data-theme='macos'] #titlebar { border-bottom: 1px solid var(--chrome-line); }
|
||||||
|
[data-theme='macos'] .btn { border-radius: 999px; border-color: rgba(255, 255, 255, .75); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 2px 8px rgba(30, 40, 80, .08); }
|
||||||
|
[data-theme='macos'] .btn.primary { background: linear-gradient(rgba(40, 145, 255, .92), rgba(0, 110, 240, .92)); border-color: rgba(255, 255, 255, .45); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55), 0 4px 14px rgba(0, 122, 255, .3); }
|
||||||
|
[data-theme='macos'] .modal-bg { -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
|
||||||
|
[data-theme='macos'] .nav.active { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 2px 8px rgba(30, 40, 80, .08); }
|
||||||
|
|||||||
+19
-1
@@ -29,6 +29,20 @@ TERM_THEMES.mocha = { name: 'Catppuccin Mocha', background: '#1e1e2e', foregroun
|
|||||||
TERM_THEMES.navy = { ...TERM_THEMES.mrterm, name: 'Navy', background: '#141729', cursor: '#21c7a8', cursorAccent: '#141729', selectionBackground: '#21c7a844', black: '#212742' };
|
TERM_THEMES.navy = { ...TERM_THEMES.mrterm, name: 'Navy', background: '#141729', cursor: '#21c7a8', cursorAccent: '#141729', selectionBackground: '#21c7a844', black: '#212742' };
|
||||||
TERM_THEMES.forest = { ...TERM_THEMES.mrterm, name: 'Forest', background: '#141a17', foreground: '#e3ece6', cursor: '#4cc38a', cursorAccent: '#141a17', selectionBackground: '#4cc38a44', black: '#1f2a24' };
|
TERM_THEMES.forest = { ...TERM_THEMES.mrterm, name: 'Forest', background: '#141a17', foreground: '#e3ece6', cursor: '#4cc38a', cursorAccent: '#141a17', selectionBackground: '#4cc38a44', black: '#1f2a24' };
|
||||||
|
|
||||||
|
// Terminal-Schemata zu den System-Designs
|
||||||
|
TERM_THEMES.xp = { name: 'Windows XP (cmd.exe)', background: '#000000', foreground: '#c0c0c0', cursor: '#c0c0c0', cursorAccent: '#000000', selectionBackground: '#c0c0c066',
|
||||||
|
black: '#000000', red: '#800000', green: '#008000', yellow: '#808000', blue: '#000080', magenta: '#800080', cyan: '#008080', white: '#c0c0c0',
|
||||||
|
brightBlack: '#808080', brightRed: '#ff0000', brightGreen: '#00ff00', brightYellow: '#ffff00', brightBlue: '#0000ff', brightMagenta: '#ff00ff', brightCyan: '#00ffff', brightWhite: '#ffffff' };
|
||||||
|
TERM_THEMES.campbell = { name: 'Windows 11 (Campbell)', background: '#0c0c0c', foreground: '#cccccc', cursor: '#ffffff', cursorAccent: '#0c0c0c', selectionBackground: '#ffffff40',
|
||||||
|
black: '#0c0c0c', red: '#c50f1f', green: '#13a10e', yellow: '#c19c00', blue: '#0037da', magenta: '#881798', cyan: '#3a96dd', white: '#cccccc',
|
||||||
|
brightBlack: '#767676', brightRed: '#e74856', brightGreen: '#16c60c', brightYellow: '#f9f1a5', brightBlue: '#3b78ff', brightMagenta: '#b4009e', brightCyan: '#61d6d6', brightWhite: '#f2f2f2' };
|
||||||
|
TERM_THEMES.macos = { name: 'macOS Terminal', background: '#ffffff', foreground: '#1d1d1f', cursor: '#7f7f7f', cursorAccent: '#ffffff', selectionBackground: '#b4d7ff',
|
||||||
|
black: '#000000', red: '#c23621', green: '#25bc24', yellow: '#adad27', blue: '#492ee1', magenta: '#d338d3', cyan: '#33bbc8', white: '#cbcccd',
|
||||||
|
brightBlack: '#818383', brightRed: '#fc391f', brightGreen: '#31e722', brightYellow: '#eaec23', brightBlue: '#5833ff', brightMagenta: '#f935f8', brightCyan: '#14f0f0', brightWhite: '#e9ebeb' };
|
||||||
|
TERM_THEMES.cyberpunk = { name: 'Cyberpunk 2077', background: '#0a0a0f', foreground: '#eafcff', cursor: '#fcee0a', cursorAccent: '#0a0a0f', selectionBackground: '#00f0ff44',
|
||||||
|
black: '#15151f', red: '#ff003c', green: '#00ff9f', yellow: '#fcee0a', blue: '#00b8ff', magenta: '#ff2bd6', cyan: '#00f0ff', white: '#d7e6ee',
|
||||||
|
brightBlack: '#5a7680', brightRed: '#ff4f70', brightGreen: '#5cffc0', brightYellow: '#fff45c', brightBlue: '#5cd3ff', brightMagenta: '#ff6be4', brightCyan: '#6bf7ff', brightWhite: '#ffffff' };
|
||||||
|
|
||||||
// App-Designs: Vorschaufarben + passendes Terminal-Schema (für "Passend zum Design")
|
// App-Designs: Vorschaufarben + passendes Terminal-Schema (für "Passend zum Design")
|
||||||
window.APP_THEMES = {
|
window.APP_THEMES = {
|
||||||
midnight: { name: 'Midnight', bg: '#13151c', side: '#0f1117', card: '#212533', accent: '#6e7bff', text: '#e6e8ef', term: 'mrterm' },
|
midnight: { name: 'Midnight', bg: '#13151c', side: '#0f1117', card: '#212533', accent: '#6e7bff', text: '#e6e8ef', term: 'mrterm' },
|
||||||
@@ -37,5 +51,9 @@ window.APP_THEMES = {
|
|||||||
dracula: { name: 'Dracula', bg: '#282a36', side: '#21222c', card: '#343746', accent: '#bd93f9', text: '#f8f8f2', term: 'dracula' },
|
dracula: { name: 'Dracula', bg: '#282a36', side: '#21222c', card: '#343746', accent: '#bd93f9', text: '#f8f8f2', term: 'dracula' },
|
||||||
mocha: { name: 'Catppuccin', bg: '#1e1e2e', side: '#181825', card: '#2a2a3d', accent: '#cba6f7', text: '#cdd6f4', term: 'mocha' },
|
mocha: { name: 'Catppuccin', bg: '#1e1e2e', side: '#181825', card: '#2a2a3d', accent: '#cba6f7', text: '#cdd6f4', term: 'mocha' },
|
||||||
forest: { name: 'Forest', bg: '#141a17', side: '#0f1411', card: '#1f2a24', accent: '#4cc38a', text: '#e3ece6', term: 'forest' },
|
forest: { name: 'Forest', bg: '#141a17', side: '#0f1411', card: '#1f2a24', accent: '#4cc38a', text: '#e3ece6', term: 'forest' },
|
||||||
light: { name: 'Light', bg: '#f6f7fb', side: '#e9ecf4', card: '#ffffff', accent: '#5b67f1', text: '#1f2330', term: 'light' },
|
light: { name: 'Light', bg: '#f6f7fb', side: '#e9ecf4', card: '#ffffff', accent: '#5b67f1', text: '#1f2330', term: 'light', light: true },
|
||||||
|
xp: { name: 'Windows XP', bg: '#ece9d8', side: '#0a5fdc', card: '#ffffff', accent: '#316ac5', text: '#000000', term: 'xp', light: true },
|
||||||
|
win11: { name: 'Windows 11', bg: '#f3f3f3', side: '#ebebeb', card: '#ffffff', accent: '#0067c0', text: '#1b1b1b', term: 'campbell', light: true },
|
||||||
|
macos: { name: 'macOS', bg: '#ffffff', side: '#e8e8ed', card: '#f5f5f7', accent: '#007aff', text: '#1d1d1f', term: 'macos', light: true },
|
||||||
|
cyberpunk: { name: 'Cyberpunk 2077', bg: '#0a0a0f', side: '#07070b', card: '#15151f', accent: '#fcee0a', text: '#eafcff', term: 'cyberpunk' },
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user