diff --git a/desktop/src/app/AppTopChrome.tsx b/desktop/src/app/AppTopChrome.tsx
index dd0fabe8a..84b017b31 100644
--- a/desktop/src/app/AppTopChrome.tsx
+++ b/desktop/src/app/AppTopChrome.tsx
@@ -101,6 +101,13 @@ export function AppTopChrome({
)}
data-tauri-drag-region
data-testid="app-top-chrome"
+ style={
+ {
+ "--app-top-chrome-center-offset": hasCommunityRail
+ ? "-1.75rem"
+ : "0rem",
+ } as React.CSSProperties
+ }
>
diff --git a/desktop/src/features/projects/lib/projectExternalUrl.test.mjs b/desktop/src/features/projects/lib/projectExternalUrl.test.mjs
new file mode 100644
index 000000000..83a114ad1
--- /dev/null
+++ b/desktop/src/features/projects/lib/projectExternalUrl.test.mjs
@@ -0,0 +1,33 @@
+import assert from "node:assert/strict";
+import { test } from "node:test";
+
+import { projectExternalRefUrl } from "./projectExternalUrl.ts";
+
+test("opens the selected GitHub branch", () => {
+ assert.equal(
+ projectExternalRefUrl(
+ "https://github.com/block/buzz",
+ "fix/agent-profile-about-preserve",
+ ),
+ "https://github.com/block/buzz/tree/fix%2Fagent-profile-about-preserve",
+ );
+});
+
+test("normalizes clone URLs before adding the selected ref", () => {
+ assert.equal(
+ projectExternalRefUrl("https://github.com/block/buzz.git/", "main"),
+ "https://github.com/block/buzz/tree/main",
+ );
+});
+
+test("keeps unsupported and unscoped URLs unchanged", () => {
+ assert.equal(
+ projectExternalRefUrl("https://gitlab.com/block/buzz", "main"),
+ "https://gitlab.com/block/buzz",
+ );
+ assert.equal(
+ projectExternalRefUrl("https://github.com/block/buzz", null),
+ "https://github.com/block/buzz",
+ );
+ assert.equal(projectExternalRefUrl("not a URL", "main"), "not a URL");
+});
diff --git a/desktop/src/features/projects/lib/projectExternalUrl.ts b/desktop/src/features/projects/lib/projectExternalUrl.ts
new file mode 100644
index 000000000..86427722d
--- /dev/null
+++ b/desktop/src/features/projects/lib/projectExternalUrl.ts
@@ -0,0 +1,26 @@
+/** Builds a GitHub repository URL scoped to the selected branch or tag. */
+export function projectExternalRefUrl(
+ externalUrl: string | null | undefined,
+ ref: string | null | undefined,
+): string | null {
+ if (!externalUrl) return null;
+ const selectedRef = ref?.trim();
+ if (!selectedRef) return externalUrl;
+
+ try {
+ const url = new URL(externalUrl);
+ if (
+ url.protocol !== "https:" ||
+ url.hostname.toLowerCase() !== "github.com"
+ ) {
+ return externalUrl;
+ }
+ const segments = url.pathname.split("/").filter(Boolean);
+ if (segments.length !== 2) return externalUrl;
+ const repository = segments[1]?.replace(/\.git$/i, "");
+ if (!segments[0] || !repository) return externalUrl;
+ return `${url.origin}/${segments[0]}/${repository}/tree/${encodeURIComponent(selectedRef)}`;
+ } catch {
+ return externalUrl;
+ }
+}
diff --git a/desktop/src/features/projects/ui/DiscussionChannels.tsx b/desktop/src/features/projects/ui/DiscussionChannels.tsx
index 344e6be09..d48521f34 100644
--- a/desktop/src/features/projects/ui/DiscussionChannels.tsx
+++ b/desktop/src/features/projects/ui/DiscussionChannels.tsx
@@ -34,6 +34,7 @@ import {
getMentionTagPubkey,
resolveMentionProps,
} from "@/shared/lib/resolveMentionNames";
+import { BuzzLoadingState } from "@/shared/ui/BuzzLoadingState";
import { Markdown } from "@/shared/ui/markdown";
import { UserAvatar } from "@/shared/ui/UserAvatar";
import { useProjectConversationPanel } from "./ProjectConversationPanelContext";
@@ -491,11 +492,7 @@ export function DiscussionChannelsPanel({
const profiles = profilesQuery.data?.profiles;
if (isLoading) {
- return (
-
- Searching channel discussions…
-
- );
+ return
;
}
if (channels.length === 0) {
return (
diff --git a/desktop/src/features/projects/ui/ProjectConversationPanel.tsx b/desktop/src/features/projects/ui/ProjectConversationPanel.tsx
index 9d4ab63d1..59f3264b0 100644
--- a/desktop/src/features/projects/ui/ProjectConversationPanel.tsx
+++ b/desktop/src/features/projects/ui/ProjectConversationPanel.tsx
@@ -40,6 +40,7 @@ export function ProjectConversationPanel({
onClose,
onResetWidth,
onResizeStart,
+ sharedHeaderBackdrop,
widthPx,
}: {
canResetWidth: boolean;
@@ -47,6 +48,7 @@ export function ProjectConversationPanel({
onClose: () => void;
onResetWidth: () => void;
onResizeStart: (event: React.PointerEvent
) => void;
+ sharedHeaderBackdrop?: boolean;
widthPx: number;
}) {
const { goChannel } = useAppNavigation();
@@ -204,7 +206,7 @@ export function ProjectConversationPanel({
showBackButton: false,
splitPaneClamp: false,
testId: isOverlay ? "project-conversation-panel" : "message-thread-panel",
- transparentChrome: false,
+ transparentChrome: sharedHeaderBackdrop,
};
const handleSend = React.useCallback(
diff --git a/desktop/src/features/projects/ui/ProjectConversationPanelContext.tsx b/desktop/src/features/projects/ui/ProjectConversationPanelContext.tsx
index 2de4a1047..2bb73d270 100644
--- a/desktop/src/features/projects/ui/ProjectConversationPanelContext.tsx
+++ b/desktop/src/features/projects/ui/ProjectConversationPanelContext.tsx
@@ -86,6 +86,7 @@ export function ProjectConversationPanelController({
onClose={() => setHit(null)}
onResetWidth={onResetWidth}
onResizeStart={onResizeStart}
+ sharedHeaderBackdrop={sharedHeaderBackdrop}
widthPx={widthPx}
/>
) : (
diff --git a/desktop/src/features/projects/ui/ProjectDetailChrome.tsx b/desktop/src/features/projects/ui/ProjectDetailChrome.tsx
index 1c41f9278..843fb890f 100644
--- a/desktop/src/features/projects/ui/ProjectDetailChrome.tsx
+++ b/desktop/src/features/projects/ui/ProjectDetailChrome.tsx
@@ -42,7 +42,10 @@ export function ProjectDetailChrome({
>