mirror of https://github.com/ospab/ostp.git
386 lines
18 KiB
HTML
386 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>OSTP</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" />
|
|
<link rel="stylesheet" href="styles.css" />
|
|
</head>
|
|
<body>
|
|
<div class="app-root">
|
|
|
|
<!-- Eagle watermark — behind everything, every screen -->
|
|
<div class="watermark" aria-hidden="true">
|
|
<img src="assets/logo.svg" alt="" />
|
|
</div>
|
|
|
|
<!-- ── HOME SCREEN ──────────────────────────────────────── -->
|
|
<div id="home-screen" class="screen active">
|
|
|
|
<header class="topbar">
|
|
<div class="brand">
|
|
<div class="brand-dot" id="brand-dot"></div>
|
|
<span class="brand-name">OSTP</span>
|
|
</div>
|
|
<div class="topbar-right">
|
|
<button id="btn-auto-connect" class="icon-btn" aria-label="Auto" title="Auto-connect">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
|
|
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>
|
|
</svg>
|
|
</button>
|
|
<button id="btn-go-settings" class="icon-btn" aria-label="Settings">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="12" cy="12" r="3"/>
|
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Center stage -->
|
|
<main class="stage">
|
|
|
|
<!-- Orbit rings (animated when connecting/connected) -->
|
|
<div class="orbit-wrap" id="orbit-wrap">
|
|
<div class="orbit orbit-1"></div>
|
|
<div class="orbit orbit-2"></div>
|
|
<div class="orbit orbit-3"></div>
|
|
|
|
<!-- Power button -->
|
|
<button id="btn-connect" class="power-btn" aria-label="Connect / Disconnect">
|
|
<div class="power-icon">
|
|
<svg width="46" height="46" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M18.36 6.64a9 9 0 1 1-12.73 0"/>
|
|
<line x1="12" y1="2" x2="12" y2="12"/>
|
|
</svg>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Status text -->
|
|
<div class="status-block">
|
|
<div id="status-text" class="status-label">Disconnected</div>
|
|
<div id="uptime-text" class="status-sub">Tap to protect your traffic</div>
|
|
</div>
|
|
|
|
<!-- Error banner -->
|
|
<div id="error-banner" class="error-banner hidden"></div>
|
|
|
|
<!-- Connection info (visible when connected) -->
|
|
<div id="connection-info" class="connection-info hidden">
|
|
<div class="server-badge">
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<rect x="2" y="2" width="20" height="8" rx="2"/>
|
|
<rect x="2" y="14" width="20" height="8" rx="2"/>
|
|
<line x1="6" y1="6" x2="6.01" y2="6"/>
|
|
<line x1="6" y1="18" x2="6.01" y2="18"/>
|
|
</svg>
|
|
<span id="server-badge-text">—</span>
|
|
</div>
|
|
|
|
<!-- Live RTT + speeds -->
|
|
<div class="live-stats">
|
|
<div class="live-stat">
|
|
<span class="live-stat-label">RTT</span>
|
|
<span id="live-rtt" class="live-stat-value">--</span>
|
|
</div>
|
|
<div class="live-stat-sep"></div>
|
|
<div class="live-stat">
|
|
<span class="live-stat-label">↓</span>
|
|
<span id="live-down-speed" class="live-stat-value">0 B/s</span>
|
|
</div>
|
|
<div class="live-stat-sep"></div>
|
|
<div class="live-stat">
|
|
<span class="live-stat-label">↑</span>
|
|
<span id="live-up-speed" class="live-stat-value">0 B/s</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</main>
|
|
|
|
<!-- Total traffic bar -->
|
|
<footer class="metrics-bar">
|
|
<div class="metric">
|
|
<div class="metric-icon down-icon">
|
|
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M12 5v14M19 12l-7 7-7-7"/>
|
|
</svg>
|
|
</div>
|
|
<div class="metric-body">
|
|
<span class="metric-label">Download</span>
|
|
<span id="metric-down" class="metric-value">0 B</span>
|
|
</div>
|
|
</div>
|
|
<div class="metric-sep"></div>
|
|
<div class="metric">
|
|
<div class="metric-icon up-icon">
|
|
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M12 19V5M5 12l7-7 7 7"/>
|
|
</svg>
|
|
</div>
|
|
<div class="metric-body">
|
|
<span class="metric-label">Upload</span>
|
|
<span id="metric-up" class="metric-value">0 B</span>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
|
|
<!-- ── SETTINGS SCREEN ──────────────────────────────────── -->
|
|
<div id="settings-screen" class="screen">
|
|
|
|
<header class="topbar">
|
|
<button id="btn-back" class="icon-btn" aria-label="Back">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M19 12H5M12 19l-7-7 7-7"/>
|
|
</svg>
|
|
</button>
|
|
<span class="topbar-title">Profiles</span>
|
|
<button id="btn-add-profile" class="icon-btn add-btn" aria-label="Add profile">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
<line x1="12" y1="5" x2="12" y2="19"/>
|
|
<line x1="5" y1="12" x2="19" y2="12"/>
|
|
</svg>
|
|
</button>
|
|
</header>
|
|
|
|
<div class="settings-body">
|
|
|
|
<!-- Profile list -->
|
|
<div id="profile-list" class="profile-list">
|
|
<div id="profile-empty" class="profile-empty">
|
|
<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<line x1="12" y1="8" x2="12" y2="16"/>
|
|
<line x1="8" y1="12" x2="16" y2="12"/>
|
|
</svg>
|
|
<p>No profiles yet.<br/>Tap <strong>+</strong> to add one.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Client settings -->
|
|
<div class="section-divider"><span>Client Settings</span></div>
|
|
|
|
<div class="client-settings-card">
|
|
|
|
<div class="toggle-row">
|
|
<div class="toggle-text">
|
|
<span class="toggle-name">TUN Mode</span>
|
|
<span class="toggle-hint">Route all system traffic</span>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" id="in-tun-mode" />
|
|
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="toggle-row sub-row" id="group-kill-switch" style="display:none;">
|
|
<div class="toggle-text">
|
|
<span class="toggle-name">Kill Switch</span>
|
|
<span class="toggle-hint">Block traffic if VPN drops</span>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" id="in-kill-switch" />
|
|
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="toggle-row">
|
|
<div class="toggle-text">
|
|
<span class="toggle-name">Multiplexing</span>
|
|
<span class="toggle-hint">Multiple streams over one connection</span>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" id="in-mux-mode" />
|
|
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="inline-field sub-row" id="group-mux-sessions" style="display:none;">
|
|
<span class="field-label">Sessions</span>
|
|
<input id="in-mux-sessions" class="field-input compact" type="number" placeholder="2" min="1" max="8" />
|
|
</div>
|
|
|
|
<div class="inline-field">
|
|
<span class="field-label">MTU</span>
|
|
<input id="in-mtu" class="field-input compact" type="number" placeholder="1350" />
|
|
</div>
|
|
|
|
<div class="inline-field">
|
|
<span class="field-label">DNS</span>
|
|
<input id="in-dns" class="field-input compact" type="text" placeholder="1.1.1.1" />
|
|
</div>
|
|
|
|
<div class="inline-field">
|
|
<span class="field-label">Local Proxy</span>
|
|
<input id="in-socks" class="field-input compact" type="text" placeholder="127.0.0.1:1088" />
|
|
</div>
|
|
|
|
<div class="section-divider-mini"><span>Exceptions / Routing</span></div>
|
|
|
|
<div class="field-group" style="padding: 10px 14px; margin-bottom: 0;">
|
|
<label class="field-label" for="in-ex-domains">Excluded Domains</label>
|
|
<textarea id="in-ex-domains" class="field-input mono" placeholder="google.com, mycompany.internal" rows="2" spellcheck="false"></textarea>
|
|
</div>
|
|
|
|
<div class="field-group" style="padding: 0 14px 10px; margin-bottom: 0;">
|
|
<label class="field-label" for="in-ex-ips">Excluded IPs / Subnets</label>
|
|
<textarea id="in-ex-ips" class="field-input mono" placeholder="192.168.1.0/24, 10.0.0.1" rows="2" spellcheck="false"></textarea>
|
|
</div>
|
|
|
|
<div class="field-group" style="padding: 0 14px 10px; margin-bottom: 0; border-bottom: 1px solid rgba(255,255,255,0.04);">
|
|
<label class="field-label" for="in-ex-procs">Excluded Processes</label>
|
|
<textarea id="in-ex-procs" class="field-input mono" placeholder="chrome.exe, spotify.exe" rows="2" spellcheck="false"></textarea>
|
|
</div>
|
|
|
|
<div class="section-divider-mini"><span>Application</span></div>
|
|
|
|
<div class="toggle-row" style="border-top:none;">
|
|
<div class="toggle-text">
|
|
<span class="toggle-name">Auto-connect</span>
|
|
<span class="toggle-hint">Connect on startup</span>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" id="in-autoconnect" />
|
|
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="toggle-row" style="border-top:none;">
|
|
<div class="toggle-text">
|
|
<span class="toggle-name">Launch at Startup</span>
|
|
<span class="toggle-hint">Start with Windows</span>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" id="in-launch-startup" />
|
|
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="toggle-row" style="border-top:none;">
|
|
<div class="toggle-text">
|
|
<span class="toggle-name">Debug Logs</span>
|
|
<span class="toggle-hint">Verbose output to .log file</span>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" id="in-debug" />
|
|
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
</label>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── ADD PROFILE DROPDOWN ─────────────────────────────── -->
|
|
<div id="add-menu" class="add-menu hidden">
|
|
<button id="add-from-link" class="add-menu-item">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
|
|
From link
|
|
</button>
|
|
<button id="add-from-clipboard" class="add-menu-item">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
|
From clipboard
|
|
</button>
|
|
<button id="add-manually" class="add-menu-item">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
Manually
|
|
</button>
|
|
</div>
|
|
|
|
<!-- ── LINK INPUT MODAL ─────────────────────────────────── -->
|
|
<div id="link-modal" class="modal-overlay hidden">
|
|
<div class="modal-content compact">
|
|
<h3 class="modal-title">Paste link</h3>
|
|
<div class="field-group">
|
|
<input id="link-input" class="field-input mono" type="text" placeholder="ostp://key@host:port" spellcheck="false" />
|
|
</div>
|
|
<div class="modal-actions">
|
|
<button id="btn-link-cancel" class="btn secondary">Cancel</button>
|
|
<button id="btn-link-import" class="btn primary">Import</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── PROFILE EDITOR MODAL ─────────────────────────────── -->
|
|
<div id="profile-modal" class="modal-overlay hidden">
|
|
<div class="modal-content">
|
|
<h3 class="modal-title" id="profile-modal-title">New Profile</h3>
|
|
|
|
<div class="field-group">
|
|
<label class="field-label" for="pm-name">Name</label>
|
|
<input id="pm-name" class="field-input" type="text" placeholder="My Server" />
|
|
</div>
|
|
<div class="field-group">
|
|
<label class="field-label" for="pm-server">Server</label>
|
|
<input id="pm-server" class="field-input mono" type="text" placeholder="host:port" spellcheck="false" />
|
|
</div>
|
|
<div class="field-group">
|
|
<label class="field-label" for="pm-key">Access Key</label>
|
|
<div class="input-wrap">
|
|
<input id="pm-key" class="field-input mono has-icon" type="password" placeholder="Secure access key" spellcheck="false" />
|
|
<button class="peek-btn" id="btn-peek-pm" tabindex="-1" aria-label="Show key">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="field-group">
|
|
<label class="field-label" for="pm-transport">Transport</label>
|
|
<select id="pm-transport" class="field-input">
|
|
<option value="udp">UDP (Default)</option>
|
|
<option value="uot">TCP (UoT)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="modal-actions">
|
|
<button id="btn-profile-cancel" class="btn secondary">Cancel</button>
|
|
<button id="btn-profile-delete" class="btn danger" style="display:none;">Delete</button>
|
|
<button id="btn-profile-save" class="btn primary">Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── SHARE MODAL ──────────────────────────────────────── -->
|
|
<div id="share-modal" class="modal-overlay hidden">
|
|
<div class="modal-content">
|
|
<h3 class="modal-title">Share Profile</h3>
|
|
<p class="modal-text">QR generated locally — the key never leaves this device.</p>
|
|
<div id="share-qr" class="share-qr"></div>
|
|
<input id="share-link" class="field-input mono" type="text" readonly />
|
|
<div class="modal-actions">
|
|
<button id="btn-share-close" class="btn secondary">Close</button>
|
|
<button id="btn-share-copy" class="btn primary">Copy link</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── WINTUN MODAL ─────────────────────────────────────── -->
|
|
<div id="wintun-modal" class="modal-overlay hidden">
|
|
<div class="modal-content">
|
|
<h3 class="modal-title">Wintun Driver Missing</h3>
|
|
<p class="modal-text">TUN mode requires the Wintun network driver.</p>
|
|
<ol class="modal-steps">
|
|
<li>Download <strong>wintun.zip</strong> from wintun.net</li>
|
|
<li>Extract <code>amd64\wintun.dll</code></li>
|
|
<li>Place it here: <code id="wintun-install-path">...</code></li>
|
|
<li>Restart the connection</li>
|
|
</ol>
|
|
<div class="modal-actions">
|
|
<button id="btn-wintun-cancel" class="btn secondary">Cancel</button>
|
|
<a id="btn-wintun-open" href="https://www.wintun.net" target="_blank" class="btn primary">Open wintun.net ↗</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toast notification -->
|
|
<div id="toast" class="toast" role="status" aria-live="polite"></div>
|
|
|
|
</div>
|
|
<script type="module" src="main.js"></script>
|
|
</body>
|
|
</html>
|