Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TaskInput } from "@features/task-detail/components/TaskInput";
import { ArrowsOut, Plus, X } from "@phosphor-icons/react";
import { Flex, Text } from "@radix-ui/themes";
import type { Task } from "@shared/types";
Expand All @@ -15,6 +16,48 @@ interface CommandCenterPanelProps {

function EmptyCell({ cellIndex }: { cellIndex: number }) {
const [selectorOpen, setSelectorOpen] = useState(false);
const [isCreating, setIsCreating] = useState(false);
const assignTask = useCommandCenterStore((s) => s.assignTask);

const handleTaskCreated = useCallback(
(task: Task) => {
assignTask(cellIndex, task.id);
},
[assignTask, cellIndex],
);

if (isCreating) {
return (
<Flex direction="column" height="100%">
<Flex
align="center"
justify="between"
px="2"
py="1"
className="shrink-0 border-gray-6 border-b"
>
<Text
size="1"
weight="medium"
className="font-mono text-[11px] text-gray-11"
>
New task
</Text>
<button
type="button"
onClick={() => setIsCreating(false)}
className="flex h-5 w-5 items-center justify-center rounded text-gray-10 transition-colors hover:bg-gray-4 hover:text-gray-12"
title="Cancel"
>
<X size={12} />
</button>
</Flex>
<Flex direction="column" className="min-h-0 flex-1">
<TaskInput onTaskCreated={handleTaskCreated} />
</Flex>
</Flex>
);
}

return (
<Flex align="center" justify="center" height="100%">
Expand All @@ -23,6 +66,7 @@ function EmptyCell({ cellIndex }: { cellIndex: number }) {
cellIndex={cellIndex}
open={selectorOpen}
onOpenChange={setSelectorOpen}
onNewTask={() => setIsCreating(true)}
>
<button
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ interface TaskSelectorProps {
cellIndex: number;
open: boolean;
onOpenChange: (open: boolean) => void;
onNewTask?: () => void;
children: ReactNode;
}

export function TaskSelector({
cellIndex,
open,
onOpenChange,
onNewTask,
children,
}: TaskSelectorProps) {
const availableTasks = useAvailableTasks();
Expand All @@ -32,8 +34,12 @@ export function TaskSelector({

const handleNewTask = useCallback(() => {
onOpenChange(false);
navigateToTaskInput();
}, [onOpenChange, navigateToTaskInput]);
if (onNewTask) {
onNewTask();
} else {
navigateToTaskInput();
}
}, [onOpenChange, onNewTask, navigateToTaskInput]);

return (
<Popover.Root open={open} onOpenChange={onOpenChange}>
Expand All @@ -44,29 +50,31 @@ export function TaskSelector({
sideOffset={4}
style={{ padding: 4, minWidth: 240, maxHeight: 300 }}
>
<div className="overflow-y-auto" style={{ maxHeight: 280 }}>
<button
type="button"
onClick={handleNewTask}
className="flex w-full items-center gap-1.5 rounded-sm px-2 py-1.5 text-left font-mono text-[11px] text-gray-12 transition-colors hover:bg-gray-3"
>
<Plus size={12} className="shrink-0" />
<span>New task</span>
</button>
{availableTasks.length > 0 && (
<>
<Separator size="4" my="1" />
{availableTasks.map((task) => (
<button
key={task.id}
type="button"
onClick={() => handleSelect(task.id)}
className="flex w-full items-center rounded-sm px-2 py-1.5 text-left font-mono text-[11px] text-gray-12 transition-colors hover:bg-gray-3"
>
<span className="min-w-0 flex-1 truncate">{task.title}</span>
</button>
))}
</>
<button
type="button"
onClick={handleNewTask}
className="flex w-full items-center gap-1.5 rounded-sm px-2 py-1.5 text-left font-mono text-[11px] text-gray-12 transition-colors hover:bg-gray-3"
>
<Plus size={12} />
New task
</button>
<Separator size="4" className="my-1" />
<div className="overflow-y-auto" style={{ maxHeight: 240 }}>
{availableTasks.length === 0 ? (
<div className="px-2 py-3 text-center font-mono text-[11px] text-gray-10">
No available tasks
</div>
) : (
availableTasks.map((task) => (
<button
key={task.id}
type="button"
onClick={() => handleSelect(task.id)}
className="flex w-full items-center rounded-sm px-2 py-1.5 text-left font-mono text-[11px] text-gray-12 transition-colors hover:bg-gray-3"
>
<span className="min-w-0 flex-1 truncate">{task.title}</span>
</button>
))
)}
</div>
</Popover.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import { type WorkspaceMode, WorkspaceModeSelect } from "./WorkspaceModeSelect";

const DOT_FILL = "var(--gray-6)";

export function TaskInput() {
interface TaskInputProps {
onTaskCreated?: (task: import("@shared/types").Task) => void;
}

export function TaskInput({ onTaskCreated }: TaskInputProps = {}) {
const trpcReact = useTRPC();
const { view } = useNavigationStore();
const { data: mostRecentRepo } = useQuery(
Expand Down Expand Up @@ -131,6 +135,7 @@ export function TaskInput() {
executionMode: currentExecutionMode,
model: currentModel,
reasoningLevel: currentReasoningLevel,
onTaskCreated,
});

const handleCycleMode = useCallback(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useConnectivity } from "@hooks/useConnectivity";
import type { WorkspaceMode } from "@main/services/workspace/schemas";
import { get } from "@renderer/di/container";
import { RENDERER_TOKENS } from "@renderer/di/tokens";
import type { ExecutionMode } from "@shared/types";
import type { ExecutionMode, Task } from "@shared/types";
import { useNavigationStore } from "@stores/navigationStore";
import { logger } from "@utils/logger";
import { useCallback, useState } from "react";
Expand All @@ -30,6 +30,7 @@ interface UseTaskCreationOptions {
adapter?: "claude" | "codex";
model?: string;
reasoningLevel?: string;
onTaskCreated?: (task: Task) => void;
}

interface UseTaskCreationReturn {
Expand Down Expand Up @@ -91,6 +92,7 @@ export function useTaskCreation({
adapter,
model,
reasoningLevel,
onTaskCreated,
}: UseTaskCreationOptions): UseTaskCreationReturn {
const [isCreatingTask, setIsCreatingTask] = useState(false);
const { navigateToTask } = useNavigationStore();
Expand Down Expand Up @@ -140,8 +142,12 @@ export function useTaskCreation({
// Invalidate tasks query
invalidateTasks(task);

// Navigate to the new task
navigateToTask(task);
// Navigate to the new task or notify caller
if (onTaskCreated) {
onTaskCreated(task);
} else {
navigateToTask(task);
}

// Clear editor
editor.clear();
Expand Down Expand Up @@ -176,6 +182,7 @@ export function useTaskCreation({
reasoningLevel,
invalidateTasks,
navigateToTask,
onTaskCreated,
]);

return {
Expand Down
Loading