diff --git a/packages/ui/src/data-display/project-avatar/project-avatar.test.ts b/packages/ui/src/data-display/project-avatar/project-avatar.test.ts new file mode 100644 index 000000000000..ff68a7a20d6e --- /dev/null +++ b/packages/ui/src/data-display/project-avatar/project-avatar.test.ts @@ -0,0 +1,21 @@ +import { createHash } from "crypto" +import { describe, expect, test } from "bun:test" +import { getProjectAvatarSource } from "./project-avatar" + +describe("getProjectAvatarSource", () => { + test("prefers a chosen image, then a chosen color, then the automatic icon", () => { + expect(getProjectAvatarSource("abc", { override: "data:image/png;base64,AA==", url: "data:auto" })).toBe( + "data:image/png;base64,AA==", + ) + expect(getProjectAvatarSource("abc", { color: "blue", url: "data:auto" })).toBeUndefined() + expect(getProjectAvatarSource("abc", { url: "data:auto" })).toBe("data:auto") + }) + + test("recognizes the OpenCode repository by its remote-derived project ID", () => { + const id = createHash("sha1").update("git-remote:github.com/anomalyco/opencode").digest("hex") + + expect(getProjectAvatarSource(id)).toBe("https://opencode.ai/favicon.svg") + expect(getProjectAvatarSource(id, { override: "data:custom" })).toBe("data:custom") + expect(getProjectAvatarSource(id, { color: "blue" })).toBeUndefined() + }) +}) diff --git a/packages/ui/src/data-display/project-avatar/project-avatar.tsx b/packages/ui/src/data-display/project-avatar/project-avatar.tsx index 54e52e80ca42..2933b910a7f1 100644 --- a/packages/ui/src/data-display/project-avatar/project-avatar.tsx +++ b/packages/ui/src/data-display/project-avatar/project-avatar.tsx @@ -31,15 +31,20 @@ export type ProjectAvatarVariant = (typeof PROJECT_AVATAR_VARIANTS)[number] // "outline" is a neutral, muted style (e.g. recently closed projects) and is not part of the color rotation. export type ProjectAvatarStyle = ProjectAvatarVariant | "outline" -const OPENCODE_PROJECT_ID = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" +// Project IDs hash the normalized origin remote (`git-remote:github.com/anomalyco/opencode`); V1 used the root commit. +const OPENCODE_PROJECT_IDS = new Set([ + "012780c4098d08caa4ea8c479ed0a4690489f38d", + "476fbfe6befa9e63ddd7f9ae71655999a0104256", + "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750", +]) export function getProjectAvatarSource(id?: string, icon?: { color?: string; url?: string; override?: string }) { - if (id === OPENCODE_PROJECT_ID) return "https://opencode.ai/favicon.svg" - if (icon?.override) return icon.override if (icon?.color) return undefined + if (id && OPENCODE_PROJECT_IDS.has(id)) return "https://opencode.ai/favicon.svg" + return icon?.url } @@ -90,7 +95,7 @@ export function ProjectAvatar(props: ProjectAvatarProps) { ...split.classList, [split.class ?? ""]: !!split.class, }} - style={typeof split.style === "object" ? split.style : undefined} + style={split.style} >