352 lines
23 KiB
HTML
352 lines
23 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>NetDesk — The Fast Self-Hosted Remote Desktop</title>
|
||
<link rel="stylesheet" href="app.css?v=53">
|
||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%233d7eff'/%3E%3Cpath d='M8 20l8-12 8 12-8-4z' fill='white'/%3E%3Crect x='12' y='18' width='8' height='7' rx='2' fill='white'/%3E%3C/svg%3E">
|
||
<link rel="manifest" href="manifest.webmanifest">
|
||
<meta name="theme-color" content="#3d7eff">
|
||
<meta name="robots" content="noindex, nofollow">
|
||
</head>
|
||
<body>
|
||
|
||
<div id="screenConnect">
|
||
<div class="topnote">ⓘ <b>netdesk.space</b> is the only official domain for this NetDesk server. No third-party cloud ever sees your screen.</div>
|
||
|
||
<header class="nav">
|
||
<div class="nav-brand">
|
||
<svg width="30" height="30" viewBox="0 0 32 32"><defs><linearGradient id="ndg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#25d386"/><stop offset="1" stop-color="#16a765"/></linearGradient></defs><rect width="32" height="32" rx="8" fill="url(#ndg)"/><path d="M16 6.5L6.5 18.2C6.1 18.7 6.4 19.4 7 19.4H25C25.6 19.4 25.9 18.7 25.5 18.2L16 6.5Z" fill="#fff"/><path d="M11.8 21H20.2L21.5 26.4C21.6 26.8 21.3 27.2 20.9 27.2H11.1C10.7 27.2 10.4 26.8 10.5 26.4L11.8 21Z" fill="#fff"/></svg>
|
||
<b>NetDesk</b>
|
||
</div>
|
||
<nav class="nav-links">
|
||
<a href="/">Home</a>
|
||
<a href="/features">Features</a>
|
||
<a href="/download">Download</a>
|
||
<button id="btnTheme" class="theme-toggle" title="Switch theme">☀ Light</button>
|
||
<span id="navAuth"></span>
|
||
</nav>
|
||
</header>
|
||
|
||
<section class="hero">
|
||
<div class="hero-copy">
|
||
<h1>The Fast Self-Hosted<br>Remote Desktop</h1>
|
||
<p class="hero-sub">Your own remote access and support software — unattended, silent in the
|
||
background, end-to-end encrypted, with your own server. The alternative to TeamViewer,
|
||
AnyDesk and RustDesk that you fully control.</p>
|
||
<div class="hero-cta">
|
||
<a class="btn-big btn-blue" href="#download">Download <span class="dl-ic">⬇</span></a>
|
||
<a class="btn-big btn-ghost" href="/portal">Self-Hosting</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="hero-card">
|
||
<div class="card" id="connect">
|
||
<h2>Connect to a computer</h2>
|
||
<p class="sub">Enter the remote ID shown by the NetDesk agent.</p>
|
||
<label>Remote ID</label>
|
||
<input id="inId" type="text" inputmode="numeric" pattern="[0-9]*" placeholder="123 456 789" spellcheck="false" autocomplete="off">
|
||
<label>Password</label>
|
||
<div class="pw-wrap">
|
||
<input id="inPw" type="password" placeholder="permanent password" autocomplete="off">
|
||
<button id="btnPwEye" class="ghost" type="button" title="Show password"><svg class="ic" 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>
|
||
<label id="lblTotp" hidden>2FA code</label>
|
||
<input id="inTotp" type="text" inputmode="numeric" maxlength="6" placeholder="6-digit authenticator code" autocomplete="off" hidden>
|
||
<details style="margin-top:14px">
|
||
<summary class="foot" style="cursor:pointer;user-select:none">Advanced — direct connection</summary>
|
||
<label>Server</label>
|
||
<input id="inServer" type="text" placeholder="blank = this server · or ws://PC-IP:8901 for direct LAN" spellcheck="false">
|
||
</details>
|
||
<label class="chk"><input id="inRemember" type="checkbox"> Remember password on this device</label>
|
||
<label class="chk"><input id="inViewOnly" type="checkbox"> View only (no input)</label>
|
||
<button id="btnConnect" class="primary">Connect</button>
|
||
<div id="connectErr" class="error" hidden></div>
|
||
|
||
<style>
|
||
#hostShare{margin-top:22px;padding-top:20px;border-top:1px solid rgba(148,163,184,.25);text-align:center}
|
||
#hostShare .host-or{font-size:12px;color:#8a97ab;letter-spacing:1px;margin-bottom:12px}
|
||
#hostShare h3{margin:0 0 6px;font-size:16px}
|
||
#hostShare .host-sub{margin:0 0 14px;font-size:12.5px;color:#8a97ab;line-height:1.5}
|
||
#hostShare .host-cred{font-size:13px;margin-bottom:14px;color:#cdd6e4}
|
||
#hostShare .host-cred b{font-size:15px;letter-spacing:.5px;color:#3d7eff;font-variant-numeric:tabular-nums}
|
||
#hostShare #btnHostRegen{padding:2px 8px;font-size:13px;vertical-align:middle;margin-left:6px}
|
||
#hostShare .host-status{margin-top:12px;font-size:12.5px;color:#8a97ab;min-height:16px}
|
||
</style>
|
||
<div id="hostShare">
|
||
<div class="host-or">— OR —</div>
|
||
<h3>Share THIS screen</h3>
|
||
<p class="host-sub">Let someone view this computer right from their browser — no app to install.<br>(View-only: they can see & hear it, not control it.)</p>
|
||
<div class="host-cred">ID <b id="hostIdOut">—</b> · Password <b id="hostPwOut">—</b><button id="btnHostRegen" class="tb" title="Generate a new ID + password">↻</button></div>
|
||
<button id="btnHostStart" class="primary">Share my screen</button>
|
||
<button id="btnHostStop" class="tb" hidden>Stop sharing</button>
|
||
<div id="hostStatus" class="host-status"></div>
|
||
</div>
|
||
<div id="myDevsWrap" hidden>
|
||
<div class="ab-head"><span>My computers</span><span class="foot">click to connect</span></div>
|
||
<div id="myDevs"></div>
|
||
</div>
|
||
<div id="abookWrap">
|
||
<div class="ab-head"><span>Address book</span><button id="btnAbAdd" class="tb">+ Save current</button></div>
|
||
<div id="abook" hidden></div>
|
||
</div>
|
||
<div class="hint">
|
||
Direct connection (no server): put <code>ws://IP:8901</code> in the Server
|
||
field when the host runs with <code>--listen</code> on your LAN or via port-forward.
|
||
</div>
|
||
<div class="form-foot">
|
||
<span class="foot">NetDesk viewer</span>
|
||
<span style="display:flex;gap:8px;align-items:center">
|
||
<span id="authChip" class="foot" hidden></span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
|
||
</div><!-- /screenConnect -->
|
||
|
||
<div id="authModal" class="modal-wrap" hidden>
|
||
<div class="modal-card auth-card">
|
||
<button id="btnAuthClose" class="modal-x" title="Close">✕</button>
|
||
<div class="auth-head">
|
||
<span class="auth-logo"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M12 3.2L3.2 12.6C2.8 13 3.1 13.7 3.7 13.7H20.3C20.9 13.7 21.2 13 20.8 12.6L12 3.2Z" fill="#fff"/><path d="M8.7 15.1H15.3L16.4 20.3C16.5 20.7 16.2 21 15.8 21H8.2C7.8 21 7.5 20.7 7.6 20.3L8.7 15.1Z" fill="#fff"/></svg></span>
|
||
<span class="auth-brand">NetDesk <i>Account</i></span>
|
||
</div>
|
||
<div class="auth-tabs">
|
||
<button class="atab on" data-t="in">Sign in</button>
|
||
<button class="atab" data-t="up">Create account</button>
|
||
<button class="atab" data-t="fp">Forgot</button>
|
||
<button class="atab" data-t="2fa" id="atab2fa" hidden>Two-factor</button>
|
||
</div>
|
||
<div class="apane" id="pane-in">
|
||
<h3 class="auth-title">Welcome back</h3>
|
||
<p class="auth-sub">Sign in to see your computers and connect in one click.</p>
|
||
<label class="auth-lbl" for="auEmail">Email address</label>
|
||
<input id="auEmail" type="email" placeholder="you@company.com" autocomplete="email" spellcheck="false">
|
||
<label class="auth-lbl" for="auPass">Password</label>
|
||
<input id="auPass" type="password" placeholder="••••••••••" autocomplete="current-password">
|
||
<label class="auth-lbl" id="auTotpLbl" for="auTotp" hidden>Two-factor code</label>
|
||
<input id="auTotp" type="text" inputmode="numeric" maxlength="6" placeholder="6-digit authenticator code" autocomplete="one-time-code" hidden>
|
||
<button id="auGo" class="primary auth-cta">Sign in →</button>
|
||
<div id="ssoWrap" hidden style="margin-top:12px">
|
||
<div style="display:flex;align-items:center;gap:10px;color:var(--faint);font-size:12px;margin:4px 0 10px"><span style="flex:1;height:1px;background:var(--border)"></span>OR<span style="flex:1;height:1px;background:var(--border)"></span></div>
|
||
<a id="ssoBtn" class="btn-big btn-ghost" href="/saml/login?RelayState=/app" style="width:100%;justify-content:center;box-sizing:border-box">Sign in with SSO</a>
|
||
</div>
|
||
</div>
|
||
<div class="apane" id="pane-up" hidden>
|
||
<h3 class="auth-title">Create your account</h3>
|
||
<p class="auth-sub">Free for individuals — your fleet syncs between the desktop app and this site.</p>
|
||
<label class="auth-lbl" for="auEmail2">Email address</label>
|
||
<input id="auEmail2" type="email" placeholder="you@company.com" autocomplete="email" spellcheck="false">
|
||
<label class="auth-lbl" for="auPass2">Password</label>
|
||
<input id="auPass2" type="password" placeholder="8+ characters" autocomplete="new-password">
|
||
<button id="auGo2" class="primary auth-cta">Create account →</button>
|
||
<div class="foot">Works right away — sign in with the same account in the NetDesk desktop app and your computers appear here automatically.</div>
|
||
</div>
|
||
<div class="apane" id="pane-fp" hidden>
|
||
<h3 class="auth-title">Reset your password</h3>
|
||
<p class="auth-sub">We'll email you a secure link to choose a new one.</p>
|
||
<label class="auth-lbl" for="auEmail3">Account email</label>
|
||
<input id="auEmail3" type="email" placeholder="you@company.com" autocomplete="email" spellcheck="false">
|
||
<button id="auGo3" class="primary auth-cta">Send reset link</button>
|
||
</div>
|
||
<div class="apane" id="pane-rs" hidden>
|
||
<h3 class="auth-title">Choose a new password</h3>
|
||
<label class="auth-lbl" for="auPass4">New password</label>
|
||
<input id="auPass4" type="password" placeholder="8+ characters" autocomplete="new-password">
|
||
<button id="auGo4" class="primary auth-cta">Set new password</button>
|
||
</div>
|
||
<div class="apane" id="pane-2fa" hidden>
|
||
<h3 class="auth-title">Two-factor authentication</h3>
|
||
<p class="auth-sub">Add a 6-digit authenticator code on top of your password at sign-in.</p>
|
||
<div id="tf2Status" class="foot">Checking…</div>
|
||
<button id="tf2Enable" class="primary auth-cta" hidden>Enable 2FA →</button>
|
||
<div id="tf2Enroll" hidden>
|
||
<p class="auth-sub">Add this secret to your authenticator app (Google Authenticator, Authy, 1Password…), then enter a code to confirm.</p>
|
||
<label class="auth-lbl">Secret</label>
|
||
<input id="tf2Secret" type="text" readonly spellcheck="false">
|
||
<div id="tf2Uri" class="foot" style="word-break:break-all;margin:4px 0 8px"></div>
|
||
<label class="auth-lbl" for="tf2Code">Confirmation code</label>
|
||
<input id="tf2Code" type="text" inputmode="numeric" maxlength="6" placeholder="6-digit code" autocomplete="one-time-code">
|
||
<button id="tf2Confirm" class="primary auth-cta">Confirm & enable →</button>
|
||
</div>
|
||
<div id="tf2DisableWrap" hidden>
|
||
<label class="auth-lbl" for="tf2DisCode">Enter a current code to turn 2FA off</label>
|
||
<input id="tf2DisCode" type="text" inputmode="numeric" maxlength="6" placeholder="6-digit code" autocomplete="one-time-code">
|
||
<button id="tf2Disable" class="auth-cta">Disable 2FA</button>
|
||
</div>
|
||
</div>
|
||
<div id="auMsg" class="error" hidden></div>
|
||
<div id="auOk" class="auok" hidden></div>
|
||
<div class="auth-secure">🔒 TLS 1.3 in transit · passwords stored as PBKDF2-SHA256 · 200,000 rounds</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="screenSession" class="screen" hidden>
|
||
<div id="toolbar">
|
||
<div class="tb-group">
|
||
<span id="tbTitle" class="tb-title">NetDesk</span>
|
||
<span id="tbState" class="state">connecting…</span>
|
||
</div>
|
||
<div class="sep"></div>
|
||
<div class="tb-group" id="menubar">
|
||
<button class="tb menu-btn" data-menu="mActions">Actions ▾</button>
|
||
<button class="tb menu-btn" data-menu="mView">View ▾</button>
|
||
<button class="tb menu-btn" data-menu="mComm">Communicate ▾</button>
|
||
<button class="tb menu-btn" data-menu="mExtras">Extras ▾</button>
|
||
</div>
|
||
<div class="tmenu" id="mComm" hidden>
|
||
<button class="mi" id="miMsg">Send message… (chat)</button>
|
||
<button class="mi mtoggle" id="miSound">Play remote computer sound<span class="mtick">✓</span></button>
|
||
<div class="msep"></div>
|
||
<button class="mi mtoggle" id="miVoice" title="Talk to the person at the host PC using your microphone">Start voice call (your mic)<span class="mtick">✓</span></button>
|
||
</div>
|
||
<div class="tmenu" id="mActions" hidden>
|
||
<button class="mi" data-sys="lock">Lock remote computer</button>
|
||
<button class="mi" data-sys="logoff" data-confirm="Sign out the remote user?">Sign out on remote computer</button>
|
||
<button class="mi" data-sys="reboot" data-confirm="Reboot the remote computer? The session will end.">Remote reboot</button>
|
||
<button class="mi" data-sys="cad">Send Ctrl + Alt + Del</button>
|
||
<div class="msep"></div>
|
||
<button class="mi" id="miWol">Wake a PC on this network (Wake-on-LAN)…</button>
|
||
<div class="msep"></div>
|
||
<button class="mi mtoggle" id="miBlockInput">Block remote user's input<span class="mtick">✓</span></button>
|
||
<button class="mi mtoggle" id="miLockEnd">Lock on session end<span class="mtick">✓</span></button>
|
||
<div class="msep"></div>
|
||
<button class="mi" id="miInfo">Session information…</button>
|
||
</div>
|
||
<div class="tmenu" id="mView" hidden>
|
||
<div class="mhead">Monitor</div>
|
||
<div id="miMons"></div>
|
||
<div class="mhead">Quality</div>
|
||
<div id="miQual"></div>
|
||
<div class="mhead">Scaling</div>
|
||
<button class="mi mradio" data-scale="fit">Best fit<span class="mtick">✓</span></button>
|
||
<button class="mi mradio" data-scale="orig">Original (1:1, scroll)<span class="mtick">✓</span></button>
|
||
<div class="mhead">Screen resolution</div>
|
||
<div id="miModes"><button class="mi" id="miModesLoad">Load resolutions…</button></div>
|
||
<div class="msep"></div>
|
||
<button class="mi mtoggle" id="miWallpaper">Hide wallpaper<span class="mtick">✓</span></button>
|
||
<button class="mi" id="miRefresh">Refresh screen</button>
|
||
</div>
|
||
<div class="tmenu" id="mExtras" hidden>
|
||
<button class="mi" id="miFiles">File transfer</button>
|
||
<button class="mi" id="miChat">Chat</button>
|
||
<button class="mi" id="miShot">Save screenshot</button>
|
||
<button class="mi" id="miRec">Record session (WebM)</button>
|
||
</div>
|
||
<div class="tb-group">
|
||
<select id="selMonitor" title="Monitor"></select>
|
||
<select id="selQuality" title="Quality">
|
||
<option value="auto" selected>Auto (adaptive)</option>
|
||
<option value="low">Low · 15fps · 2 Mbps</option>
|
||
<option value="balanced">Balanced · 30fps · 6 Mbps</option>
|
||
<option value="high">High · 30fps · 12 Mbps</option>
|
||
<option value="extreme">Extreme · 60fps · 20 Mbps</option>
|
||
</select>
|
||
</div>
|
||
<div class="sep"></div>
|
||
<div class="tb-group">
|
||
<button id="btnViewOnly" class="tb" title="Toggle remote input"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3l18 18"/><path d="M10.6 5.1A9.8 9.8 0 0 1 12 5c7 0 11 8 11 8a13.2 13.2 0 0 1-1.7 2.4"/><path d="M6.6 6.6C4 8.3 2 12 2 12s4 8 12 8a9.7 9.7 0 0 0 4.3-1"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/></svg><span>Input</span></button>
|
||
<button id="btnOsk" class="tb touch-only" title="Open the on-screen keyboard">⌨<span>Type</span></button>
|
||
<button id="btnKbdLock" class="tb" title="Capture system keys while fullscreen"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><path d="M6 10h.01M10 10h.01M14 10h.01M18 10h.01M7 14h10"/></svg><span>Keys</span></button>
|
||
<button id="btnMonCycle" class="tb" title="Switch monitor" hidden><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="13" height="9" rx="1.5"/><rect x="9" y="11" width="13" height="9" rx="1.5"/></svg><span id="monCycleLbl">1/2</span></button>
|
||
<button id="btnFullscreen" class="tb" title="Fullscreen"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3M16 3h3a2 2 0 0 1 2 2v3M8 21H5a2 2 0 0 1-2-2v-3M16 21h3a2 2 0 0 0 2-2v-3"/></svg></button>
|
||
<button id="btnClipboard" class="tb" title="Clipboard sync"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="8" y="2" width="8" height="4" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/></svg></button>
|
||
<button id="btnFiles" class="tb" title="File manager"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg></button>
|
||
<button id="btnChat" class="tb" title="Chat"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></button>
|
||
<button id="btnAudio" class="tb" title="Host audio: off → system → microphone"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H2v6h4l5 4V5z"/><path d="M15.5 8.5a5 5 0 0 1 0 7M19 5a8 8 0 0 1 0 14"/></svg><span id="audioLbl">Audio</span></button>
|
||
<button id="btnSys" class="tb" title="Power / processes"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18.4 6.6a9 9 0 1 1-12.8 0"/><path d="M12 2v10"/></svg></button>
|
||
<button id="btnPrivacy" class="tb" title="Privacy mode"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.9 17.9A9.8 9.8 0 0 1 12 20c-8 0-11-8-11-8a13.4 13.4 0 0 1 4.1-4.4M9.9 4.2A9.6 9.6 0 0 1 12 4c8 0 11 8 11 8a13.5 13.5 0 0 1-2.2 3.1"/><path d="M3 3l18 18"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/></svg></button>
|
||
<button id="btnRec" class="tb" title="Record session"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="4" fill="currentColor" stroke="none"/></svg></button>
|
||
</div>
|
||
<div class="sep"></div>
|
||
<div class="tb-group">
|
||
<span id="tbStats" class="stats"></span>
|
||
<button id="btnDisconnect" class="tb danger" title="Disconnect"><svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg><span>Disconnect</span></button>
|
||
</div>
|
||
<button id="tbTab" title="Hide the toolbar">▲</button>
|
||
</div>
|
||
<button id="tbShow" title="Show the toolbar" hidden>▼ NetDesk</button>
|
||
<input id="oskInput" type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" aria-hidden="true">
|
||
|
||
<div id="stage">
|
||
<canvas id="canvas" tabindex="0"></canvas>
|
||
<img id="remoteCursor" alt="" hidden>
|
||
<div id="dropHint" hidden>Drop files to upload to the remote desktop</div>
|
||
<div id="banner" class="banner" hidden></div>
|
||
<div id="localCursor" hidden></div>
|
||
|
||
<div id="filePanel" class="panel" data-title="Files" hidden>
|
||
<div class="panel-head" data-panel="filePanel"><span>Remote files</span><button class="tb" data-min="filePanel" title="Minimize to edge">»</button><button class="tb" id="btnFilesClose" title="Close">✕</button></div>
|
||
<div class="file-path">
|
||
<input id="filePath" spellcheck="false">
|
||
<button id="btnFileGo" class="tb">Go</button>
|
||
<button id="btnFileUp" class="tb" title="Up">⬆</button>
|
||
<button id="btnFileHome" class="tb" title="Drives">💾</button>
|
||
</div>
|
||
<div id="fileList" class="file-list"></div>
|
||
<div class="panel-foot">
|
||
<button id="btnFileMkdir" class="tb">New folder</button>
|
||
<button id="btnFileUpload" class="tb">Upload…</button>
|
||
<input id="fileInput" type="file" multiple hidden>
|
||
<button id="btnDirUpload" class="tb" title="Upload a folder">Folder…</button>
|
||
<input id="dirInput" type="file" webkitdirectory multiple hidden>
|
||
<span id="fileStatus" class="stats"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="chatPanel" class="panel" data-title="Chat" hidden>
|
||
<div class="panel-head" data-panel="chatPanel"><span>Chat</span><button class="tb" data-min="chatPanel" title="Minimize to edge">»</button><button class="tb" id="btnChatClose" title="Close">✕</button></div>
|
||
<div id="chatLog" class="chat-log"></div>
|
||
<div class="chat-input">
|
||
<input id="chatText" placeholder="Type a message…">
|
||
<button id="chatSend" class="tb">Send</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="sysPanel" class="panel" data-title="Remote power" hidden>
|
||
<div class="panel-head" data-panel="sysPanel"><span>Remote power</span><button class="tb" data-min="sysPanel" title="Minimize to edge">»</button><button class="tb" id="btnSysClose" title="Close">✕</button></div>
|
||
<details class="sec" open>
|
||
<summary>Power actions<span class="chev">▾</span></summary>
|
||
<div class="sys-grid">
|
||
<button class="tb" data-cmd="lock">Lock workstation</button>
|
||
<button class="tb" data-cmd="logoff">Sign out user</button>
|
||
<button class="tb" data-cmd="reboot">Reboot</button>
|
||
<button class="tb danger" data-cmd="shutdown">Shut down</button>
|
||
</div>
|
||
<div class="panel-foot">
|
||
<input id="sysCmd" placeholder="run a command on host (cmd /c …)">
|
||
<button id="btnSysRun" class="tb">Run</button>
|
||
</div>
|
||
</details>
|
||
<details class="sec" open>
|
||
<summary>Options<span class="chev">▾</span></summary>
|
||
<div class="panel-foot">
|
||
<label class="chk" style="margin:0"><input id="chkLockOnEnd" type="checkbox"> Lock PC when I disconnect</label>
|
||
</div>
|
||
</details>
|
||
<details class="sec">
|
||
<summary>Processes<span class="chev">▾</span><button id="btnProcRefresh" class="tb" style="margin-left:auto">↻ Refresh</button></summary>
|
||
<div id="procList" class="file-list" style="max-height:200px"></div>
|
||
</details>
|
||
<details class="sec">
|
||
<summary>TCP tunnel <span class="muted" style="text-transform:none">(portal sign-in)</span><span class="chev">▾</span></summary>
|
||
<div class="panel-foot">
|
||
<input id="tnlPort" placeholder="port on the host" style="width:120px">
|
||
<button id="btnTnlOpen" class="tb">Connect</button>
|
||
<span id="tnlStatus" class="stats"></span>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="app.js?v=55"></script>
|
||
<script src="host.js?v=5"></script>
|
||
</body>
|
||
</html>
|