feat: Windows stack (daemon, installer, GUI)
Components: - ostp-daemon: Windows Service with Named Pipe IPC - ostp-installer: Setup wizard with admin privileges - ostp-gui: Tauri dark theme UI (450x600) Features: - Background service management (OspabGuard) - IPC commands: CONNECT/DISCONNECT/STATUS - Firewall rules auto-configuration - Wintun driver placeholder (download from wintun.net) - Real-time stats display (upload/download/ping) Note: Requires wintun.dll download for full functionality
This commit is contained in:
117
ostp-gui/ui/app.js
Normal file
117
ostp-gui/ui/app.js
Normal file
@@ -0,0 +1,117 @@
|
||||
const { invoke } = window.__TAURI__.core;
|
||||
|
||||
let isConnected = false;
|
||||
|
||||
// Initialize
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await loadServers();
|
||||
await updateStatus();
|
||||
|
||||
// Update stats every 2 seconds when connected
|
||||
setInterval(async () => {
|
||||
if (isConnected) {
|
||||
await updateStatus();
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
async function loadServers() {
|
||||
try {
|
||||
const servers = await invoke('fetch_servers');
|
||||
const select = document.getElementById('serverSelect');
|
||||
select.innerHTML = '';
|
||||
|
||||
servers.forEach(server => {
|
||||
const option = document.createElement('option');
|
||||
option.value = server;
|
||||
option.textContent = server;
|
||||
select.appendChild(option);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to load servers:', error);
|
||||
showError('Failed to load server list');
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleConnection() {
|
||||
const button = document.getElementById('connectButton');
|
||||
const buttonText = document.getElementById('buttonText');
|
||||
|
||||
button.disabled = true;
|
||||
buttonText.textContent = 'Connecting...';
|
||||
|
||||
try {
|
||||
if (!isConnected) {
|
||||
const response = await invoke('connect_vpn');
|
||||
console.log('Connect response:', response);
|
||||
isConnected = true;
|
||||
updateUI(true);
|
||||
} else {
|
||||
const response = await invoke('disconnect_vpn');
|
||||
console.log('Disconnect response:', response);
|
||||
isConnected = false;
|
||||
updateUI(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Connection error:', error);
|
||||
showError(error);
|
||||
} finally {
|
||||
button.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function updateUI(connected) {
|
||||
const button = document.getElementById('connectButton');
|
||||
const buttonText = document.getElementById('buttonText');
|
||||
const statusIndicator = document.getElementById('statusIndicator');
|
||||
const statsGrid = document.getElementById('statsGrid');
|
||||
|
||||
if (connected) {
|
||||
button.classList.add('connected');
|
||||
buttonText.textContent = 'Disconnect';
|
||||
statusIndicator.textContent = 'Connected';
|
||||
statusIndicator.classList.add('connected');
|
||||
statsGrid.style.display = 'grid';
|
||||
} else {
|
||||
button.classList.remove('connected');
|
||||
buttonText.textContent = 'Connect';
|
||||
statusIndicator.textContent = 'Disconnected';
|
||||
statusIndicator.classList.remove('connected');
|
||||
statsGrid.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async function updateStatus() {
|
||||
if (!isConnected) return;
|
||||
|
||||
try {
|
||||
const status = await invoke('get_status');
|
||||
const data = JSON.parse(status);
|
||||
|
||||
// Update stats
|
||||
document.getElementById('uploadSpeed').textContent = formatSpeed(data.upload_speed);
|
||||
document.getElementById('downloadSpeed').textContent = formatSpeed(data.download_speed);
|
||||
document.getElementById('ping').textContent = `${data.ping} ms`;
|
||||
} catch (error) {
|
||||
console.error('Failed to update status:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function formatSpeed(bytesPerSecond) {
|
||||
if (bytesPerSecond < 1024) {
|
||||
return `${bytesPerSecond} B/s`;
|
||||
} else if (bytesPerSecond < 1024 * 1024) {
|
||||
return `${(bytesPerSecond / 1024).toFixed(1)} KB/s`;
|
||||
} else {
|
||||
return `${(bytesPerSecond / (1024 * 1024)).toFixed(2)} MB/s`;
|
||||
}
|
||||
}
|
||||
|
||||
function showSettings() {
|
||||
alert('Settings panel coming soon!');
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
// TODO: Better error UI
|
||||
alert(`Error: ${message}`);
|
||||
}
|
||||
Reference in New Issue
Block a user