Added Shell Page
This commit is contained in:
90
src/js/shell.js
Normal file
90
src/js/shell.js
Normal file
@@ -0,0 +1,90 @@
|
||||
// js/shell.js — SPA-safe interactive shell with history + Ctrl-L clear
|
||||
(() => {
|
||||
if (window.shellInitialized) return;
|
||||
window.shellInitialized = true;
|
||||
|
||||
document.addEventListener('page-loaded', (e) => {
|
||||
if (e.detail.page !== 'shell') return;
|
||||
|
||||
console.log('[shell.js] Initializing shell...');
|
||||
|
||||
const form = document.getElementById('shellForm');
|
||||
const input = document.getElementById('shellInput');
|
||||
const output = document.getElementById('shellOutput');
|
||||
const runBtn = document.getElementById('runBtn');
|
||||
if (!form || !input || !output || !runBtn) return;
|
||||
|
||||
// ----- History -----
|
||||
const history = [];
|
||||
let histIndex = -1;
|
||||
|
||||
function appendLine(text, type = 'out') {
|
||||
const line = document.createElement('pre');
|
||||
line.className = `line ${type}`;
|
||||
line.textContent = text;
|
||||
output.appendChild(line);
|
||||
output.scrollTop = output.scrollHeight;
|
||||
}
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const cmd = input.value.trim();
|
||||
if (!cmd) return;
|
||||
|
||||
history.push(cmd);
|
||||
histIndex = history.length;
|
||||
appendLine(`$ ${cmd}`, 'cmd');
|
||||
input.value = '';
|
||||
runBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const res = await fetch('includes/shell_exec.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({ command: cmd })
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.error) appendLine(data.error, 'err');
|
||||
if (data.output) appendLine(data.output, 'out');
|
||||
} catch (err) {
|
||||
appendLine(`Error: ${err.message}`, 'err');
|
||||
} finally {
|
||||
runBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// ----- Keyboard handlers -----
|
||||
input.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'ArrowUp') {
|
||||
if (histIndex > 0) {
|
||||
histIndex--;
|
||||
input.value = history[histIndex];
|
||||
setTimeout(() => input.setSelectionRange(input.value.length, input.value.length), 0);
|
||||
}
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowDown') {
|
||||
if (histIndex < history.length - 1) {
|
||||
histIndex++;
|
||||
input.value = history[histIndex];
|
||||
} else {
|
||||
histIndex = history.length;
|
||||
input.value = '';
|
||||
}
|
||||
e.preventDefault();
|
||||
} else if (e.key.toLowerCase() === 'l' && e.ctrlKey) {
|
||||
// Ctrl+L clear screen
|
||||
output.innerHTML = '';
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
console.log('[shell.js] Shell initialized.');
|
||||
console.log('💡 Usage');
|
||||
console.log('Shortcut Action');
|
||||
console.log('↑ / ↓ Browse previous commands');
|
||||
console.log('Ctrl + L Clear the screen');
|
||||
console.log('Enter Execute command');
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user