Make board notifications Linux-specific

This commit is contained in:
codebanditssss 2026-07-04 20:29:12 +05:30
parent dcc3583be1
commit 52e6c7f3cd
3 changed files with 36 additions and 11 deletions

View File

@ -14,6 +14,12 @@ import { prDiffSummary, sessionPRDisplaySummaries } from "../lib/pr-display";
import { cn } from "../lib/utils"; import { cn } from "../lib/utils";
import { PRAttentionPanel, PRStatusStrip } from "./PRSummaryDisplay"; import { PRAttentionPanel, PRStatusStrip } from "./PRSummaryDisplay";
const isLinux =
typeof navigator !== "undefined" &&
((navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData?.platform ?? navigator.platform)
.toLowerCase()
.includes("linux");
type SessionsBoardProps = { type SessionsBoardProps = {
/** When set, the board shows only this project's sessions. */ /** When set, the board shows only this project's sessions. */
projectId?: string; projectId?: string;
@ -127,7 +133,7 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) {
const actions = projectId ? ( const actions = projectId ? (
<> <>
<NotificationCenter /> {isLinux ? <NotificationCenter /> : null}
<button <button
aria-label="New task" aria-label="New task"
className="dashboard-app-header__accent-btn" className="dashboard-app-header__accent-btn"
@ -148,9 +154,9 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) {
{isSpawning ? "Spawning..." : orchestrator ? "Orchestrator" : "Spawn Orchestrator"} {isSpawning ? "Spawning..." : orchestrator ? "Orchestrator" : "Spawn Orchestrator"}
</button> </button>
</> </>
) : ( ) : isLinux ? (
<NotificationCenter /> <NotificationCenter />
); ) : undefined;
return ( return (
<div className="flex h-full min-h-0 flex-col bg-background text-foreground"> <div className="flex h-full min-h-0 flex-col bg-background text-foreground">

View File

@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useNavigate, useParams } from "@tanstack/react-router"; import { useNavigate, useParams } from "@tanstack/react-router";
import { GitBranch, LayoutDashboard, PanelRightClose, PanelRightOpen, Plus, Square, Trash2 } from "lucide-react"; import { GitBranch, LayoutDashboard, PanelRightClose, PanelRightOpen, Plus, Square, Trash2 } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { NotificationCenter } from "./NotificationCenter";
import { import {
findProjectOrchestrator, findProjectOrchestrator,
isOrchestratorSession, isOrchestratorSession,
@ -20,6 +21,11 @@ import { NewTaskDialog } from "./NewTaskDialog";
import { cn } from "../lib/utils"; import { cn } from "../lib/utils";
const isMac = typeof navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.userAgent); const isMac = typeof navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.userAgent);
const isLinux =
typeof navigator !== "undefined" &&
((navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData?.platform ?? navigator.platform)
.toLowerCase()
.includes("linux");
const dragStyle = isMac ? ({ WebkitAppRegion: "drag" } as React.CSSProperties) : undefined; const dragStyle = isMac ? ({ WebkitAppRegion: "drag" } as React.CSSProperties) : undefined;
const noDragStyle = isMac ? ({ WebkitAppRegion: "no-drag" } as React.CSSProperties) : undefined; const noDragStyle = isMac ? ({ WebkitAppRegion: "no-drag" } as React.CSSProperties) : undefined;
@ -69,10 +75,12 @@ export function ShellTopbar() {
// removed, or data still loading) shows an empty crumb — never the raw // removed, or data still loading) shows an empty crumb — never the raw
// route slug. "agent-orchestrator" is the root-board crumb only. // route slug. "agent-orchestrator" is the root-board crumb only.
const projectId = session?.workspaceId ?? params.projectId; const projectId = session?.workspaceId ?? params.projectId;
const projectLabel = session?.workspaceName ?? ""; const isProjectBoardRoute = !isSessionRoute && Boolean(projectId);
const project = projectId ? all.find((workspace) => workspace.id === projectId) : undefined;
const projectLabel = project?.name ?? session?.workspaceName ?? (projectId ? "" : "agent-orchestrator");
const orchestrator = projectId ? findProjectOrchestrator(all, projectId) : undefined; const orchestrator = projectId ? findProjectOrchestrator(all, projectId) : undefined;
if (!isSessionRoute) { if (isLinux && !isSessionRoute) {
return null; return null;
} }
@ -133,7 +141,7 @@ export function ShellTopbar() {
return ( return (
<header className={cn("dashboard-app-header", isMac && "is-under-titlebar-nav")} style={dragStyle}> <header className={cn("dashboard-app-header", isMac && "is-under-titlebar-nav")} style={dragStyle}>
<div className="session-topbar__lead"> <div className="session-topbar__lead">
{isOrchestrator ? ( {isSessionRoute && isOrchestrator ? (
<div className="topbar-project-pills-group"> <div className="topbar-project-pills-group">
<div className="topbar-project-line"> <div className="topbar-project-line">
<span className="dashboard-app-header__project">{projectLabel}</span> <span className="dashboard-app-header__project">{projectLabel}</span>
@ -146,7 +154,7 @@ export function ShellTopbar() {
</span> </span>
</div> </div>
</div> </div>
) : ( ) : isSessionRoute ? (
<div className="session-topbar__identity"> <div className="session-topbar__identity">
<div className="session-topbar__branch"> <div className="session-topbar__branch">
<GitBranch className="h-3 w-3 shrink-0" aria-hidden="true" /> <GitBranch className="h-3 w-3 shrink-0" aria-hidden="true" />
@ -154,13 +162,18 @@ export function ShellTopbar() {
</div> </div>
{session ? <SessionStatusPill session={session} /> : null} {session ? <SessionStatusPill session={session} /> : null}
</div> </div>
) : isProjectBoardRoute ? null : (
<div className="topbar-project-line">
<span className="dashboard-app-header__project">{projectLabel}</span>
</div>
)} )}
</div> </div>
<div className="dashboard-app-header__spacer" /> <div className="dashboard-app-header__spacer" />
<div className="dashboard-app-header__actions"> <div className="dashboard-app-header__actions">
{isOrchestrator ? ( {!isLinux ? <NotificationCenter style={noDragStyle} /> : null}
{isSessionRoute && isOrchestrator ? (
<> <>
<button <button
aria-label="New task" aria-label="New task"
@ -187,7 +200,7 @@ export function ShellTopbar() {
{/* Kill control sits beside the orchestrator link for active workers {/* Kill control sits beside the orchestrator link for active workers
moved here from the inspector's Summary "Danger zone". */} moved here from the inspector's Summary "Danger zone". */}
{!isOrchestrator && session && sessionIsActive(session) ? <TopbarKillButton session={session} /> : null} {!isOrchestrator && session && sessionIsActive(session) ? <TopbarKillButton session={session} /> : null}
{!isOrchestrator && ( {isSessionRoute && !isOrchestrator && (
<button <button
aria-label="Open orchestrator" aria-label="Open orchestrator"
className="dashboard-app-header__primary-btn dashboard-app-header__primary-btn--compact" className="dashboard-app-header__primary-btn dashboard-app-header__primary-btn--compact"
@ -201,7 +214,7 @@ export function ShellTopbar() {
</button> </button>
)} )}
{/* Inspector collapse (worker sessions only — orchestrators have no rail). */} {/* Inspector collapse (worker sessions only — orchestrators have no rail). */}
{!isOrchestrator && ( {isSessionRoute && !isOrchestrator && (
<button <button
aria-label={isInspectorOpen ? "Close inspector panel" : "Open inspector panel"} aria-label={isInspectorOpen ? "Close inspector panel" : "Open inspector panel"}
aria-pressed={isInspectorOpen} aria-pressed={isInspectorOpen}

View File

@ -34,6 +34,12 @@ function errorMessage(error: unknown) {
return error instanceof Error ? error.message : "Could not load projects"; return error instanceof Error ? error.message : "Could not load projects";
} }
const isLinux =
typeof navigator !== "undefined" &&
((navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData?.platform ?? navigator.platform)
.toLowerCase()
.includes("linux");
// Persistent app shell: the Sidebar + shared state survive route changes; only // Persistent app shell: the Sidebar + shared state survive route changes; only
// the <Outlet> content (board / session / settings / …) swaps. Lifted out of // the <Outlet> content (board / session / settings / …) swaps. Lifted out of
// the old single <App>, with selection now owned by the router (route params) // the old single <App>, with selection now owned by the router (route params)
@ -189,7 +195,7 @@ function ShellLayout() {
> >
<Sidebar <Sidebar
daemonStatus={daemonStatus} daemonStatus={daemonStatus}
underTopbar={isSessionRoute} underTopbar={isLinux ? isSessionRoute : true}
onCreateProject={createProject} onCreateProject={createProject}
onRemoveProject={removeProject} onRemoveProject={removeProject}
workspaceError={workspaceQuery.isError ? errorMessage(workspaceQuery.error) : undefined} workspaceError={workspaceQuery.isError ? errorMessage(workspaceQuery.error) : undefined}