From b7167aaab03796f29c714ad1ee35cc64066d6e2b Mon Sep 17 00:00:00 2001 From: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Date: Sun, 23 Aug 2026 14:18:15 +0800 Subject: [PATCH] feat(app): add project icon setting (#44323) --- packages/app/src/runtime/i18n/en.ts | 2 + .../src/session/timeline/message-timeline.tsx | 53 ++++++++++++++----- packages/app/src/settings/general/general.tsx | 14 +++++ packages/app/src/settings/model.tsx | 6 +++ 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/packages/app/src/runtime/i18n/en.ts b/packages/app/src/runtime/i18n/en.ts index 057f47d32d7..ddb1926c435 100644 --- a/packages/app/src/runtime/i18n/en.ts +++ b/packages/app/src/runtime/i18n/en.ts @@ -948,6 +948,8 @@ export const dict = { "settings.general.row.showTerminal.description": "Show the terminal button in the desktop title bar", "settings.general.row.showStatus.title": "Server status", "settings.general.row.showStatus.description": "Show the server status button in the title bar", + "settings.general.row.showProjectIcon.title": "Project icon", + "settings.general.row.showProjectIcon.description": "Show the project icon in the session header", "settings.general.row.mobileTitlebarBottom.title": "Bottom navigation", "settings.general.row.mobileTitlebarBottom.description": "Place the title bar and session tabs at the bottom of the screen on mobile", diff --git a/packages/app/src/session/timeline/message-timeline.tsx b/packages/app/src/session/timeline/message-timeline.tsx index 0bfe3620c8e..3e008879116 100644 --- a/packages/app/src/session/timeline/message-timeline.tsx +++ b/packages/app/src/session/timeline/message-timeline.tsx @@ -1,4 +1,4 @@ -import { createEffect, createMemo, createSignal, For, on, Show, type Accessor } from "solid-js" +import { createEffect, createMemo, createSignal, For, on, Show, type Accessor, type JSX } from "solid-js" import createPresence from "solid-presence" import { createStore } from "solid-js/store" import type { SessionUserActions } from "@opencode-ai/session-ui/actions" @@ -17,7 +17,7 @@ import { getFilename } from "@opencode-ai/util/path" import { Popover } from "@kobalte/core/popover" import { SessionContextUsage } from "@/session/timeline/session-context-usage" import { useLanguage } from "@/runtime/i18n/language" -import { useData } from "@/runtime/server/current" +import { useData, useServer } from "@/runtime/server/current" import { useWorkspaceLocation } from "@/workspaces/location" import { Timeline, TimelineRow } from "@opencode-ai/session-ui/timeline/projection" import { createSessionTimelineRowRenderer } from "@opencode-ai/session-ui/timeline/row" @@ -26,9 +26,10 @@ import { createTimelineVirtualizer } from "./virtualizer" import { containsDirectory, isWorkspaceDirectory, workspaceDirectories } from "@/workspaces/paths" import { SessionWorkspaceMenu } from "@/session/timeline/session-workspace-menu" import { getProjectAvatarVariant } from "@/shell/state/layout" -import { displayName, getProjectAvatarSource } from "@/shell/layout/helpers" +import { displayName, getProjectAvatarSource, projectForSession } from "@/shell/layout/helpers" import { parseCommentNote, readPromptPresentation } from "@/composer/comment-note" import { useCommand } from "@/shell/commands/command" +import { useSettings } from "@/settings/model" type BackgroundTask = { id: string @@ -108,7 +109,7 @@ export function BackgroundWorkSummary(props: { tasks: BackgroundTask[] }) { {(task) => (
{taskType(task)} {task.label} @@ -180,6 +181,7 @@ function WorkspaceMoveAction(props: { function SessionSummaryPanel(props: { project: Project + avatar?: JSX.Element directory: string local: boolean branch?: string @@ -206,11 +208,13 @@ function SessionSummaryPanel(props: {
- + {props.avatar ?? ( + + )} {displayName(props.project)}
isWorkspaceDirectory(project(), sessionDirectory())) + const showProjectIcon = () => + import.meta.env.VITE_OPENCODE_CHANNEL !== "prod" && settings.general.showProjectIcon() + const avatarProject = createMemo(() => { + if (!showProjectIcon()) return + const session = props.session.data.info() + if (!session) return + return projectForSession(session, server.ctx.projects.list()) + }) + const projectAvatar = () => ( + + ) createEffect(() => { const directory = project()?.worktree if (!directory) return @@ -513,7 +534,9 @@ function MessageTimelineView( when={workspaceSession()} fallback={ - + }> + {projectAvatar()} + } > @@ -525,9 +548,14 @@ function MessageTimelineView( - + }> + {projectAvatar()} + @@ -613,6 +641,7 @@ function MessageTimelineView( + + +
+ settings.general.setShowProjectIcon(checked)} + /> +
+
+
+ store.general?.showProjectIcon, defaultSettings.general.showProjectIcon), + setShowProjectIcon(value: boolean) { + setStore("general", "showProjectIcon", value) + }, showTerminal: withFallback(() => store.general?.showTerminal, defaultSettings.general.showTerminal), setShowTerminal(value: boolean) { setStore("general", "showTerminal", value)