<!--
The machines this one carries its worktrees with: pairing, and each peer's
relationship.
A machine panel of the home: peers belong to the machine, not to any of its
projects or worktrees.
-->
<script lang="ts">
import { onMount, onDestroy } from "svelte";
import { peers } from "../../stores/peers.svelte.js";
import PeerCard from "./PeerCard.svelte";
/** Refreshed on a timer because peer state changes without this page acting. */
let timer: ReturnType<typeof setInterval> | null = null;
let code = $state("");
let address = $state("");
let joining = $state(false);
onMount(() => {
peers.load();
timer = setInterval(() => peers.load(), 4000);
});
onDestroy(() => {
if (timer) clearInterval(timer);
});
async function join() {
joining = true;
const ok = await peers.join(code.trim(), address.trim());
joining = false;
if (ok) {
code = "";
address = "";
}
}
</script>
<div class="peers-panel">
{#if peers.error}
<p class="error">{peers.error}</p>
{/if}
<div class="section-head">
<p class="subtle">
{#if peers.machine}
{peers.machine.fingerprint} · peers reach it on port {peers.machine.peer_port}
{:else}
Reading this machine…
{/if}
</p>
<button
class="primary"
disabled={peers.busy === "pair"}
onclick={() => peers.openPairing()}
>
Pair another machine
</button>
</div>
{#if peers.offer}
<div class="offer">
<p>
On the other machine, within {Math.round(peers.offer.expires_in_seconds / 60)}
minutes:
</p>
<code>wsb peer pair {peers.offer.code} --at <this-host>:{peers.offer.peer_port}</code>
<p class="subtle">
Check this fingerprint there before trusting it:
<strong>{peers.offer.fingerprint}</strong>
</p>
</div>
{/if}
<div class="join">
<input class="field-input" placeholder="pairing code from the other machine" bind:value={code} />
<input class="field-input" placeholder="that machine's host:port" bind:value={address} />
<button class="secondary" disabled={joining || !code.trim() || !address.trim()} onclick={join}>
Take the code there
</button>
</div>
{#if !peers.peers.length}
<p class="empty">
No peers yet. Continuity carries a working tree between machines you
have paired — nothing leaves this one until you do.
</p>
{:else}
{#each peers.peers as peer (peer.id)}
<PeerCard {peer} />
{/each}
{/if}
</div>
<style>
.section-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--wb-spacing-10);
}
.error {
color: var(--vscode-errorForeground);
font-size: var(--wb-font-size-12);
}
.offer {
border: 1px solid var(--vscode-panel-border);
padding: var(--wb-spacing-10) var(--wb-spacing-12);
border-radius: var(--wb-corner-radius-4);
margin: var(--wb-spacing-10) 0;
}
.offer code {
display: block;
font-family: var(--vscode-editor-font-family, monospace);
padding: var(--wb-spacing-6) 0;
user-select: all;
}
.join {
display: flex;
gap: var(--wb-spacing-8);
margin: var(--wb-spacing-10) 0 var(--wb-spacing-16);
}
.join input {
flex: 1;
}
</style>