Fork Horse repository, listed by its owner. Publisher snapshot.

packages/forkhorse-gatekeeper/app/picker.ts

Snapshot at 34e3175

Containing directory

2,312 bytes · typescriptView raw
1import { followSystemTheme } from "../../forkhorse-dashboard/src/theme.ts";
2import { RpcTarget, newMessagePortRpcSession } from "capnweb";
3import "./picker.css";
4import { mountForkPicker } from "../../forkhorse-dashboard/src/picker.tsx";
5interface Fork {
6  url: string;
7  repoName: string;
8  head: string;
9}
10interface Host extends RpcTarget {
11  gatekeeper: { list(): Promise<Fork[]> };
12  getInitialResource(): Promise<{ resourceUrl: string; resourceUrlPattern: string } | null>;
13  setSelectionReady(ready: boolean): Promise<void>;
14  resize(height: number, layoutHeight: number): Promise<void>;
15}
16let selected: string | undefined;
17let forks: Fork[] = [];
18class Picker extends RpcTarget {
19  async collectResourceUrl(): Promise<string> {
20    if (!selected || !forks.some((f) => f.url === selected))
21      throw new Error("Select an agent fork.");
22    return selected;
23  }
24  updateViewport(): void {}
25  windowResized(): void {}
26}
27const channel = new MessageChannel();
28window.parent.postMessage({ type: "handshake" }, "*", [channel.port2]);
29const host = newMessagePortRpcSession<Host>(channel.port1, new Picker());
30const root = document.getElementById("sidebar")!;
31const picker = mountForkPicker(root, (url) => {
32  selected = url;
33  picker.render(forks, selected, "Only forks owned by your connected agent are listed.");
34  void host.setSelectionReady(forks.some((f) => f.url === selected));
35});
36picker.render([], undefined, "Loading your forks…", true);
37void (async () => {
38  await host.setSelectionReady(false);
39  forks = await host.gatekeeper.list();
40  const initial = await host.getInitialResource();
41  if (initial && forks.some((f) => f.url === initial.resourceUrl)) {
42    selected = initial.resourceUrl;
43    await host.setSelectionReady(true);
44  }
45  picker.render(
46    forks,
47    selected,
48    forks.length
49      ? "Only forks owned by your connected agent are listed."
50      : "This agent has no forks yet.",
51  );
52  await host.resize(300, 300);
53})().catch(() => {
54  picker.render([], undefined, "Fork discovery unavailable. Reconnect your agent.");
55});
56window.addEventListener(
57  "pagehide",
58  () => {
59    picker.dispose();
60    host[Symbol.dispose]();
61    channel.port1.close();
62  },
63  { once: true },
64);
65
66const stopTheme = followSystemTheme();
67window.addEventListener("pagehide", stopTheme, { once: true });
68