Refakturiert die Anwendung und modernisiert das Build-System
Diese umfangreiche Überarbeitung verbessert die Architektur, den Build-Prozess und die Benutzeroberfläche der Toolbox. Wesentliche Änderungen: - **Build-System:** Umfassende Modernisierung des CMake-Builds für verbesserte Stabilität und Wartbarkeit. Die Konfiguration wurde auf zielbasierte Befehle umgestellt, `c_tray` stabilisiert und `saucer-desktop` entfernt. - **Modulare Architektur:** Die Kernlogik von `ToolboxWindow` wurde in dedizierte Helferklassen ausgelagert, darunter `LuaRunner` für die Skriptausführung, `ToolRegistry` für die Tool-Erkennung, `ResourceLoader` für UI-Ressourcen, `ToolboxJsBridge` für JavaScript-Bindungen und `WindowPlacement` für die Fensterverwaltung. Dies reduziert die Komplexität und fördert die Wiederverwendbarkeit. - **Benutzeroberfläche (UI):** Die HTML-Templates (`einstellungen_custom.html`, `index.html`) und Stylesheets (`styles.css`) wurden zentralisiert und überarbeitet, um eine kohärentere Benutzeroberfläche mit benutzerdefinierten Fensterdekorationen zu bieten. Neue Funktionen wie das Öffnen der Kommandozeile und eine "Tool hinzufügen"-Karte wurden integriert. - **Tray-Verwaltung:** Die Tray-Icon-Logik wurde in `TrayController` gekapselt, um eine robustere und zentralisierte Steuerung zu ermöglichen, insbesondere im Umgang mit Explorer-Neustarts.
This commit is contained in:
@@ -4,147 +4,10 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Toolbox</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background: linear-gradient(to bottom, #1e1e2e, #28293d);
|
||||
color: white;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Linke Sidebar */
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
background-color: #2b2c3b;
|
||||
padding: 15px;
|
||||
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.3);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
color: #ff79c6;
|
||||
font-size: 16px;
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
.sidebar ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar ul li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.sidebar ul li a {
|
||||
text-decoration: none;
|
||||
padding: 10px;
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
background: #32334a;
|
||||
color: #fff;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.sidebar ul li a:hover {
|
||||
background: #ff79c6;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Hauptbereich mit flexibler Anzeige */
|
||||
.main-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: #1b1b2b;
|
||||
padding: 15px 20px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
background: #2b2c3b;
|
||||
border: none;
|
||||
color: #ff79c6;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
background: #32334a;
|
||||
}
|
||||
|
||||
.editor {
|
||||
flex: 1;
|
||||
background: #1e1e2e;
|
||||
padding: 15px;
|
||||
display: none; /* Standardmäßig ausgeblendet */
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.editor textarea {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
background: #2b2c3b;
|
||||
color: #fff;
|
||||
border: 1px solid #ff79c6;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
padding: 10px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.editor pre {
|
||||
width: 80%;
|
||||
margin-top: 10px;
|
||||
background: #2b2c3b;
|
||||
color: #fff;
|
||||
border: 1px solid #32334a;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.general {
|
||||
flex: 1;
|
||||
background: #1e1e2e;
|
||||
padding: 15px;
|
||||
display: flex; /* Standardmäßig sichtbar */
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background: #1b1b2b;
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #aaa;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="saucer://embedded/html/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body class="settings-page">
|
||||
<div id="shell">
|
||||
<!-- Sidebar für Optionen -->
|
||||
<div class="sidebar">
|
||||
<h2>Einstellungen</h2>
|
||||
@@ -173,19 +36,18 @@
|
||||
</div>
|
||||
|
||||
<div class="general" id="general">
|
||||
<div style="width: 80%; max-width: 520px;">
|
||||
<div class="settings-card">
|
||||
<h3 style="margin: 0 0 10px 0;">Tool</h3>
|
||||
<div id="tool-name" style="margin-bottom: 20px; color: #ff79c6;">-</div>
|
||||
<div id="tool-name" class="settings-tool-name">-</div>
|
||||
|
||||
<label for="lua-timeout">Lua Timeout (Sekunden)</label>
|
||||
<input id="lua-timeout" type="number" min="0" step="1" value="30"
|
||||
style="width: 100%; margin-top: 6px; padding: 8px; border-radius: 4px; border: 1px solid #32334a; background: #2b2c3b; color: #fff;">
|
||||
<div style="margin-top: 6px; font-size: 12px; color: #aaa;">
|
||||
<input id="lua-timeout" class="settings-input" type="number" min="0" step="1" value="30">
|
||||
<div class="settings-help">
|
||||
0 = kein Timeout
|
||||
</div>
|
||||
|
||||
<button id="save-settings" class="back-button" style="margin-top: 16px;">Speichern</button>
|
||||
<div id="save-status" style="margin-top: 8px; font-size: 12px; color: #aaa;"></div>
|
||||
<button id="save-settings" class="back-button settings-save">Speichern</button>
|
||||
<div id="save-status" class="settings-status"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -195,6 +57,7 @@
|
||||
<!--Schmidti.Digital © 2024-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function goBack() {
|
||||
saucer.exposed.openIndex();
|
||||
@@ -221,13 +84,50 @@
|
||||
const output = document.getElementById('highlightedOutput');
|
||||
showContent('general');
|
||||
|
||||
function escapeHtml(text) {
|
||||
return text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function highlightLua(code) {
|
||||
let escaped = escapeHtml(code);
|
||||
const tokens = [];
|
||||
|
||||
function stash(pattern, className, input) {
|
||||
return input.replace(pattern, (match) => {
|
||||
const key = `@@TOKEN${tokens.length}@@`;
|
||||
tokens.push(`<span class="${className}">${match}</span>`);
|
||||
return key;
|
||||
});
|
||||
}
|
||||
|
||||
escaped = stash(/--\[\[[\s\S]*?\]\]|--[^\n]*/g, 'code-comment', escaped);
|
||||
escaped = stash(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\[\[[\s\S]*?\]\]/g, 'code-string', escaped);
|
||||
|
||||
escaped = escaped.replace(/\b(\d+(\.\d+)?)\b/g, '<span class="code-number">$1</span>');
|
||||
|
||||
const keywords = [
|
||||
'and','break','do','else','elseif','end','false','for','function',
|
||||
'if','in','local','nil','not','or','repeat','return','then','true',
|
||||
'until','while'
|
||||
];
|
||||
const keywordRegex = new RegExp(`\\b(${keywords.join('|')})\\b`, 'g');
|
||||
escaped = escaped.replace(keywordRegex, '<span class="code-keyword">$1</span>');
|
||||
|
||||
tokens.forEach((value, index) => {
|
||||
escaped = escaped.replace(`@@TOKEN${index}@@`, value);
|
||||
});
|
||||
|
||||
return escaped;
|
||||
}
|
||||
|
||||
// Synchronisiere den Inhalt von textarea mit dem Codeblock
|
||||
editor.addEventListener('input', () => {
|
||||
output.innerHTML = ''; // Vorheriges Highlighting entfernen
|
||||
output.textContent = editor.value; // Aktuellen Text setzen
|
||||
if (window.hljs && typeof hljs.highlightAll === 'function') {
|
||||
hljs.highlightAll();
|
||||
}
|
||||
output.innerHTML = highlightLua(editor.value);
|
||||
});
|
||||
|
||||
const toolName = document.getElementById('tool-name');
|
||||
@@ -259,3 +159,7 @@
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
175
res/html/einstellungen_custom.html
Normal file
175
res/html/einstellungen_custom.html
Normal file
@@ -0,0 +1,175 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Toolbox</title>
|
||||
<link rel="stylesheet" href="saucer://embedded/html/styles.css">
|
||||
</head>
|
||||
<body class="settings-page">
|
||||
<div id="shell" class="settings-shell">
|
||||
<div class="resize-handle resize-top" data-webview-resize="t"></div>
|
||||
<div class="resize-handle resize-right" data-webview-resize="r"></div>
|
||||
<div class="resize-handle resize-bottom" data-webview-resize="b"></div>
|
||||
<div class="resize-handle resize-left" data-webview-resize="l"></div>
|
||||
<div class="resize-handle resize-top-left" data-webview-resize="tl"></div>
|
||||
<div class="resize-handle resize-top-right" data-webview-resize="tr"></div>
|
||||
<div class="resize-handle resize-bottom-left" data-webview-resize="bl"></div>
|
||||
<div class="resize-handle resize-bottom-right" data-webview-resize="br"></div>
|
||||
<div class="titlebar" data-webview-drag>
|
||||
<div class="titlebar-left" data-webview-drag>
|
||||
<button class="titlebar-btn" onclick="goBack()" data-webview-ignore>←</button>
|
||||
<span class="titlebar-title" data-webview-drag>Einstellungen</span>
|
||||
</div>
|
||||
<div class="titlebar-actions" data-webview-drag>
|
||||
<button class="titlebar-btn" data-webview-minimize data-webview-ignore>–</button>
|
||||
<button class="titlebar-btn close" data-webview-close data-webview-ignore>×</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-body">
|
||||
<!-- Sidebar für Optionen -->
|
||||
<div class="sidebar">
|
||||
<h2>Einstellungen</h2>
|
||||
<ul>
|
||||
<li><a href="#" onclick="showContent('general')">Einstellungen</a></li>
|
||||
<li><a href="#" onclick="showContent('editor')">Skript</a></li>
|
||||
<li><a href="#" onclick="showContent('none')">Option 3</a></li>
|
||||
<li><a href="#" onclick="showContent('none')">Option 4</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Hauptcontainer -->
|
||||
<div class="main-container">
|
||||
<!-- Zentraler Editor (Standardmäßig versteckt) -->
|
||||
<div class="editor" id="editor">
|
||||
<label for="code-editor"></label>
|
||||
<textarea id="code-editor" placeholder="Write Lua code here..."></textarea>
|
||||
<pre><code id="highlightedOutput" class="language-lua"></code></pre>
|
||||
</div>
|
||||
|
||||
<div class="general" id="general">
|
||||
<div class="settings-card">
|
||||
<h3 style="margin: 0 0 10px 0;">Tool</h3>
|
||||
<div id="tool-name" class="settings-tool-name">-</div>
|
||||
|
||||
<label for="lua-timeout">Lua Timeout (Sekunden)</label>
|
||||
<input id="lua-timeout" class="settings-input" type="number" min="0" step="1" value="30">
|
||||
<div class="settings-help">
|
||||
0 = kein Timeout
|
||||
</div>
|
||||
|
||||
<button id="save-settings" class="back-button settings-save">Speichern</button>
|
||||
<div id="save-status" class="settings-status"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="footer">
|
||||
<!--Schmidti.Digital © 2024-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function goBack() {
|
||||
saucer.exposed.openIndex();
|
||||
}
|
||||
|
||||
function showContent(option) {
|
||||
const general = document.getElementById('general');
|
||||
const editor = document.getElementById('editor');
|
||||
|
||||
if (option === 'editor') {
|
||||
editor.style.display = 'flex';
|
||||
general.style.display = 'none';
|
||||
} else if (option === 'general') {
|
||||
general.style.display = 'flex';
|
||||
editor.style.display = 'none';
|
||||
} else {
|
||||
editor.style.display = 'none';
|
||||
general.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const editor = document.getElementById('code-editor');
|
||||
const output = document.getElementById('highlightedOutput');
|
||||
showContent('general');
|
||||
|
||||
function escapeHtml(text) {
|
||||
return text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function highlightLua(code) {
|
||||
let escaped = escapeHtml(code);
|
||||
const tokens = [];
|
||||
|
||||
function stash(pattern, className, input) {
|
||||
return input.replace(pattern, (match) => {
|
||||
const key = `@@TOKEN${tokens.length}@@`;
|
||||
tokens.push(`<span class="${className}">${match}</span>`);
|
||||
return key;
|
||||
});
|
||||
}
|
||||
|
||||
escaped = stash(/--\[\[[\s\S]*?\]\]|--[^\n]*/g, 'code-comment', escaped);
|
||||
escaped = stash(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\[\[[\s\S]*?\]\]/g, 'code-string', escaped);
|
||||
|
||||
escaped = escaped.replace(/\b(\d+(\.\d+)?)\b/g, '<span class="code-number">$1</span>');
|
||||
|
||||
const keywords = [
|
||||
'and','break','do','else','elseif','end','false','for','function',
|
||||
'if','in','local','nil','not','or','repeat','return','then','true',
|
||||
'until','while'
|
||||
];
|
||||
const keywordRegex = new RegExp(`\\b(${keywords.join('|')})\\b`, 'g');
|
||||
escaped = escaped.replace(keywordRegex, '<span class="code-keyword">$1</span>');
|
||||
|
||||
tokens.forEach((value, index) => {
|
||||
escaped = escaped.replace(`@@TOKEN${index}@@`, value);
|
||||
});
|
||||
|
||||
return escaped;
|
||||
}
|
||||
|
||||
// Synchronisiere den Inhalt von textarea mit dem Codeblock
|
||||
editor.addEventListener('input', () => {
|
||||
output.innerHTML = highlightLua(editor.value);
|
||||
});
|
||||
|
||||
const toolName = document.getElementById('tool-name');
|
||||
const timeoutInput = document.getElementById('lua-timeout');
|
||||
const saveBtn = document.getElementById('save-settings');
|
||||
const saveStatus = document.getElementById('save-status');
|
||||
|
||||
saucer.exposed.getActiveToolName().then(name => {
|
||||
toolName.textContent = name || '-';
|
||||
});
|
||||
|
||||
saucer.exposed.getLuaTimeoutSeconds().then(value => {
|
||||
timeoutInput.value = value;
|
||||
});
|
||||
|
||||
|
||||
saveBtn.addEventListener('click', () => {
|
||||
const seconds = parseInt(timeoutInput.value, 10);
|
||||
saucer.exposed.setLuaTimeoutSeconds(Number.isFinite(seconds) ? seconds : 0);
|
||||
saveStatus.textContent = 'Gespeichert';
|
||||
setTimeout(() => {
|
||||
saveStatus.textContent = '';
|
||||
}, 1500);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -10,13 +10,23 @@
|
||||
<body>
|
||||
<div id="shell">
|
||||
<div class="header">
|
||||
<button onclick="getNewContent()" class="button" id="reload-button">↻</button>
|
||||
<button onclick="openEinstFirst()" class="button" id="option-button" style="display: none;">⚙️</button>
|
||||
<div class="header-cluster header-left">
|
||||
<button onclick="getNewContent()" class="button icon-button" id="reload-button">↻</button>
|
||||
</div>
|
||||
<h1>Toolbox</h1>
|
||||
<button onclick="openFileSystem()" id="file-system-button" class="button">📁</button>
|
||||
<div class="header-cluster header-right">
|
||||
<div class="button-group">
|
||||
<button onclick="openCmd()" class="button icon-button" id="cmd-button">💻</button>
|
||||
<button onclick="openFileSystem()" id="file-system-button" class="button icon-button">📁</button>
|
||||
</div>
|
||||
<button onclick="openEinstFirst()" class="button icon-button" id="option-button" style="display: none;">⚙</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main" id="toolbox">
|
||||
<!-- Tool Cards werden hier dynamisch geladen -->
|
||||
<div class="add-tool-card" onclick="openAddTool()">
|
||||
<span class="plus-icon">+</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<!--Schmidti.Digital © 2024-->
|
||||
@@ -64,10 +74,19 @@
|
||||
saucer.exposed.open_file_system();
|
||||
}
|
||||
|
||||
function openCmd() {
|
||||
saucer.exposed.open_cmd();
|
||||
}
|
||||
|
||||
function openAddTool() {
|
||||
openFileSystem();
|
||||
}
|
||||
|
||||
function reloadContent() {
|
||||
const toolbox = document.getElementById('toolbox');
|
||||
|
||||
// Toolbox leeren
|
||||
// Toolbox leeren, aber das add-tool-card Element behalten
|
||||
const addToolCard = toolbox.querySelector('.add-tool-card');
|
||||
toolbox.innerHTML = '';
|
||||
|
||||
// Toolbox-Daten neu abrufen
|
||||
@@ -97,6 +116,11 @@
|
||||
toolbox.innerHTML += toolCardHTML;
|
||||
});
|
||||
|
||||
// Das add-tool-card Element wieder hinzufügen
|
||||
if (addToolCard) {
|
||||
toolbox.appendChild(addToolCard);
|
||||
}
|
||||
|
||||
// Überprüfen und Wiederherstellen des Zustands der Buttons
|
||||
document.querySelectorAll('.tool-card').forEach(card => {
|
||||
const toolId = card.getAttribute('data-tool-id');
|
||||
@@ -153,6 +177,9 @@
|
||||
|
||||
const toolbox = document.getElementById('toolbox');
|
||||
|
||||
// Das add-tool-card Element entfernen und später wieder hinzufügen
|
||||
const addToolCard = toolbox.querySelector('.add-tool-card');
|
||||
|
||||
saucer.exposed.getToolboxItems().then(jsonString => {
|
||||
const m_toolboxItems = JSON.parse(jsonString);
|
||||
|
||||
@@ -179,6 +206,11 @@
|
||||
toolbox.innerHTML += toolCardHTML;
|
||||
});
|
||||
|
||||
// Das add-tool-card Element wieder hinzufügen
|
||||
if (addToolCard) {
|
||||
toolbox.appendChild(addToolCard);
|
||||
}
|
||||
|
||||
// Überprüfen und Wiederherstellen des Zustands beim Laden der Seite
|
||||
document.querySelectorAll('.tool-card').forEach(card => {
|
||||
const toolId = card.getAttribute('data-tool-id');
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
height: 100vh;
|
||||
}
|
||||
#shell {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
@@ -38,7 +39,11 @@
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(180deg, rgba(20, 45, 70, 0.85), rgba(12, 28, 45, 0.7));
|
||||
padding: 16px 20px;
|
||||
padding: 12px 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
text-align: center;
|
||||
box-shadow: 0 10px 22px var(--shadow), inset 0 1px 0 var(--shine);
|
||||
border-bottom: 1px solid rgba(140, 210, 255, 0.2);
|
||||
@@ -57,8 +62,6 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
.button {
|
||||
position: absolute;
|
||||
transform: translateY(-50%);
|
||||
background: linear-gradient(180deg, rgba(120, 210, 255, 0.35), rgba(60, 150, 220, 0.55));
|
||||
border: 1px solid rgba(140, 210, 255, 0.45);
|
||||
color: var(--ink);
|
||||
@@ -71,27 +74,50 @@
|
||||
}
|
||||
.button:hover {
|
||||
background: linear-gradient(180deg, rgba(150, 225, 255, 0.45), rgba(80, 170, 235, 0.7));
|
||||
transform: translateY(-52%);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 10px 18px var(--shadow), inset 0 1px 0 var(--shine);
|
||||
}
|
||||
.button:active {
|
||||
transform: translateY(-48%);
|
||||
transform: translateY(1px);
|
||||
box-shadow: 0 4px 10px var(--shadow), inset 0 2px 6px rgba(0,0,0,0.25);
|
||||
}
|
||||
#file-system-button {
|
||||
top: 50%;
|
||||
right: 18px;
|
||||
.header-cluster {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 120px;
|
||||
}
|
||||
#reload-button {
|
||||
top: 50%;
|
||||
left: 18px;
|
||||
.header-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
#option-button {
|
||||
top: 50%;
|
||||
right: 92px;
|
||||
.header-right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.button-group {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 6px;
|
||||
border-radius: 999px;
|
||||
background: rgba(12, 28, 45, 0.55);
|
||||
border: 1px solid rgba(140, 210, 255, 0.25);
|
||||
box-shadow: inset 0 1px 0 var(--shine), 0 8px 16px rgba(4, 10, 16, 0.35);
|
||||
}
|
||||
.icon-button {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 19px;
|
||||
letter-spacing: 0.5px;
|
||||
color: var(--ink-soft);
|
||||
@@ -187,6 +213,36 @@
|
||||
color: #3b2a00;
|
||||
cursor: progress;
|
||||
}
|
||||
.add-tool-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: 2px dashed rgba(140, 210, 255, 0.4);
|
||||
padding: 8px 12px;
|
||||
border-radius: 14px;
|
||||
margin-bottom: 12px;
|
||||
height: calc((62px + 24px) / 2);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
.add-tool-card:hover {
|
||||
border-color: rgba(140, 210, 255, 0.7);
|
||||
background: rgba(18, 40, 60, 0.3);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 16px rgba(4, 10, 16, 0.3);
|
||||
}
|
||||
.add-tool-card .plus-icon {
|
||||
font-size: 24px;
|
||||
color: var(--aqua-2);
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
font-weight: 300;
|
||||
}
|
||||
.add-tool-card:hover .plus-icon {
|
||||
color: var(--aqua-1);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.footer {
|
||||
background: linear-gradient(180deg, rgba(18, 40, 60, 0.65), rgba(8, 18, 28, 0.6));
|
||||
padding: 10px 20px;
|
||||
@@ -195,3 +251,273 @@
|
||||
color: #9bbfd6;
|
||||
border-top: 1px solid rgba(140, 210, 255, 0.2);
|
||||
}
|
||||
.settings-page {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
.settings-page #shell {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
.settings-page .settings-shell {
|
||||
height: 100vh;
|
||||
}
|
||||
.settings-page .settings-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.settings-page .titlebar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 10px 12px;
|
||||
background: linear-gradient(180deg, rgba(20, 45, 70, 0.85), rgba(12, 28, 45, 0.75));
|
||||
border-bottom: 1px solid rgba(140, 210, 255, 0.2);
|
||||
box-shadow: 0 10px 20px var(--shadow), inset 0 1px 0 var(--shine);
|
||||
user-select: none;
|
||||
z-index: 2;
|
||||
}
|
||||
.settings-page .titlebar-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.settings-page .titlebar-title {
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.4px;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.settings-page .titlebar-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
.settings-page .titlebar-btn {
|
||||
border: 1px solid rgba(140, 210, 255, 0.35);
|
||||
background: rgba(10, 26, 40, 0.7);
|
||||
color: var(--ink);
|
||||
width: 30px;
|
||||
height: 26px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: inset 0 1px 0 var(--shine);
|
||||
transition: background 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
.settings-page .titlebar-btn:hover {
|
||||
background: rgba(30, 65, 95, 0.8);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.settings-page .titlebar-btn.close:hover {
|
||||
background: rgba(160, 45, 55, 0.85);
|
||||
}
|
||||
.settings-page .resize-handle {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
}
|
||||
.settings-page .resize-top,
|
||||
.settings-page .resize-bottom {
|
||||
left: 6px;
|
||||
right: 6px;
|
||||
height: 8px;
|
||||
}
|
||||
.settings-page .resize-left,
|
||||
.settings-page .resize-right {
|
||||
top: 6px;
|
||||
bottom: 6px;
|
||||
width: 8px;
|
||||
}
|
||||
.settings-page .resize-top {
|
||||
top: 0;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.settings-page .resize-bottom {
|
||||
bottom: 0;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.settings-page .resize-left {
|
||||
left: 0;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.settings-page .resize-right {
|
||||
right: 0;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.settings-page .resize-top-left,
|
||||
.settings-page .resize-top-right,
|
||||
.settings-page .resize-bottom-left,
|
||||
.settings-page .resize-bottom-right {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
.settings-page .resize-top-left {
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
.settings-page .resize-top-right {
|
||||
top: 0;
|
||||
right: 0;
|
||||
cursor: nesw-resize;
|
||||
}
|
||||
.settings-page .resize-bottom-left {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
cursor: nesw-resize;
|
||||
}
|
||||
.settings-page .resize-bottom-right {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
.settings-page .sidebar {
|
||||
width: 220px;
|
||||
padding: 16px;
|
||||
background: rgba(12, 28, 45, 0.7);
|
||||
border-right: 1px solid rgba(140, 210, 255, 0.2);
|
||||
box-shadow: 8px 0 18px var(--shadow);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.settings-page .sidebar h2 {
|
||||
color: var(--ink-soft);
|
||||
font-size: 16px;
|
||||
margin: 0 0 12px 0;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
.settings-page .sidebar ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.settings-page .sidebar ul li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.settings-page .sidebar ul li a {
|
||||
text-decoration: none;
|
||||
padding: 10px 12px;
|
||||
display: block;
|
||||
border-radius: 10px;
|
||||
background: var(--glass);
|
||||
color: var(--ink);
|
||||
border: 1px solid var(--glass-border);
|
||||
box-shadow: inset 0 1px 0 var(--shine);
|
||||
transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
.settings-page .sidebar ul li a:hover {
|
||||
background: var(--glass-strong);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 8px 16px var(--shadow), inset 0 1px 0 var(--shine);
|
||||
}
|
||||
.settings-page .main-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
.settings-page .header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
}
|
||||
.settings-page .header h1 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.settings-page .back-button {
|
||||
border: 1px solid rgba(140, 210, 255, 0.45);
|
||||
background: linear-gradient(180deg, rgba(120, 210, 255, 0.35), rgba(60, 150, 220, 0.55));
|
||||
color: var(--ink);
|
||||
padding: 8px 14px;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 6px 12px var(--shadow), inset 0 1px 0 var(--shine);
|
||||
transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
.settings-page .back-button:hover {
|
||||
background: linear-gradient(180deg, rgba(150, 225, 255, 0.45), rgba(80, 170, 235, 0.7));
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 10px 18px var(--shadow), inset 0 1px 0 var(--shine);
|
||||
}
|
||||
.settings-page .editor,
|
||||
.settings-page .general {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
min-height: 0;
|
||||
}
|
||||
.settings-page .settings-card {
|
||||
width: min(80%, 520px);
|
||||
background: var(--glass);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 14px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 12px 22px var(--shadow), inset 0 1px 0 var(--shine);
|
||||
}
|
||||
.settings-page .settings-tool-name {
|
||||
margin-bottom: 20px;
|
||||
color: var(--accent);
|
||||
}
|
||||
.settings-page .settings-input,
|
||||
.settings-page .editor textarea {
|
||||
width: 100%;
|
||||
margin-top: 6px;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--glass-border);
|
||||
background: rgba(12, 28, 45, 0.6);
|
||||
color: var(--ink);
|
||||
font-size: 14px;
|
||||
box-shadow: inset 0 1px 0 var(--shine);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.settings-page .editor textarea {
|
||||
height: 70%;
|
||||
font-family: "Consolas", "Courier New", monospace;
|
||||
}
|
||||
.settings-page .editor pre {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
background: rgba(12, 28, 45, 0.6);
|
||||
color: var(--ink);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
overflow-x: auto;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
box-shadow: inset 0 1px 0 var(--shine);
|
||||
}
|
||||
.settings-page .code-keyword {
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
.settings-page .code-string {
|
||||
color: #ffd27a;
|
||||
}
|
||||
.settings-page .code-number {
|
||||
color: #8fe7ff;
|
||||
}
|
||||
.settings-page .code-comment {
|
||||
color: #7aa0b5;
|
||||
font-style: italic;
|
||||
}
|
||||
.settings-page .settings-help,
|
||||
.settings-page .settings-status {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #9bbfd6;
|
||||
}
|
||||
.settings-page .settings-save {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user