Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/desktop/src/main/host-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const deviceName = process.env.DEVICE_NAME;
const auth =
authToken && cloudApiUrl ? new JwtAuthProvider(authToken) : undefined;

const app = createApp({
const { app, injectWebSocket } = createApp({
credentials: new LocalCredentialProvider(),
auth,
cloudApiUrl,
Expand All @@ -38,6 +38,7 @@ const server = serve(
process.stdout.write(`${JSON.stringify({ port: info.port })}\n`);
},
);
injectWebSocket(server);

const shutdown = () => {
server.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ interface DashboardSidebarProps {
export function DashboardSidebar({
isCollapsed = false,
}: DashboardSidebarProps) {
const { groups, toggleProjectCollapsed } = useDashboardSidebarData();
const { groups, refreshWorkspacePullRequest, toggleProjectCollapsed } =
useDashboardSidebarData();
const workspaceShortcutLabels = useDashboardSidebarShortcuts(groups);

return (
Expand All @@ -24,6 +25,7 @@ export function DashboardSidebar({
project={project}
isSidebarCollapsed={isCollapsed}
workspaceShortcutLabels={workspaceShortcutLabels}
onWorkspaceHover={refreshWorkspacePullRequest}
onToggleCollapse={toggleProjectCollapsed}
/>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ interface DashboardSidebarProjectSectionProps {
project: DashboardSidebarProject;
isSidebarCollapsed?: boolean;
workspaceShortcutLabels: Map<string, string>;
onWorkspaceHover: (workspaceId: string) => void | Promise<void>;
onToggleCollapse: (projectId: string) => void;
}

export function DashboardSidebarProjectSection({
project,
isSidebarCollapsed = false,
workspaceShortcutLabels,
onWorkspaceHover,
onToggleCollapse,
}: DashboardSidebarProjectSectionProps) {
const allSections = useMemo(
Expand Down Expand Up @@ -66,13 +68,13 @@ export function DashboardSidebarProjectSection({
>
<div className={cn("border-b border-border last:border-b-0")}>
<DashboardSidebarCollapsedProjectContent
projectId={project.id}
projectName={project.name}
githubOwner={project.githubOwner}
isCollapsed={project.isCollapsed}
totalWorkspaceCount={totalWorkspaceCount}
workspaces={flattenedCollapsedWorkspaces}
workspaceShortcutLabels={workspaceShortcutLabels}
onWorkspaceHover={onWorkspaceHover}
onToggleCollapse={() => onToggleCollapse(project.id)}
/>
</div>
Expand Down Expand Up @@ -106,11 +108,11 @@ export function DashboardSidebarProjectSection({
</DashboardSidebarProjectContextMenu>

<DashboardSidebarExpandedProjectContent
projectId={project.id}
isCollapsed={project.isCollapsed}
projectChildren={project.children}
allSections={allSections}
workspaceShortcutLabels={workspaceShortcutLabels}
onWorkspaceHover={onWorkspaceHover}
onDeleteSection={deleteSection}
onRenameSection={renameSection}
onToggleSectionCollapse={toggleSectionCollapsed}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { DashboardSidebarWorkspaceItem } from "../../../DashboardSidebarWorkspac

interface DashboardSidebarCollapsedProjectContentProps
extends ComponentPropsWithoutRef<"div"> {
projectId: string;
projectName: string;
githubOwner: string | null;
isCollapsed: boolean;
totalWorkspaceCount: number;
workspaces: DashboardSidebarWorkspace[];
workspaceShortcutLabels: Map<string, string>;
onWorkspaceHover: (workspaceId: string) => void | Promise<void>;
onToggleCollapse: () => void;
}

Expand All @@ -24,13 +24,13 @@ export const DashboardSidebarCollapsedProjectContent = forwardRef<
>(
(
{
projectId,
projectName,
githubOwner,
isCollapsed,
totalWorkspaceCount,
workspaces,
workspaceShortcutLabels,
onWorkspaceHover,
onToggleCollapse,
className,
...props
Expand Down Expand Up @@ -83,13 +83,9 @@ export const DashboardSidebarCollapsedProjectContent = forwardRef<
<div className="flex w-full flex-col pt-1">
{workspaces.map((workspace) => (
<DashboardSidebarWorkspaceItem
accentColor={workspace.accentColor}
key={workspace.id}
id={workspace.id}
projectId={projectId}
hostType={workspace.hostType}
name={workspace.name}
branch={workspace.branch}
workspace={workspace}
onHoverCardOpen={() => onWorkspaceHover(workspace.id)}
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Handle the async onWorkspaceHover call with await/try-catch so hover-triggered refresh failures don’t surface as unhandled promise rejections.

(Based on your team's feedback about handling async calls with proper await and catch.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarProjectSection/components/DashboardSidebarCollapsedProjectContent/DashboardSidebarCollapsedProjectContent.tsx, line 88:

<comment>Handle the async `onWorkspaceHover` call with `await`/`try`-`catch` so hover-triggered refresh failures don’t surface as unhandled promise rejections.

(Based on your team's feedback about handling async calls with proper await and catch.) </comment>

<file context>
@@ -83,14 +83,9 @@ export const DashboardSidebarCollapsedProjectContent = forwardRef<
-										branch={workspace.branch}
-										pullRequest={workspace.pullRequest}
+										workspace={workspace}
+										onHoverCardOpen={() => onWorkspaceHover(workspace.id)}
 										shortcutLabel={workspaceShortcutLabels.get(workspace.id)}
 										isCollapsed
</file context>
Suggested change
onHoverCardOpen={() => onWorkspaceHover(workspace.id)}
onHoverCardOpen={async () => {
try {
await onWorkspaceHover(workspace.id);
} catch (error) {
console.warn(
"[DashboardSidebar] failed to refresh workspace PR data",
error,
);
}
}}
Fix with Cubic

shortcutLabel={workspaceShortcutLabels.get(workspace.id)}
isCollapsed
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import { DashboardSidebarSection as DashboardSidebarSectionComponent } from "../
import { DashboardSidebarWorkspaceItem } from "../../../DashboardSidebarWorkspaceItem";

interface DashboardSidebarExpandedProjectContentProps {
projectId: string;
isCollapsed: boolean;
projectChildren: DashboardSidebarProjectChild[];
allSections: Array<{ id: string; name: string }>;
workspaceShortcutLabels: Map<string, string>;
onWorkspaceHover: (workspaceId: string) => void | Promise<void>;
onDeleteSection: (sectionId: string) => void;
onRenameSection: (sectionId: string, name: string) => void;
onToggleSectionCollapse: (sectionId: string) => void;
}

export function DashboardSidebarExpandedProjectContent({
projectId,
isCollapsed,
projectChildren,
allSections,
workspaceShortcutLabels,
onWorkspaceHover,
onDeleteSection,
onRenameSection,
onToggleSectionCollapse,
Expand All @@ -39,23 +39,20 @@ export function DashboardSidebarExpandedProjectContent({
child.type === "workspace" ? (
<DashboardSidebarWorkspaceItem
key={child.workspace.id}
id={child.workspace.id}
projectId={projectId}
accentColor={child.workspace.accentColor}
hostType={child.workspace.hostType}
name={child.workspace.name}
branch={child.workspace.branch}
workspace={child.workspace}
onHoverCardOpen={() => onWorkspaceHover(child.workspace.id)}
shortcutLabel={workspaceShortcutLabels.get(
child.workspace.id,
)}
/>
) : (
<DashboardSidebarSectionComponent
key={child.section.id}
projectId={projectId}
projectId={child.section.projectId}
section={child.section}
allSections={allSections}
workspaceShortcutLabels={workspaceShortcutLabels}
onWorkspaceHover={onWorkspaceHover}
onDelete={onDeleteSection}
onRename={onRenameSection}
onToggleCollapse={onToggleSectionCollapse}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ interface DashboardSidebarSectionProps {
section: DashboardSidebarSectionRecord;
allSections: Array<{ id: string; name: string }>;
workspaceShortcutLabels: Map<string, string>;
onWorkspaceHover: (workspaceId: string) => void | Promise<void>;
onDelete: (sectionId: string) => void;
onRename: (sectionId: string, name: string) => void;
onToggleCollapse: (sectionId: string) => void;
}

export function DashboardSidebarSection({
projectId,
section,
workspaceShortcutLabels,
onWorkspaceHover,
onDelete,
onRename,
onToggleCollapse,
Expand Down Expand Up @@ -72,9 +73,9 @@ export function DashboardSidebarSection({
</DashboardSidebarSectionContextMenu>

<DashboardSidebarSectionContent
projectId={projectId}
section={section}
workspaceShortcutLabels={workspaceShortcutLabels}
onWorkspaceHover={onWorkspaceHover}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import type { DashboardSidebarSection } from "../../../../types";
import { DashboardSidebarWorkspaceItem } from "../../../DashboardSidebarWorkspaceItem";

interface DashboardSidebarSectionContentProps {
projectId: string;
section: DashboardSidebarSection;
workspaceShortcutLabels: Map<string, string>;
onWorkspaceHover: (workspaceId: string) => void | Promise<void>;
}

export function DashboardSidebarSectionContent({
projectId,
section,
workspaceShortcutLabels,
onWorkspaceHover,
}: DashboardSidebarSectionContentProps) {
return (
<AnimatePresence initial={false}>
Expand All @@ -26,13 +26,9 @@ export function DashboardSidebarSectionContent({
<div>
{section.workspaces.map((workspace) => (
<DashboardSidebarWorkspaceItem
accentColor={workspace.accentColor}
key={workspace.id}
id={workspace.id}
projectId={projectId}
hostType={workspace.hostType}
name={workspace.name}
branch={workspace.branch}
workspace={workspace}
onHoverCardOpen={() => onWorkspaceHover(workspace.id)}
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Handle promise rejections from onWorkspaceHover. The callback can be async, but the handler ignores its promise, so a rejection becomes an unhandled promise rejection.

(Based on your team's feedback about handling async calls with proper await and catch.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarSection/components/DashboardSidebarSectionContent/DashboardSidebarSectionContent.tsx, line 31:

<comment>Handle promise rejections from `onWorkspaceHover`. The callback can be async, but the handler ignores its promise, so a rejection becomes an unhandled promise rejection.

(Based on your team's feedback about handling async calls with proper await and catch.) </comment>

<file context>
@@ -26,14 +26,9 @@ export function DashboardSidebarSectionContent({
-								branch={workspace.branch}
-								pullRequest={workspace.pullRequest}
+								workspace={workspace}
+								onHoverCardOpen={() => onWorkspaceHover(workspace.id)}
 								shortcutLabel={workspaceShortcutLabels.get(workspace.id)}
 							/>
</file context>
Fix with Cubic

shortcutLabel={workspaceShortcutLabels.get(workspace.id)}
/>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { DashboardSidebarWorkspace } from "../../types";
import { DashboardSidebarDeleteDialog } from "../DashboardSidebarDeleteDialog";
import { DashboardSidebarCollapsedWorkspaceButton } from "./components/DashboardSidebarCollapsedWorkspaceButton";
import { DashboardSidebarExpandedWorkspaceRow } from "./components/DashboardSidebarExpandedWorkspaceRow";
Expand All @@ -7,26 +8,26 @@ import { useDashboardSidebarWorkspaceItemActions } from "./hooks/useDashboardSid
import { getWorkspaceRowMocks } from "./utils";

interface DashboardSidebarWorkspaceItemProps {
id: string;
projectId: string;
accentColor?: string | null;
hostType: "local-device" | "remote-device" | "cloud";
name: string;
branch: string;
workspace: DashboardSidebarWorkspace;
onHoverCardOpen?: () => void;
shortcutLabel?: string;
isCollapsed?: boolean;
}

export function DashboardSidebarWorkspaceItem({
id,
projectId,
accentColor = null,
hostType,
name,
branch,
workspace,
onHoverCardOpen,
shortcutLabel,
isCollapsed = false,
}: DashboardSidebarWorkspaceItemProps) {
const {
id,
projectId,
accentColor = null,
hostType,
name,
branch,
} = workspace;
const mockData = getWorkspaceRowMocks(id);
const {
cancelRename,
Expand Down Expand Up @@ -57,10 +58,12 @@ export function DashboardSidebarWorkspaceItem({
<>
<DashboardSidebarWorkspaceContextMenu
projectId={projectId}
onHoverCardOpen={
hostType === "local-device" ? onHoverCardOpen : undefined
}
hoverCardContent={
<DashboardSidebarWorkspaceHoverCardContent
name={name}
branch={branch}
workspace={workspace}
mockData={mockData}
/>
}
Expand Down Expand Up @@ -108,10 +111,12 @@ export function DashboardSidebarWorkspaceItem({
<>
<DashboardSidebarWorkspaceContextMenu
projectId={projectId}
onHoverCardOpen={
hostType === "local-device" ? onHoverCardOpen : undefined
}
hoverCardContent={
<DashboardSidebarWorkspaceHoverCardContent
name={name}
branch={branch}
workspace={workspace}
mockData={mockData}
/>
}
Expand All @@ -126,10 +131,7 @@ export function DashboardSidebarWorkspaceItem({
onDelete={() => setIsDeleteDialogOpen(true)}
>
<DashboardSidebarExpandedWorkspaceRow
accentColor={accentColor}
hostType={hostType}
name={name}
branch={branch}
workspace={workspace}
isActive={isActive}
isRenaming={isRenaming}
renameValue={renameValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@ import { cn } from "@superset/ui/utils";
import { type ComponentPropsWithoutRef, forwardRef } from "react";
import { HiMiniXMark } from "react-icons/hi2";
import { RenameInput } from "renderer/screens/main/components/WorkspaceSidebar/RenameInput";
import type { DashboardSidebarWorkspaceHostType } from "../../../../types";
import type { DashboardSidebarWorkspace } from "../../../../types";
import type { WorkspaceRowMockData } from "../../utils";
import { DashboardSidebarWorkspaceDiffStats } from "../DashboardSidebarWorkspaceDiffStats";
import { DashboardSidebarWorkspaceIcon } from "../DashboardSidebarWorkspaceIcon";
import { DashboardSidebarWorkspaceStatusBadge } from "../DashboardSidebarWorkspaceStatusBadge";

interface DashboardSidebarExpandedWorkspaceRowProps
extends ComponentPropsWithoutRef<"div"> {
accentColor?: string | null;
hostType: DashboardSidebarWorkspaceHostType;
name: string;
branch: string;
workspace: DashboardSidebarWorkspace;
isActive: boolean;
isRenaming: boolean;
renameValue: string;
Expand All @@ -34,10 +31,7 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef<
>(
(
{
accentColor = null,
hostType,
name,
branch,
workspace,
isActive,
isRenaming,
renameValue,
Expand All @@ -54,8 +48,15 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef<
},
ref,
) => {
const {
accentColor = null,
hostType,
name,
branch,
pullRequest,
} = workspace;
const showBranchSubtitle = !!name && name !== branch;
const showSubtitle = showBranchSubtitle || !!mockData.pr;
const showSubtitle = showBranchSubtitle || !!pullRequest;
const showsStandaloneActiveStripe = accentColor == null;

return (
Expand Down Expand Up @@ -174,10 +175,11 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef<
</span>
)}

{mockData.pr && (
{pullRequest && (
<DashboardSidebarWorkspaceStatusBadge
state={mockData.pr.state}
prNumber={mockData.pr.number}
state={pullRequest.state}
prNumber={pullRequest.number}
prUrl={pullRequest.url}
className="col-start-2 row-start-2 justify-self-end"
/>
)}
Expand Down
Loading
Loading