PTY terminals now survive browser refresh and close. Session manager owns PTY lifecycle independently of WebSocket connections, with background readers storing scrollback for replay on reconnect. Desktop state (open apps, active app, terminal tabs) persists server-side and restores automatically on login. Auth tokens moved to localStorage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
53 lines
1.7 KiB
JavaScript
53 lines
1.7 KiB
JavaScript
/* Atlus — Login screen logic */
|
|
(function () {
|
|
'use strict';
|
|
|
|
// Redirect to desktop if already authenticated
|
|
const token = localStorage.getItem('atlus_token');
|
|
if (token) {
|
|
window.location.href = '/desktop';
|
|
return;
|
|
}
|
|
|
|
const form = document.getElementById('loginForm');
|
|
const usernameInput = document.getElementById('username');
|
|
const passwordInput = document.getElementById('password');
|
|
const loginBtn = document.getElementById('loginBtn');
|
|
const errorEl = document.getElementById('loginError');
|
|
|
|
form.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
errorEl.textContent = '';
|
|
loginBtn.disabled = true;
|
|
loginBtn.textContent = 'Signing in…';
|
|
|
|
try {
|
|
const res = await fetch('/api/auth/login', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
username: usernameInput.value.trim(),
|
|
password: passwordInput.value,
|
|
}),
|
|
});
|
|
|
|
if (!res.ok) {
|
|
const data = await res.json().catch(() => ({}));
|
|
throw new Error(data.detail || 'Invalid credentials');
|
|
}
|
|
|
|
const data = await res.json();
|
|
localStorage.setItem('atlus_token', data.token);
|
|
localStorage.setItem('atlus_user', data.username);
|
|
window.location.href = '/desktop';
|
|
} catch (err) {
|
|
errorEl.textContent = err.message;
|
|
loginBtn.disabled = false;
|
|
loginBtn.textContent = 'Sign In';
|
|
passwordInput.value = '';
|
|
passwordInput.focus();
|
|
}
|
|
});
|
|
|
|
usernameInput.focus();
|
|
})();
|