OXYGENHUB
◆ main oxygenhub-vscode / src / diffusionview.ts
2.9 KiB · last changed feat: a Diffusion view, what each repository takes from and diffuses to (closes #5) 22 days ago source blame history raw
1
// Diffusion in the editor, without VS Code (oxygenhub-vscode#5): how a pin
2
// between an upstream and its consumer looks. The hub's pill has two halves,
3
// the upstream's state and the consumer's; a tree row has one icon, so it
4
// shows the more urgent of the two and says both in words.
5
6
import type { DiffusionHalf, DiffusionPin } from "./hubapi";
7
8
/** A codicon and a theme colour id. */
9
export interface Look {
10
  icon: string;
11
  color: string;
12
}
13
14
/** Most urgent first: a failure, then what nothing checked, then waiting. */
15
const URGENCY = ["red", "amber", "grey", "green", "off"];
16
17
/** The tone a row shows: the more urgent half, ignoring a consumer that does not follow. */
18
export function tone(pin: DiffusionPin): string {
19
  const tones = [pin.upstream_state.tone, pin.consumer_state.tone].filter((t) => t !== "off");
20
  return tones.sort((a, b) => rank(a) - rank(b))[0] ?? "off";
21
}
22
23
function rank(t: string): number {
24
  const i = URGENCY.indexOf(t);
25
  return i < 0 ? URGENCY.length : i;
26
}
27
28
export function look(t: string): Look {
29
  switch (t) {
30
    case "green":
31
      return { icon: "pass-filled", color: "testing.iconPassed" };
32
    case "red":
33
      return { icon: "error", color: "testing.iconFailed" };
34
    case "amber":
35
      return { icon: "warning", color: "list.warningForeground" };
36
    case "grey":
37
      return { icon: "clock", color: "testing.iconQueued" };
38
    default:
39
      return { icon: "circle-outline", color: "disabledForeground" };
40
  }
41
}
42
43
/** The row's name: the repository on the other end of the pin. */
44
export function pinLabel(pin: DiffusionPin, side: "takes" | "gives"): string {
45
  return side === "takes" ? pin.upstream : pin.consumer;
46
}
47
48
/** "untested │ passes · 2 behind · bump #304", as the hub's pill reads. */
49
export function pinDescription(pin: DiffusionPin): string {
50
  const parts = [`${pin.upstream_state.word} │ ${pin.consumer_state.word}`];
51
  if (pin.behind !== null && pin.behind !== undefined && pin.behind > 0) {
52
    parts.push(`${pin.behind} behind`);
53
  }
54
  if (pin.bump !== null && pin.bump !== undefined) {
55
    parts.push(`bump #${pin.bump}`);
56
  }
57
  return parts.join(" · ");
58
}
59
60
const FOLLOW: Record<string, string> = { off: "does not follow", green: "follows when the upstream is green", any: "follows every move" };
61
62
/** The tooltip, in Markdown: both halves' sentences, then the pin. */
63
export function pinTooltip(pin: DiffusionPin): string {
64
  const half = (who: string, h: DiffusionHalf) => `**${who}: ${h.word}.** ${h.title}`;
65
  const run = pin.run !== null && pin.run !== undefined ? ` · run #${pin.run}${pin.run_status ? ` ${pin.run_status}` : ""}` : "";
66
  return [
67
    half(pin.upstream, pin.upstream_state),
68
    half(pin.consumer, pin.consumer_state),
69
    `Pinned at \`${pin.path}\` on \`${pin.bookmark}\`; ${pin.consumer} ${FOLLOW[pin.follow] ?? pin.follow}.${pin.bump !== null && pin.bump !== undefined ? ` Open bump #${pin.bump}${run}.` : ""}`,
70
  ].join("\n\n");
71
}