From 6e91aa83f631f5fecb924ad5aba0a62324f3b50e Mon Sep 17 00:00:00 2001 From: iamnbutler Date: Thu, 22 Oct 2026 16:38:29 -0400 Subject: [PATCH 1/3] fix(app): show who has joined the team directory and name its Mac when it is down Why: apps/host/src/directory.ts#function server | a served directory's Mac is found by the address it publishes; a deployed directory matches none and keeps the generic error --- apps/app/src/directory-settings.tsx | 17 +++----- apps/app/src/settings-layout.tsx | 8 ++++ apps/app/src/team-setup.tsx | 67 +++++++++++++++++++++++++++-- apps/host/src/diagnostics.ts | 3 +- apps/host/src/directory.ts | 23 +++++++++- apps/host/src/protocol.ts | 5 +++ docs/setup.md | 4 +- 7 files changed, 110 insertions(+), 17 deletions(-) diff --git a/apps/app/src/directory-settings.tsx b/apps/app/src/directory-settings.tsx index 0f2035a4..1ee35203 100644 --- a/apps/app/src/directory-settings.tsx +++ b/apps/app/src/directory-settings.tsx @@ -8,8 +8,8 @@ import { host } from "./host"; import { useDiagnostics } from "./host-settings"; import { parse } from "./invite"; import { CREATE_DIRECTORY, DIRECTORY_CHANGED, People, useRoster } from "./onboarding"; -import { Confirm, Group, Page, Problem, Row, Status, Value } from "./settings-layout"; -import { TEAM_SETUP } from "./team-setup"; +import { Confirm, Group, Page, Problem, Row, Status, Value, when } from "./settings-layout"; +import { DirectoryHosts, TEAM_SETUP } from "./team-setup"; const SETUP = "https://github.com/githubnext/ace/blob/main/docs/setup.md#team-directory"; @@ -107,6 +107,11 @@ export function TeamSettings({ active }: { active: boolean }) { )} + {checked?.directory.url && ( + + + + )} {checks.open && } {checked?.directory.url && checked.directory.synced && !served(checked.directory) && ( @@ -194,14 +199,6 @@ function shared(shares: Share[]): string { return [...projects].map(([name, people]) => `${name} with ${people.join(", ")}`).join("; "); } -/** A time today, or a date and time when older, so a stale sync doesn't read as recent. */ -function when(time: number) { - const date = new Date(time); - return date.toDateString() === new Date().toDateString() - ? date.toLocaleTimeString() - : date.toLocaleString(); -} - /** `row` keeps each result beside the control that caused it. */ type Action = { row?: "directory" | "secret"; busy?: string; error?: string; message?: string }; diff --git a/apps/app/src/settings-layout.tsx b/apps/app/src/settings-layout.tsx index 8a0673ee..c9e57ff3 100644 --- a/apps/app/src/settings-layout.tsx +++ b/apps/app/src/settings-layout.tsx @@ -178,6 +178,14 @@ export function Confirm({ children, action, busy, onConfirm, onCancel }: { ); } +/** A time today, or a date and time when older, so a stale sync doesn't read as recent. */ +export function when(time: number) { + const date = new Date(time); + return date.toDateString() === new Date().toDateString() + ? date.toLocaleTimeString() + : date.toLocaleString(); +} + export function Status({ children }: { children: ReactNode }) { return

{children}

; } diff --git a/apps/app/src/team-setup.tsx b/apps/app/src/team-setup.tsx index 508e75fe..10519003 100644 --- a/apps/app/src/team-setup.tsx +++ b/apps/app/src/team-setup.tsx @@ -13,11 +13,12 @@ import { toast, } from "@ace/ui"; import { IconArrowUpRight, IconCheck, IconCopy, IconLoader, IconUsers } from "@ace/ui/icons"; -import { TEAM_ASK_EXPIRES, type TeamPeer } from "@ace/host/protocol"; +import { type Diagnostics, TEAM_ASK_EXPIRES, type TeamPeer } from "@ace/host/protocol"; import { host } from "./host"; import { useDiagnostics } from "./host-settings"; import { type Invite as Team, link, page, parse } from "./invite"; +import { Row, Status, Value, when } from "./settings-layout"; const DOCS = "https://github.com/githubnext/ace/blob/main/docs/setup.md"; export const TEAM_SETUP = "ace:team-setup"; @@ -68,6 +69,11 @@ export function TeamSetup({ github, invite, inviting, onClose }: { const [provider, setProvider] = useState("cloudflare"); const [joined, setJoined] = useState(); const [error, setError] = useState(""); + const checks = useDiagnostics(step === "fork"); + const checked = checks.value; + const directory = checked?.directory.url ? checked.directory : undefined; + // Until the host answers, the fork can't tell a first person from one already in a team. + const pending = checks.open && !checked && !checks.error; useEffect(() => { if (!inviting) return; @@ -81,7 +87,31 @@ export function TeamSetup({ github, invite, inviting, onClose }: { next || onClose()}> {STEPS[step] && !inviting && } - {step === "fork" && ( + {step === "fork" && directory && ( + <> + +
+
+ +
+ +