diff --git a/src/components/command-palette/CommandPalette.tsx b/src/components/command-palette/CommandPalette.tsx index 7f66c554..cd4ac593 100644 --- a/src/components/command-palette/CommandPalette.tsx +++ b/src/components/command-palette/CommandPalette.tsx @@ -95,7 +95,7 @@ export function CommandPalette({ notesFolder, } = useNotes(); const { setTheme } = useTheme(); - const { status, gitAvailable, gitEnabled, commit, sync, isSyncing } = useGit(); + const { status, gitAvailable, gitEnabled, sync, isSyncing } = useGit(); const [query, setQuery] = useState(""); const [selectedIndex, setSelectedIndex] = useState(0); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); @@ -376,15 +376,12 @@ export function CommandPalette({ if (hasChanges) { baseCommands.push({ id: "git-commit", - label: "Git: Quick Commit", + label: "Git: Commit Changes", icon: , action: async () => { - const success = await commit("Quick commit from Scratch"); - if (success) { - toast.success("Changes committed"); - } else { - toast.error("Failed to commit"); - } + window.dispatchEvent( + new CustomEvent("open-commit-panel") + ) onClose(); }, }); @@ -514,7 +511,6 @@ export function CommandPalette({ gitEnabled, gitAvailable, status, - commit, sync, isSyncing, selectNote, diff --git a/src/components/git/CommitPanel.tsx b/src/components/git/CommitPanel.tsx new file mode 100644 index 00000000..5222b0bd --- /dev/null +++ b/src/components/git/CommitPanel.tsx @@ -0,0 +1,118 @@ +import { + useCallback, + useEffect, + useMemo, + useRef, + useState, + type KeyboardEvent, +} from "react"; +import { toast } from "sonner"; +import { useGit } from "../../context/GitContext"; +import { Button, Textarea } from "../ui"; + +const DEFAULT_COMMIT_MESSAGE = "Quick Commit from Scratch"; + +interface CommitPanelProps { + open: boolean; + onClose: () => void; +} + +export function CommitPanel({ open, onClose }: CommitPanelProps) { + const { commit, isCommitting } = useGit(); + + const [message, setMessage] = useState(DEFAULT_COMMIT_MESSAGE); + + const textareaRef = useRef(null); + + useEffect(() => { + if (!open) { + return; + } + + setMessage(DEFAULT_COMMIT_MESSAGE); + + requestAnimationFrame(() => { + textareaRef.current?.focus(); + textareaRef.current?.select(); + }); + }, [open]); + + const canCommit = useMemo(() => message.trim().length > 0, [message]); + + const handleCommit = useCallback(async () => { + const commitMessage = message.trim(); + + if (!commitMessage || isCommitting) { + return; + } + + try { + const success = await commit(commitMessage); + + if (success) { + toast.success("Changes committed"); + onClose(); + } else { + toast.error("Failed to commit"); + } + } catch { + toast.error("Failed to commit"); + } + }, [commit, isCommitting, message, onClose]); + + const handleKeyDown = useCallback( + async (event: KeyboardEvent) => { + if (event.key === "Escape") { + event.preventDefault(); + onClose(); + return; + } + + if (event.key === "Enter" && !event.shiftKey) { + event.preventDefault(); + await handleCommit(); + } + }, + [handleCommit, onClose], + ); + + if (!open) { + return null; + } + + return ( +
+
+

Commit Changes

+ +

+ Enter to commit • Shift+Enter for newline +

+
+ +