feat(project): add icon_url_override field to projects (#23955)

This commit is contained in:
Brendan Allan 2026-04-23 18:57:04 +08:00 committed by GitHub
parent 785f3589ab
commit 6002500bc0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 1545 additions and 77 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE `project` ADD `icon_url_override` text;
UPDATE `project` SET `icon_url_override` = `icon_url` WHERE `icon_url` IS NOT NULL;

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,7 @@ export const ProjectTable = sqliteTable("project", {
vcs: text(),
name: text(),
icon_url: text(),
icon_url_override: text(),
icon_color: text(),
...Timestamps,
time_initialized: integer(),

View file

@ -60,7 +60,13 @@ type Row = typeof ProjectTable.$inferSelect
export function fromRow(row: Row): Info {
const icon =
row.icon_url || row.icon_color ? { url: row.icon_url ?? undefined, color: row.icon_color ?? undefined } : undefined
row.icon_url || row.icon_url_override || row.icon_color
? {
url: row.icon_url ?? undefined,
override: row.icon_url_override ?? undefined,
color: row.icon_color ?? undefined,
}
: undefined
return {
id: row.id,
worktree: row.worktree,
@ -289,6 +295,7 @@ export const layer: Layer.Layer<
vcs: result.vcs ?? null,
name: result.name,
icon_url: result.icon?.url,
icon_url_override: result.icon?.override,
icon_color: result.icon?.color,
time_created: result.time.created,
time_updated: result.time.updated,
@ -303,6 +310,7 @@ export const layer: Layer.Layer<
vcs: result.vcs ?? null,
name: result.name,
icon_url: result.icon?.url,
icon_url_override: result.icon?.override,
icon_color: result.icon?.color,
time_updated: result.time.updated,
time_initialized: result.time.initialized,
@ -365,6 +373,7 @@ export const layer: Layer.Layer<
.set({
name: input.name,
icon_url: input.icon?.url,
icon_url_override: input.icon?.override,
icon_color: input.icon?.color,
commands: input.commands,
time_updated: Date.now(),

View file

@ -168,6 +168,7 @@ export async function run(db: SQLiteBunDatabase<any, any> | NodeSQLiteDatabase<a
vcs: data.vcs,
name: data.name ?? undefined,
icon_url: data.icon?.url,
icon_url_override: data.icon?.override,
icon_color: data.icon?.color,
time_created: data.time?.created ?? now,
time_updated: data.time?.updated ?? now,

View file

@ -278,6 +278,31 @@ describe("Project.discover", () => {
expect(updated).toBeDefined()
expect(updated!.icon).toBeUndefined()
})
test("should not discover favicon when override is set", async () => {
await using tmp = await tmpdir({ git: true })
const { project } = await run((svc) => svc.fromDirectory(tmp.path))
await run((svc) =>
svc.update({
projectID: project.id,
icon: { override: "data:image/png;base64,override" },
}),
)
const updatedProject = await run((svc) => svc.get(project.id))
if (!updatedProject) throw new Error("Project not found")
const pngData = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
await Bun.write(path.join(tmp.path, "favicon.png"), pngData)
await run((svc) => svc.discover(updatedProject))
const updated = Project.get(project.id)
expect(updated).toBeDefined()
expect(updated!.icon?.override).toBe("data:image/png;base64,override")
expect(updated!.icon?.url).toBeUndefined()
})
})
describe("Project.update", () => {
@ -332,6 +357,23 @@ describe("Project.update", () => {
expect(fromDb?.icon?.color).toBe("#ff0000")
})
test("should update icon override", async () => {
await using tmp = await tmpdir({ git: true })
const { project } = await run((svc) => svc.fromDirectory(tmp.path))
const updated = await run((svc) =>
svc.update({
projectID: project.id,
icon: { override: "data:image/png;base64,abc123" },
}),
)
expect(updated.icon?.override).toBe("data:image/png;base64,abc123")
const fromDb = Project.get(project.id)
expect(fromDb?.icon?.override).toBe("data:image/png;base64,abc123")
})
test("should update commands", async () => {
await using tmp = await tmpdir({ git: true })
const { project } = await run((svc) => svc.fromDirectory(tmp.path))
@ -389,13 +431,14 @@ describe("Project.update", () => {
svc.update({
projectID: project.id,
name: "Multi Update",
icon: { url: "https://example.com/favicon.ico", color: "#00ff00" },
icon: { url: "https://example.com/favicon.ico", override: "data:image/png;base64,abc123", color: "#00ff00" },
commands: { start: "make start" },
}),
)
expect(updated.name).toBe("Multi Update")
expect(updated.icon?.url).toBe("https://example.com/favicon.ico")
expect(updated.icon?.override).toBe("data:image/png;base64,abc123")
expect(updated.icon?.color).toBe("#00ff00")
expect(updated.commands?.start).toBe("make start")
})