wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
<!--
  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 &lt;this-host&gt;:{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>