Spaces:
Running
Running
Update templates/index.html
Browse files- templates/index.html +63 -57
templates/index.html
CHANGED
|
@@ -63,48 +63,47 @@
|
|
| 63 |
.info-log { color: #007bff; }
|
| 64 |
.test-pass { color: #28a745; font-weight: bold; }
|
| 65 |
|
| 66 |
-
/* --- НОВЫЙ СТЕЛС-
|
| 67 |
-
.stealth-
|
| 68 |
-
display: flex;
|
|
|
|
| 69 |
background-color: #eaedf1;
|
| 70 |
-
padding: 4px 15px;
|
| 71 |
border-top: 1px solid var(--gray-border);
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
align-items: center;
|
| 74 |
gap: 10px;
|
| 75 |
-
z-index: 5;
|
| 76 |
}
|
|
|
|
| 77 |
.stealth-label { font-size: 12px; color: var(--text-muted); font-family: monospace; white-space: nowrap; }
|
| 78 |
-
.stealth-field { flex: 1; border: 1px solid var(--gray-border); border-radius: 3px; padding: 4px 8px; font-size: 13px; font-family: 'Segoe UI', sans-serif; }
|
| 79 |
.stealth-field:focus { outline: 1px solid var(--blue-primary); }
|
| 80 |
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
right: 10px;
|
| 89 |
-
width: 380px;
|
| 90 |
-
max-height: 360px;
|
| 91 |
-
background: rgba(255, 255, 255, 0.97);
|
| 92 |
-
border: 1px solid #ccc;
|
| 93 |
-
box-shadow: 0px 4px 15px rgba(0,0,0,0.2);
|
| 94 |
-
border-radius: 4px;
|
| 95 |
-
z-index: 9999;
|
| 96 |
-
flex-direction: column;
|
| 97 |
overflow-y: auto;
|
| 98 |
-
padding: 12px;
|
| 99 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 100 |
font-size: 13px;
|
| 101 |
color: #2c3e50;
|
|
|
|
| 102 |
}
|
| 103 |
-
|
| 104 |
-
.stealth-
|
| 105 |
-
.stealth-
|
| 106 |
-
.stealth-
|
|
|
|
| 107 |
.loading-stealth { color: #d35400; font-weight: bold; font-family: monospace; }
|
|
|
|
|
|
|
| 108 |
</style>
|
| 109 |
</head>
|
| 110 |
<body>
|
|
@@ -152,13 +151,14 @@
|
|
| 152 |
<div id="output" class="output-body">Process finished with exit code 0</div>
|
| 153 |
</div>
|
| 154 |
</div>
|
| 155 |
-
|
| 156 |
-
<div id="stealth-modal" class="stealth-modal"></div>
|
| 157 |
</div>
|
| 158 |
|
| 159 |
-
<div id="stealth-
|
| 160 |
-
<
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
| 162 |
</div>
|
| 163 |
|
| 164 |
<footer class="status-bar">
|
|
@@ -178,7 +178,7 @@
|
|
| 178 |
autofocus: true
|
| 179 |
});
|
| 180 |
|
| 181 |
-
//
|
| 182 |
editor.setValue("\nprint(\"Hello, World!\")\n");
|
| 183 |
|
| 184 |
function updateStatusBar() {
|
|
@@ -189,7 +189,7 @@
|
|
| 189 |
editor.on('cursorActivity', updateStatusBar);
|
| 190 |
updateStatusBar();
|
| 191 |
|
| 192 |
-
//
|
| 193 |
async function runFakeConsole() {
|
| 194 |
const outputDiv = document.getElementById("output");
|
| 195 |
outputDiv.innerHTML = "<span class='info-log'>Executing main.py...</span>\n";
|
|
@@ -198,7 +198,7 @@
|
|
| 198 |
}, 600);
|
| 199 |
}
|
| 200 |
|
| 201 |
-
// Парсинг
|
| 202 |
function renderOutput(rawText) {
|
| 203 |
const mathBlocks = [];
|
| 204 |
const protect = (match) => {
|
|
@@ -215,24 +215,26 @@
|
|
| 215 |
return html;
|
| 216 |
}
|
| 217 |
|
| 218 |
-
//
|
| 219 |
async function fetchAI(queryText) {
|
| 220 |
-
const
|
| 221 |
-
|
| 222 |
-
|
|
|
|
|
|
|
| 223 |
|
| 224 |
try {
|
| 225 |
const response = await fetch('/run', {
|
| 226 |
method: 'POST',
|
| 227 |
headers: { 'Content-Type': 'application/json' },
|
| 228 |
-
body: JSON.stringify({ code: queryText })
|
| 229 |
});
|
| 230 |
|
| 231 |
const data = await response.json();
|
| 232 |
|
| 233 |
if (data.output) {
|
| 234 |
-
|
| 235 |
-
renderMathInElement(
|
| 236 |
delimiters: [
|
| 237 |
{ left: '$$', right: '$$', display: true },
|
| 238 |
{ left: '$', right: '$', display: false },
|
|
@@ -243,14 +245,14 @@
|
|
| 243 |
ignoredTags: ["script", "noscript", "style", "textarea", "pre", "code"]
|
| 244 |
});
|
| 245 |
} else if (data.error) {
|
| 246 |
-
|
| 247 |
}
|
| 248 |
} catch (err) {
|
| 249 |
-
|
| 250 |
}
|
| 251 |
}
|
| 252 |
|
| 253 |
-
// Обработка Enter
|
| 254 |
function handleStealthSubmit(e) {
|
| 255 |
if (e.key === 'Enter') {
|
| 256 |
e.preventDefault();
|
|
@@ -258,28 +260,32 @@
|
|
| 258 |
const queryText = queryField.value.trim();
|
| 259 |
|
| 260 |
if (queryText) {
|
| 261 |
-
fetchAI(queryText);
|
| 262 |
-
|
|
|
|
| 263 |
}
|
| 264 |
}
|
| 265 |
}
|
| 266 |
|
| 267 |
-
//
|
| 268 |
-
let
|
| 269 |
|
| 270 |
window.addEventListener('keyup', function(e) {
|
| 271 |
if (e.key === 'Alt') {
|
| 272 |
e.preventDefault();
|
| 273 |
-
const
|
| 274 |
-
const
|
| 275 |
|
| 276 |
-
|
| 277 |
|
| 278 |
-
if (
|
| 279 |
-
|
| 280 |
} else {
|
| 281 |
-
|
| 282 |
-
|
|
|
|
|
|
|
|
|
|
| 283 |
}
|
| 284 |
}
|
| 285 |
});
|
|
|
|
| 63 |
.info-log { color: #007bff; }
|
| 64 |
.test-pass { color: #28a745; font-weight: bold; }
|
| 65 |
|
| 66 |
+
/* --- НОВЫЙ СТЕЛС-КОНТЕЙНЕР (Ввод + Вывод) --- */
|
| 67 |
+
.stealth-container {
|
| 68 |
+
display: flex;
|
| 69 |
+
flex-direction: column;
|
| 70 |
background-color: #eaedf1;
|
|
|
|
| 71 |
border-top: 1px solid var(--gray-border);
|
| 72 |
+
z-index: 5;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
.stealth-input-row {
|
| 76 |
+
display: flex;
|
| 77 |
+
padding: 4px 15px;
|
| 78 |
align-items: center;
|
| 79 |
gap: 10px;
|
|
|
|
| 80 |
}
|
| 81 |
+
|
| 82 |
.stealth-label { font-size: 12px; color: var(--text-muted); font-family: monospace; white-space: nowrap; }
|
| 83 |
+
.stealth-field { flex: 1; border: 1px solid var(--gray-border); border-radius: 3px; padding: 4px 8px; font-size: 13px; font-family: 'Segoe UI', sans-serif; background: white; }
|
| 84 |
.stealth-field:focus { outline: 1px solid var(--blue-primary); }
|
| 85 |
|
| 86 |
+
/* Блок с ответом, который появляется под вводом */
|
| 87 |
+
.stealth-result {
|
| 88 |
+
display: none; /* Скрыто до отправки запроса */
|
| 89 |
+
padding: 10px 15px;
|
| 90 |
+
background-color: white;
|
| 91 |
+
border-top: 1px dashed var(--gray-border);
|
| 92 |
+
max-height: 35vh; /* Занимает не больше трети экрана */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
overflow-y: auto;
|
|
|
|
| 94 |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 95 |
font-size: 13px;
|
| 96 |
color: #2c3e50;
|
| 97 |
+
box-shadow: inset 0 2px 4px rgba(0,0,0,0.05);
|
| 98 |
}
|
| 99 |
+
|
| 100 |
+
.stealth-result h1, .stealth-result h2, .stealth-result h3 { font-size: 1.1em; color: #007bff; margin: 10px 0 5px 0; }
|
| 101 |
+
.stealth-result p { margin: 5px 0; }
|
| 102 |
+
.stealth-result code { background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace; }
|
| 103 |
+
.stealth-result .katex-display { margin: 5px 0; overflow-x: auto; overflow-y: hidden; }
|
| 104 |
.loading-stealth { color: #d35400; font-weight: bold; font-family: monospace; }
|
| 105 |
+
|
| 106 |
+
.status-bar { background-color: #eaedf1; color: var(--text-muted); font-size: 0.8em; padding: 4px 15px; z-index: 4; display: flex; justify-content: flex-start; gap: 15px; border-top: 1px solid var(--gray-border); }
|
| 107 |
</style>
|
| 108 |
</head>
|
| 109 |
<body>
|
|
|
|
| 151 |
<div id="output" class="output-body">Process finished with exit code 0</div>
|
| 152 |
</div>
|
| 153 |
</div>
|
|
|
|
|
|
|
| 154 |
</div>
|
| 155 |
|
| 156 |
+
<div id="stealth-container" class="stealth-container">
|
| 157 |
+
<div class="stealth-input-row">
|
| 158 |
+
<span class="stealth-label">Search in files...</span>
|
| 159 |
+
<input type="text" id="stealth-query" class="stealth-field" placeholder="Enter terms to filter project files..." onkeydown="handleStealthSubmit(event)">
|
| 160 |
+
</div>
|
| 161 |
+
<div id="stealth-result" class="stealth-result"></div>
|
| 162 |
</div>
|
| 163 |
|
| 164 |
<footer class="status-bar">
|
|
|
|
| 178 |
autofocus: true
|
| 179 |
});
|
| 180 |
|
| 181 |
+
// Дефолтный код
|
| 182 |
editor.setValue("\nprint(\"Hello, World!\")\n");
|
| 183 |
|
| 184 |
function updateStatusBar() {
|
|
|
|
| 189 |
editor.on('cursorActivity', updateStatusBar);
|
| 190 |
updateStatusBar();
|
| 191 |
|
| 192 |
+
// Фейковый Run
|
| 193 |
async function runFakeConsole() {
|
| 194 |
const outputDiv = document.getElementById("output");
|
| 195 |
outputDiv.innerHTML = "<span class='info-log'>Executing main.py...</span>\n";
|
|
|
|
| 198 |
}, 600);
|
| 199 |
}
|
| 200 |
|
| 201 |
+
// Парсинг
|
| 202 |
function renderOutput(rawText) {
|
| 203 |
const mathBlocks = [];
|
| 204 |
const protect = (match) => {
|
|
|
|
| 215 |
return html;
|
| 216 |
}
|
| 217 |
|
| 218 |
+
// Запрос к ИИ и вывод в ту же панель
|
| 219 |
async function fetchAI(queryText) {
|
| 220 |
+
const resultDiv = document.getElementById("stealth-result");
|
| 221 |
+
|
| 222 |
+
// Открываем панель с результатами
|
| 223 |
+
resultDiv.style.display = 'block';
|
| 224 |
+
resultDiv.innerHTML = "<span class='loading-stealth'>> decrypting stream...</span>";
|
| 225 |
|
| 226 |
try {
|
| 227 |
const response = await fetch('/run', {
|
| 228 |
method: 'POST',
|
| 229 |
headers: { 'Content-Type': 'application/json' },
|
| 230 |
+
body: JSON.stringify({ code: queryText })
|
| 231 |
});
|
| 232 |
|
| 233 |
const data = await response.json();
|
| 234 |
|
| 235 |
if (data.output) {
|
| 236 |
+
resultDiv.innerHTML = renderOutput(data.output);
|
| 237 |
+
renderMathInElement(resultDiv, {
|
| 238 |
delimiters: [
|
| 239 |
{ left: '$$', right: '$$', display: true },
|
| 240 |
{ left: '$', right: '$', display: false },
|
|
|
|
| 245 |
ignoredTags: ["script", "noscript", "style", "textarea", "pre", "code"]
|
| 246 |
});
|
| 247 |
} else if (data.error) {
|
| 248 |
+
resultDiv.innerHTML = `<span style="color: red;">${data.error}</span>`;
|
| 249 |
}
|
| 250 |
} catch (err) {
|
| 251 |
+
resultDiv.innerText = "Connection lost.";
|
| 252 |
}
|
| 253 |
}
|
| 254 |
|
| 255 |
+
// Обработка Enter
|
| 256 |
function handleStealthSubmit(e) {
|
| 257 |
if (e.key === 'Enter') {
|
| 258 |
e.preventDefault();
|
|
|
|
| 260 |
const queryText = queryField.value.trim();
|
| 261 |
|
| 262 |
if (queryText) {
|
| 263 |
+
fetchAI(queryText);
|
| 264 |
+
// Очищаем поле, чтобы не палить запрос, если кто-то посмотрит
|
| 265 |
+
queryField.value = "";
|
| 266 |
}
|
| 267 |
}
|
| 268 |
}
|
| 269 |
|
| 270 |
+
// Обработчик ALT: скрывает или показывает ВЕСЬ стелс-контейнер
|
| 271 |
+
let isStealthVisible = true;
|
| 272 |
|
| 273 |
window.addEventListener('keyup', function(e) {
|
| 274 |
if (e.key === 'Alt') {
|
| 275 |
e.preventDefault();
|
| 276 |
+
const container = document.getElementById('stealth-container');
|
| 277 |
+
const resultDiv = document.getElementById('stealth-result');
|
| 278 |
|
| 279 |
+
isStealthVisible = !isStealthVisible;
|
| 280 |
|
| 281 |
+
if (isStealthVisible) {
|
| 282 |
+
container.style.display = 'flex';
|
| 283 |
} else {
|
| 284 |
+
container.style.display = 'none';
|
| 285 |
+
// Прячем и очищаем блок с ответом при скрытии,
|
| 286 |
+
// чтобы при следующем открытии он не висел открытым
|
| 287 |
+
resultDiv.style.display = 'none';
|
| 288 |
+
resultDiv.innerHTML = '';
|
| 289 |
}
|
| 290 |
}
|
| 291 |
});
|