223 lines
9.1 KiB
HTML
223 lines
9.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>Flying Jib</title>
|
|
<meta name="theme-color" content="#0c1a22" />
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,[email protected],500;9..144,700&family=Figtree:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
<link rel="stylesheet" href="ui/styles.css" />
|
|
</head>
|
|
<body>
|
|
<div id="titlebar" role="banner">
|
|
<div class="titlebar-left">
|
|
<pear-ctrl></pear-ctrl>
|
|
<span class="titlebar-brand">Flying Jib</span>
|
|
<span class="titlebar-label">P2P Minecraft mesh</span>
|
|
</div>
|
|
<div class="titlebar-right">
|
|
<div id="session-pill" class="session-pill" data-phase="idle" title="Session status">
|
|
<span class="health-dot" aria-hidden="true"></span>
|
|
<span id="session-pill-label">Starting…</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="toast-root" class="toast-root" aria-live="polite"></div>
|
|
|
|
<main class="shell">
|
|
<section class="hero" id="hero" aria-label="Flying Jib">
|
|
<div class="hero-atmosphere" aria-hidden="true"></div>
|
|
<div class="hero-copy">
|
|
<p class="brand">Flying Jib</p>
|
|
<h1 class="headline">Private worlds. Peer tunnels.</h1>
|
|
<p class="lede">Host or join on localhost — Squid stays on your machine; friends arrive through HyperDHT.</p>
|
|
<div class="cta-row">
|
|
<button type="button" class="btn primary" id="cta-host" data-panel="host">Host a world</button>
|
|
<button type="button" class="btn ghost" id="cta-join" data-panel="join">Join with invite</button>
|
|
<button type="button" class="btn text" id="cta-workspace" data-panel="worlds">Open workspace</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="workspace" id="workspace" hidden>
|
|
<nav class="tabs" role="tablist" aria-label="Workspace">
|
|
<button type="button" class="tab is-active" data-panel="worlds" role="tab" aria-selected="true">Worlds</button>
|
|
<button type="button" class="tab" data-panel="host" role="tab">Host</button>
|
|
<button type="button" class="tab" data-panel="join" role="tab">Join</button>
|
|
<button type="button" class="tab" data-panel="status" role="tab">Status</button>
|
|
<button type="button" class="tab" data-panel="logs" role="tab">Logs</button>
|
|
<button type="button" class="tab" data-panel="settings" role="tab">Settings</button>
|
|
</nav>
|
|
|
|
<div class="panels">
|
|
<div class="panel is-active" id="panel-worlds" role="tabpanel">
|
|
<header class="panel-head">
|
|
<div>
|
|
<h2>Worlds</h2>
|
|
<p>Local Anvil folders under app storage.</p>
|
|
</div>
|
|
<button type="button" class="btn ghost sm" id="btn-refresh-worlds">Refresh</button>
|
|
</header>
|
|
<form id="form-create" class="inline-form">
|
|
<label>
|
|
<span>Name</span>
|
|
<input name="name" required placeholder="my-world" autocomplete="off" />
|
|
</label>
|
|
<label>
|
|
<span>Version</span>
|
|
<input name="version" id="create-version" value="1.21.1" />
|
|
</label>
|
|
<button type="submit" class="btn primary" id="btn-create">Create</button>
|
|
</form>
|
|
<ul id="world-list" class="world-list"></ul>
|
|
</div>
|
|
|
|
<div class="panel" id="panel-host" role="tabpanel" hidden>
|
|
<header class="panel-head">
|
|
<div>
|
|
<h2>Host</h2>
|
|
<p>Start Squid on 127.0.0.1 and mint a private-world invite.</p>
|
|
</div>
|
|
</header>
|
|
<form id="form-host" class="stack-form">
|
|
<label>
|
|
<span>World</span>
|
|
<select name="world" id="host-world" required></select>
|
|
</label>
|
|
<div class="form-row">
|
|
<label>
|
|
<span>Local port</span>
|
|
<input name="port" id="host-port" type="number" value="25565" min="1" max="65535" />
|
|
</label>
|
|
<label>
|
|
<span>Display name</span>
|
|
<input name="displayName" id="host-display" value="host" />
|
|
</label>
|
|
</div>
|
|
<label class="check-label">
|
|
<input type="checkbox" name="noExpire" id="host-no-expire" />
|
|
<span>Invite never expires</span>
|
|
</label>
|
|
<button type="submit" class="btn primary" id="btn-host">
|
|
<span class="btn-label">Host & share</span>
|
|
<span class="btn-spinner" hidden aria-hidden="true"></span>
|
|
</button>
|
|
</form>
|
|
<div id="host-result" class="result-card" hidden>
|
|
<div class="result-card-head">
|
|
<h3>Invite</h3>
|
|
<button type="button" class="btn ghost sm" id="btn-copy-invite">Copy</button>
|
|
</div>
|
|
<textarea id="host-invite" readonly rows="3"></textarea>
|
|
<p class="hint" id="host-hint"></p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel" id="panel-join" role="tabpanel" hidden>
|
|
<header class="panel-head">
|
|
<div>
|
|
<h2>Join</h2>
|
|
<p>Paste an fj1. invite; connect Java Edition to your localhost port.</p>
|
|
</div>
|
|
</header>
|
|
<form id="form-join" class="stack-form">
|
|
<label>
|
|
<span>Invite</span>
|
|
<textarea name="invite" required rows="3" placeholder="fj1.…" spellcheck="false"></textarea>
|
|
</label>
|
|
<div class="form-row">
|
|
<label>
|
|
<span>Local port</span>
|
|
<input name="port" id="join-port" type="number" value="25565" min="1" max="65535" />
|
|
</label>
|
|
<label>
|
|
<span>Display name</span>
|
|
<input name="displayName" id="join-display" value="player" />
|
|
</label>
|
|
</div>
|
|
<button type="submit" class="btn primary" id="btn-join">
|
|
<span class="btn-label">Join</span>
|
|
<span class="btn-spinner" hidden aria-hidden="true"></span>
|
|
</button>
|
|
</form>
|
|
<p class="hint success" id="join-hint" hidden></p>
|
|
</div>
|
|
|
|
<div class="panel" id="panel-status" role="tabpanel" hidden>
|
|
<header class="panel-head">
|
|
<div>
|
|
<h2>Status</h2>
|
|
<p>Live session from the Bare control API.</p>
|
|
</div>
|
|
<div class="cta-row">
|
|
<button type="button" class="btn ghost sm" id="btn-refresh">Refresh</button>
|
|
<button type="button" class="btn danger sm" id="btn-stop">Stop session</button>
|
|
</div>
|
|
</header>
|
|
<div id="status-cards" class="status-grid"></div>
|
|
<details class="raw-status">
|
|
<summary>Raw JSON</summary>
|
|
<pre id="status-pre" class="status-pre">Loading…</pre>
|
|
</details>
|
|
</div>
|
|
|
|
<div class="panel" id="panel-logs" role="tabpanel" hidden>
|
|
<header class="panel-head">
|
|
<div>
|
|
<h2>Logs</h2>
|
|
<p>Backend messages and errors from this session.</p>
|
|
</div>
|
|
<div class="cta-row">
|
|
<button type="button" class="btn ghost sm" id="btn-clear-logs">Clear</button>
|
|
<label class="check-label sm">
|
|
<input type="checkbox" id="logs-autoscroll" checked />
|
|
<span>Autoscroll</span>
|
|
</label>
|
|
</div>
|
|
</header>
|
|
<div id="log-view" class="log-view" role="log" aria-live="polite"></div>
|
|
</div>
|
|
|
|
<div class="panel" id="panel-settings" role="tabpanel" hidden>
|
|
<header class="panel-head">
|
|
<div>
|
|
<h2>Settings</h2>
|
|
<p>Defaults for host/join forms. Saved under app storage.</p>
|
|
</div>
|
|
</header>
|
|
<form id="form-settings" class="stack-form">
|
|
<label>
|
|
<span>Display name</span>
|
|
<input name="displayName" id="settings-display" autocomplete="nickname" />
|
|
</label>
|
|
<div class="form-row">
|
|
<label>
|
|
<span>Default port</span>
|
|
<input name="defaultPort" id="settings-port" type="number" min="1" max="65535" />
|
|
</label>
|
|
<label>
|
|
<span>Default MC version</span>
|
|
<input name="defaultVersion" id="settings-version" />
|
|
</label>
|
|
</div>
|
|
<label>
|
|
<span>Invite TTL (hours)</span>
|
|
<input name="inviteTtlHours" id="settings-ttl" type="number" min="1" max="8760" />
|
|
</label>
|
|
<p class="hint" id="settings-storage"></p>
|
|
<button type="submit" class="btn primary" id="btn-settings-save">Save settings</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<p id="boot-error" class="boot-error" hidden></p>
|
|
</main>
|
|
|
|
<script type="module" src="ui/app.js"></script>
|
|
</body>
|
|
</html>
|