diff --git a/.lane/memory/apps/host/src/directory.ts/01M4YX72YG7JQ8ACP15VM1V6XB-every-directory-request-must.md b/.lane/memory/apps/host/src/directory.ts/01M4YX72YG7JQ8ACP15VM1V6XB-every-directory-request-must.md index 0b67a279..f9306f11 100644 --- a/.lane/memory/apps/host/src/directory.ts/01M4YX72YG7JQ8ACP15VM1V6XB-every-directory-request-must.md +++ b/.lane/memory/apps/host/src/directory.ts/01M4YX72YG7JQ8ACP15VM1V6XB-every-directory-request-must.md @@ -4,9 +4,9 @@ anchor: function call created: 2026-10-15T04:30:36Z norm: '1' sig: 3b9d360bb018f164 -body_hash: ed032412ce991b6b -raw_hash: 17ca2b8a23ffb09d -vouched: 2026-10-22T14:33:26Z +body_hash: fd35da8da75facb4 +raw_hash: 366b10d619b52eba +vouched: 2026-10-22T20:38:32Z lines: 97-125 --- diff --git a/.lane/memory/apps/host/src/directory.ts/01M5JNCCJHPCRSGY5EFTASKNDP-a-served-directory-s-mac-is.md b/.lane/memory/apps/host/src/directory.ts/01M5JNCCJHPCRSGY5EFTASKNDP-a-served-directory-s-mac-is.md new file mode 100644 index 00000000..fe24dba2 --- /dev/null +++ b/.lane/memory/apps/host/src/directory.ts/01M5JNCCJHPCRSGY5EFTASKNDP-a-served-directory-s-mac-is.md @@ -0,0 +1,12 @@ +--- +id: 01M5JNCCJHPCRSGY5EFTASKNDP +anchor: function server +created: 2026-10-22T20:38:30Z +norm: '1' +sig: 128e3397d58bcc17 +body_hash: 9d1be79086813df2 +raw_hash: b33a79c8a848f2a2 +lines: 240-243 +--- + +a served directory's Mac is found by the address it publishes; a deployed directory matches none and keeps the generic error 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 && ( + <> + +
+
+ +
+ +