mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
Merge pull request #505 from AutoMaker-Org/feature/v0.12.0rc-1768509532254-tt6z
fix: "Remove Project" button not working on right click of the project
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useRef, useState, memo } from 'react';
|
||||
import { useEffect, useRef, useState, memo, useCallback } from 'react';
|
||||
import type { LucideIcon } from 'lucide-react';
|
||||
import { Edit2, Trash2, Palette, ChevronRight, Moon, Sun, Monitor } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { type ThemeMode, useAppStore } from '@/store/app-store';
|
||||
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||
@@ -8,6 +9,9 @@ import type { Project } from '@/lib/electron';
|
||||
import { PROJECT_DARK_THEMES, PROJECT_LIGHT_THEMES } from '@/components/layout/sidebar/constants';
|
||||
import { useThemePreview } from '@/components/layout/sidebar/hooks';
|
||||
|
||||
// Constant for "use global theme" option
|
||||
const USE_GLOBAL_THEME = '' as const;
|
||||
|
||||
// Constants for z-index values
|
||||
const Z_INDEX = {
|
||||
CONTEXT_MENU: 100,
|
||||
@@ -124,19 +128,26 @@ export function ProjectContextMenu({
|
||||
} = useAppStore();
|
||||
const [showRemoveDialog, setShowRemoveDialog] = useState(false);
|
||||
const [showThemeSubmenu, setShowThemeSubmenu] = useState(false);
|
||||
const [removeConfirmed, setRemoveConfirmed] = useState(false);
|
||||
const themeSubmenuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { handlePreviewEnter, handlePreviewLeave } = useThemePreview({ setPreviewTheme });
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
||||
const handleClickOutside = (event: globalThis.MouseEvent) => {
|
||||
// Don't close if a confirmation dialog is open (dialog is in a portal)
|
||||
if (showRemoveDialog) return;
|
||||
|
||||
if (menuRef.current && !menuRef.current.contains(event.target as globalThis.Node)) {
|
||||
setPreviewTheme(null);
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
const handleEscape = (event: KeyboardEvent) => {
|
||||
const handleEscape = (event: globalThis.KeyboardEvent) => {
|
||||
// Don't close if a confirmation dialog is open (let the dialog handle escape)
|
||||
if (showRemoveDialog) return;
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
setPreviewTheme(null);
|
||||
onClose();
|
||||
@@ -150,7 +161,7 @@ export function ProjectContextMenu({
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
document.removeEventListener('keydown', handleEscape);
|
||||
};
|
||||
}, [onClose, setPreviewTheme]);
|
||||
}, [onClose, setPreviewTheme, showRemoveDialog]);
|
||||
|
||||
const handleEdit = () => {
|
||||
onEdit(project);
|
||||
@@ -160,24 +171,44 @@ export function ProjectContextMenu({
|
||||
setShowRemoveDialog(true);
|
||||
};
|
||||
|
||||
const handleThemeSelect = (value: ThemeMode | '') => {
|
||||
const handleThemeSelect = useCallback(
|
||||
(value: ThemeMode | typeof USE_GLOBAL_THEME) => {
|
||||
setPreviewTheme(null);
|
||||
if (value !== '') {
|
||||
setTheme(value);
|
||||
} else {
|
||||
setTheme(globalTheme);
|
||||
}
|
||||
setProjectTheme(project.id, value === '' ? null : value);
|
||||
const isUsingGlobal = value === USE_GLOBAL_THEME;
|
||||
setTheme(isUsingGlobal ? globalTheme : value);
|
||||
setProjectTheme(project.id, isUsingGlobal ? null : value);
|
||||
setShowThemeSubmenu(false);
|
||||
};
|
||||
},
|
||||
[globalTheme, project.id, setPreviewTheme, setProjectTheme, setTheme]
|
||||
);
|
||||
|
||||
const handleConfirmRemove = () => {
|
||||
const handleConfirmRemove = useCallback(() => {
|
||||
moveProjectToTrash(project.id);
|
||||
toast.success('Project removed', {
|
||||
description: `${project.name} has been removed from your projects list`,
|
||||
});
|
||||
setRemoveConfirmed(true);
|
||||
}, [moveProjectToTrash, project.id, project.name]);
|
||||
|
||||
const handleDialogClose = useCallback(
|
||||
(isOpen: boolean) => {
|
||||
setShowRemoveDialog(isOpen);
|
||||
// Close the context menu when dialog closes (whether confirmed or cancelled)
|
||||
// This prevents the context menu from reappearing after dialog interaction
|
||||
if (!isOpen) {
|
||||
// Reset confirmation state
|
||||
setRemoveConfirmed(false);
|
||||
// Always close the context menu when dialog closes
|
||||
onClose();
|
||||
};
|
||||
}
|
||||
},
|
||||
[onClose]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Hide context menu when confirm dialog is open */}
|
||||
{!showRemoveDialog && (
|
||||
<div
|
||||
ref={menuRef}
|
||||
className={cn(
|
||||
@@ -255,7 +286,7 @@ export function ProjectContextMenu({
|
||||
<button
|
||||
onPointerEnter={() => handlePreviewEnter(globalTheme)}
|
||||
onPointerLeave={handlePreviewLeave}
|
||||
onClick={() => handleThemeSelect('')}
|
||||
onClick={() => handleThemeSelect(USE_GLOBAL_THEME)}
|
||||
className={cn(
|
||||
'w-full flex items-center gap-2 px-3 py-2 rounded-md',
|
||||
'text-sm font-medium text-left',
|
||||
@@ -316,10 +347,11 @@ export function ProjectContextMenu({
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ConfirmDialog
|
||||
open={showRemoveDialog}
|
||||
onOpenChange={setShowRemoveDialog}
|
||||
onOpenChange={handleDialogClose}
|
||||
onConfirm={handleConfirmRemove}
|
||||
title="Remove Project"
|
||||
description={`Are you sure you want to remove "${project.name}" from the project list? This won't delete any files on disk.`}
|
||||
|
||||
Reference in New Issue
Block a user