Files
flying-jib/index.html
T
2026-07-31 02:05:43 -04:00

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 &amp; 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>