mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 08:53:36 +00:00
Remove 5-project limit from project dropdown
- Remove .slice(0, 5) to show all projects in dropdown - Extend keyboard shortcuts to support 1-9 (was 1-5) - Only show hotkey indicators for first 9 projects - Update tests to reflect new behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,27 @@
|
||||
"category": "Core",
|
||||
"description": "I want the ability to press P which will automatically select my projects drop down and show all my projects. And then for each one, put a hotkey in the left that says 12345 and selecting one of those with my keyboard should automatically select that project.\n",
|
||||
"steps": [],
|
||||
"status": "in_progress",
|
||||
"startedAt": "2025-12-09T17:11:14.402Z"
|
||||
"status": "in_progress"
|
||||
},
|
||||
{
|
||||
"id": "feature-1765301095506-cpy06q9u0",
|
||||
"category": "Core",
|
||||
"description": "It seems like there's only a limit of five of how many things show up in the project select drop down. I need to show everything.",
|
||||
"steps": [],
|
||||
"status": "verified"
|
||||
},
|
||||
{
|
||||
"id": "feature-1765301127030-a4nnqp0ja",
|
||||
"category": "Kanban",
|
||||
"description": "In creating new cards in Kanban, I need the ability to drag and drop images into the description section, which will attach the image as context in store in the temp directory, so that later on when the agent runs, it can know where to fetch that image from.",
|
||||
"steps": [],
|
||||
"status": "in_progress"
|
||||
},
|
||||
{
|
||||
"id": "feature-1765301184184-ttvhd8kkt",
|
||||
"category": "Core",
|
||||
"description": "-o should actually open the select folder prompt. Right now when you click o it goes to like the overview page. That's not the correct experience I'm looking for. Also just clicking on the top left open folder icon should do the same thing of opening the system prompt so they can select a project.",
|
||||
"steps": [],
|
||||
"status": "in_progress"
|
||||
}
|
||||
]
|
||||
@@ -37,6 +37,9 @@ import {
|
||||
ACTION_SHORTCUTS,
|
||||
KeyboardShortcut,
|
||||
} from "@/hooks/use-keyboard-shortcuts";
|
||||
import { getElectronAPI } from "@/lib/electron";
|
||||
import { initializeProject } from "@/lib/project-init";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface NavSection {
|
||||
label?: string;
|
||||
@@ -56,6 +59,7 @@ export function Sidebar() {
|
||||
currentProject,
|
||||
currentView,
|
||||
sidebarOpen,
|
||||
addProject,
|
||||
setCurrentProject,
|
||||
setCurrentView,
|
||||
toggleSidebar,
|
||||
@@ -65,6 +69,56 @@ export function Sidebar() {
|
||||
// State for project picker dropdown
|
||||
const [isProjectPickerOpen, setIsProjectPickerOpen] = useState(false);
|
||||
|
||||
/**
|
||||
* Opens the system folder selection dialog and initializes the selected project.
|
||||
* Used by both the 'O' keyboard shortcut and the folder icon button.
|
||||
*/
|
||||
const handleOpenFolder = useCallback(async () => {
|
||||
const api = getElectronAPI();
|
||||
const result = await api.openDirectory();
|
||||
|
||||
if (!result.canceled && result.filePaths[0]) {
|
||||
const path = result.filePaths[0];
|
||||
const name = path.split("/").pop() || "Untitled Project";
|
||||
|
||||
try {
|
||||
// Initialize the .automaker directory structure
|
||||
const initResult = await initializeProject(path);
|
||||
|
||||
if (!initResult.success) {
|
||||
toast.error("Failed to initialize project", {
|
||||
description: initResult.error || "Unknown error occurred",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const project = {
|
||||
id: `project-${Date.now()}`,
|
||||
name,
|
||||
path,
|
||||
lastOpened: new Date().toISOString(),
|
||||
};
|
||||
|
||||
addProject(project);
|
||||
setCurrentProject(project);
|
||||
|
||||
if (initResult.createdFiles && initResult.createdFiles.length > 0) {
|
||||
toast.success(initResult.isNewProject ? "Project initialized" : "Project updated", {
|
||||
description: `Set up ${initResult.createdFiles.length} file(s) in .automaker`,
|
||||
});
|
||||
} else {
|
||||
toast.success("Project opened", {
|
||||
description: `Opened ${name}`,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[Sidebar] Failed to open project:", error);
|
||||
toast.error("Failed to open project", {
|
||||
description: error instanceof Error ? error.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [addProject, setCurrentProject]);
|
||||
|
||||
const navSections: NavSection[] = [
|
||||
{
|
||||
@@ -99,7 +153,7 @@ export function Sidebar() {
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
const num = parseInt(event.key, 10);
|
||||
if (num >= 1 && num <= 5) {
|
||||
if (num >= 1 && num <= 9) {
|
||||
event.preventDefault();
|
||||
selectProjectByNumber(num);
|
||||
} else if (event.key === "Escape") {
|
||||
@@ -122,11 +176,11 @@ export function Sidebar() {
|
||||
description: "Toggle sidebar",
|
||||
});
|
||||
|
||||
// Open project shortcut - always available
|
||||
// Open project shortcut - opens the folder selection dialog directly
|
||||
shortcuts.push({
|
||||
key: ACTION_SHORTCUTS.openProject,
|
||||
action: () => setCurrentView("welcome"),
|
||||
description: "Open project (navigate to welcome view)",
|
||||
action: () => handleOpenFolder(),
|
||||
description: "Open folder selection dialog",
|
||||
});
|
||||
|
||||
// Project picker shortcut - only when we have projects
|
||||
@@ -161,7 +215,7 @@ export function Sidebar() {
|
||||
}
|
||||
|
||||
return shortcuts;
|
||||
}, [currentProject, setCurrentView, toggleSidebar, projects.length]);
|
||||
}, [currentProject, setCurrentView, toggleSidebar, projects.length, handleOpenFolder]);
|
||||
|
||||
// Register keyboard shortcuts
|
||||
useKeyboardShortcuts(navigationShortcuts);
|
||||
@@ -241,9 +295,9 @@ export function Sidebar() {
|
||||
<Plus className="w-4 h-4 flex-shrink-0" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setCurrentView("welcome")}
|
||||
onClick={handleOpenFolder}
|
||||
className="group flex items-center justify-center w-8 h-8 rounded-lg relative overflow-hidden transition-all text-zinc-400 hover:text-white hover:bg-white/5"
|
||||
title={`Open Project (${ACTION_SHORTCUTS.openProject})`}
|
||||
title={`Open Folder (${ACTION_SHORTCUTS.openProject})`}
|
||||
data-testid="open-project-button"
|
||||
>
|
||||
<FolderOpen className="w-4 h-4 flex-shrink-0" />
|
||||
@@ -283,7 +337,7 @@ export function Sidebar() {
|
||||
align="start"
|
||||
data-testid="project-picker-dropdown"
|
||||
>
|
||||
{projects.slice(0, 5).map((project, index) => (
|
||||
{projects.map((project, index) => (
|
||||
<DropdownMenuItem
|
||||
key={project.id}
|
||||
onClick={() => {
|
||||
@@ -293,12 +347,14 @@ export function Sidebar() {
|
||||
className="flex items-center gap-2 cursor-pointer text-zinc-300 hover:text-white hover:bg-zinc-700/50"
|
||||
data-testid={`project-option-${project.id}`}
|
||||
>
|
||||
<span
|
||||
className="flex items-center justify-center w-5 h-5 text-[10px] font-mono rounded bg-white/5 border border-white/10 text-zinc-400"
|
||||
data-testid={`project-hotkey-${index + 1}`}
|
||||
>
|
||||
{index + 1}
|
||||
</span>
|
||||
{index < 9 && (
|
||||
<span
|
||||
className="flex items-center justify-center w-5 h-5 text-[10px] font-mono rounded bg-white/5 border border-white/10 text-zinc-400"
|
||||
data-testid={`project-hotkey-${index + 1}`}
|
||||
>
|
||||
{index + 1}
|
||||
</span>
|
||||
)}
|
||||
<Folder className="h-4 w-4" />
|
||||
<span className="flex-1 truncate">{project.name}</span>
|
||||
{currentProject?.id === project.id && (
|
||||
|
||||
@@ -152,9 +152,9 @@ test.describe("Project Picker Keyboard Shortcuts", () => {
|
||||
await expect(shortcutIndicator).toHaveText("P");
|
||||
});
|
||||
|
||||
test("only first 5 projects are shown with hotkeys", async ({ page }) => {
|
||||
// Setup with 7 projects
|
||||
await setupMockMultipleProjects(page, 7);
|
||||
test("all projects are shown, with hotkeys for first 9", async ({ page }) => {
|
||||
// Setup with 10 projects
|
||||
await setupMockMultipleProjects(page, 10);
|
||||
await page.goto("/");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
@@ -165,16 +165,20 @@ test.describe("Project Picker Keyboard Shortcuts", () => {
|
||||
await pressShortcut(page, "p");
|
||||
await waitForProjectPickerDropdown(page);
|
||||
|
||||
// Only 5 hotkey indicators should be visible (1-5)
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
// All 10 projects should be visible
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
const projectOption = page.locator(`[data-testid="project-option-test-project-${i}"]`);
|
||||
await expect(projectOption).toBeVisible();
|
||||
}
|
||||
|
||||
// First 9 hotkey indicators should be visible (1-9)
|
||||
for (let i = 1; i <= 9; i++) {
|
||||
expect(await isProjectHotkeyVisible(page, i)).toBe(true);
|
||||
}
|
||||
|
||||
// 6th and 7th should not exist
|
||||
const hotkey6 = page.locator('[data-testid="project-hotkey-6"]');
|
||||
const hotkey7 = page.locator('[data-testid="project-hotkey-7"]');
|
||||
await expect(hotkey6).not.toBeVisible();
|
||||
await expect(hotkey7).not.toBeVisible();
|
||||
// 10th hotkey should not exist (no keyboard shortcut for it)
|
||||
const hotkey10 = page.locator('[data-testid="project-hotkey-10"]');
|
||||
await expect(hotkey10).not.toBeVisible();
|
||||
});
|
||||
|
||||
test("clicking a project option also works", async ({ page }) => {
|
||||
|
||||
Reference in New Issue
Block a user