fix: consolidate project avatar source logic (#23819)

This commit is contained in:
Brendan Allan 2026-04-22 17:09:00 +08:00 committed by Aiden Cline
parent 71d196d3cd
commit d884ab73d5
2 changed files with 23 additions and 13 deletions

View file

@ -12,6 +12,7 @@ import { type LocalProject, getAvatarColors } from "@/context/layout"
import { getFilename } from "@opencode-ai/shared/util/path" import { getFilename } from "@opencode-ai/shared/util/path"
import { Avatar } from "@opencode-ai/ui/avatar" import { Avatar } from "@opencode-ai/ui/avatar"
import { useLanguage } from "@/context/language" import { useLanguage } from "@/context/language"
import { getProjectAvatarSource } from "@/pages/layout/sidebar-items"
const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const
@ -144,7 +145,11 @@ export function DialogEditProject(props: { project: LocalProject }) {
}} }}
> >
<Show <Show
when={store.iconOverride || (!store.color && props.project.icon?.url)} when={getProjectAvatarSource(props.project.id, {
color: store.color,
url: props.project.icon?.url,
override: store.iconOverride,
})}
fallback={ fallback={
<div class="size-full flex items-center justify-center"> <div class="size-full flex items-center justify-center">
<Avatar <Avatar
@ -155,11 +160,13 @@ export function DialogEditProject(props: { project: LocalProject }) {
</div> </div>
} }
> >
<img {(src) => (
src={store.iconOverride || props.project.icon?.url} <img
alt={language.t("dialog.project.edit.icon.alt")} src={src()}
class="size-full object-cover" alt={language.t("dialog.project.edit.icon.alt")}
/> class="size-full object-cover"
/>
)}
</Show> </Show>
</div> </div>
<div <div
@ -216,6 +223,7 @@ export function DialogEditProject(props: { project: LocalProject }) {
store.color !== color, store.color !== color,
}} }}
onClick={() => { onClick={() => {
if (store.color === color && !props.project.icon?.url) return
setStore("color", store.color === color ? undefined : color) setStore("color", store.color === color ? undefined : color)
}} }}
> >

View file

@ -19,6 +19,14 @@ import { childSessionOnPath, hasProjectPermissions } from "./helpers"
const OPENCODE_PROJECT_ID = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" const OPENCODE_PROJECT_ID = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750"
export function getProjectAvatarSource(id?: string, icon?: { color?: string; url?: string; override?: string }) {
return id === OPENCODE_PROJECT_ID
? "https://opencode.ai/favicon.svg"
: icon?.color
? undefined
: icon?.override || icon?.url
}
export const ProjectIcon = (props: { project: LocalProject; class?: string; notify?: boolean }): JSX.Element => { export const ProjectIcon = (props: { project: LocalProject; class?: string; notify?: boolean }): JSX.Element => {
const globalSync = useGlobalSync() const globalSync = useGlobalSync()
const notification = useNotification() const notification = useNotification()
@ -42,13 +50,7 @@ export const ProjectIcon = (props: { project: LocalProject; class?: string; noti
<div class="size-full rounded overflow-clip"> <div class="size-full rounded overflow-clip">
<Avatar <Avatar
fallback={name()} fallback={name()}
src={ src={getProjectAvatarSource(props.project.id, props.project.icon)}
props.project.id === OPENCODE_PROJECT_ID
? "https://opencode.ai/favicon.svg"
: props.project.icon?.color
? undefined
: props.project.icon?.override || props.project.icon?.url
}
{...getAvatarColors(props.project.icon?.color)} {...getAvatarColors(props.project.icon?.color)}
class="size-full rounded" class="size-full rounded"
classList={{ "badge-mask": notify() }} classList={{ "badge-mask": notify() }}