Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
31 changes: 31 additions & 0 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4687,6 +4687,37 @@ describe("Git commit sidebar", () => {
expect(commitButton).toBeDisabled();
});

it("explains why Cmd+Enter did nothing and clears the hint once the user acts", async () => {
render(<App />);

expect(await treeButton("README.md")).toBeInTheDocument();
fireEvent.click(screen.getByTitle("Source control"));

const panel = await screen.findByLabelText("Git commit panel");
await waitFor(() => expect(within(panel).getByText("2 / 2")).toBeInTheDocument());
const message = within(panel).getByPlaceholderText("Commit message");

fireEvent.click(within(panel).getByLabelText("Deselect all changes"));
fireEvent.change(message, { target: { value: "Update readme" } });
fireEvent.keyDown(message, { key: "Enter", metaKey: true });
expect(
await within(panel).findByText("Select at least one file to commit."),
).toBeInTheDocument();

fireEvent.click(within(panel).getByLabelText("Select all changes"));
await waitFor(() =>
expect(
within(panel).queryByText("Select at least one file to commit."),
).not.toBeInTheDocument(),
);

fireEvent.change(message, { target: { value: " " } });
fireEvent.keyDown(message, { key: "Enter", metaKey: true });
Comment thread
GordonBeeming marked this conversation as resolved.
Outdated
expect(
await within(panel).findByText("Enter a commit message first."),
).toBeInTheDocument();
});
Comment thread
GordonBeeming marked this conversation as resolved.

it("commits only the selected paths and refreshes the status afterward", async () => {
render(<App />);

Expand Down
26 changes: 25 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,9 @@ export default function App() {
const [gitCommitInFlight, setGitCommitInFlight] = useState(false);
const [gitCommitError, setGitCommitError] = useState<string>();
const [gitCommitSuccess, setGitCommitSuccess] = useState<string>();
// Why-nothing-happened hint for Cmd/Ctrl+Enter in the message box — the
// Commit button disables itself, but the shortcut has no visual state.
const [gitCommitHint, setGitCommitHint] = useState<string>();
const [gitSyncInFlight, setGitSyncInFlight] = useState(false);
const [gitSyncResult, setGitSyncResult] = useState<GitSyncResult>();
const [gitSyncError, setGitSyncError] = useState<string>();
Expand Down Expand Up @@ -1652,6 +1655,12 @@ export default function App() {
return () => window.clearTimeout(timeoutId);
}, [gitCommitSuccess]);

// The commit hint answers "why did Cmd+Enter do nothing" — the moment the
// user changes the message or the file selection, the answer is stale.
useEffect(() => {
setGitCommitHint(undefined);
}, [gitCommitMessage, gitCommitSelectedPaths]);
Comment thread
GordonBeeming marked this conversation as resolved.
Outdated
Comment thread
GordonBeeming marked this conversation as resolved.
Outdated
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

// Sync notices are scoped to a commit-panel session; clear them on the way out
// so reopening the panel doesn't show a stale "Synced"/conflict line.
useEffect(() => {
Expand Down Expand Up @@ -1736,8 +1745,17 @@ export default function App() {
const handleGitCommit = useCallback(async () => {
const trimmedMessage = gitCommitMessage.trim();
const selectedPaths = changedFilePaths.filter((path) => gitCommitSelectedPaths.has(path));
if (!trimmedMessage || selectedPaths.length === 0 || gitCommitInFlight) return;
if (gitCommitInFlight) return;
if (selectedPaths.length === 0) {
setGitCommitHint("Select at least one file to commit.");
return;
}
if (!trimmedMessage) {
setGitCommitHint("Enter a commit message first.");
return;
}
Comment thread
GordonBeeming marked this conversation as resolved.

setGitCommitHint(undefined);
setGitCommitInFlight(true);
setGitCommitError(undefined);
setGitCommitSuccess(undefined);
Expand Down Expand Up @@ -5453,6 +5471,12 @@ export default function App() {
{gitCommitSuccess}
</div>
) : null}
{gitCommitHint ? (
<div className="commit-panel__notice commit-panel__notice--warning" role="status">
<TriangleAlert size={13} />
<span>{gitCommitHint}</span>
</div>
) : null}
</div>
</>
)}
Expand Down
27 changes: 14 additions & 13 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,20 @@ button {
color: var(--text);
}

.commit-panel__notice--warning {
display: flex;
align-items: center;
gap: 6px;
border: 1px solid color-mix(in oklch, var(--warning) 42%, var(--border));
background: color-mix(in oklch, var(--warning) 8%, var(--surface));
color: var(--text);
}

.commit-panel__notice--warning svg {
flex-shrink: 0;
color: var(--warning);
}

/* Transient success toasts (sync result, completed merge) hold, then ease out
over the last stretch of their ~5s life so removal doesn't just blink away.
The JS timeout clears the element at 5s; this only animates the opacity. */
Expand Down Expand Up @@ -1110,19 +1124,6 @@ button {
font-weight: 600;
}

.commit-panel__sync-conflicts {
margin: 0;
padding-left: 18px;
display: flex;
flex-direction: column;
gap: 2px;
}

.commit-panel__sync-conflicts li {
overflow-wrap: anywhere;
word-break: break-word;
}

/* Live merge-resolution block: a bordered call-out that replaces the normal
sync notice while a merge is unfinished. */
.commit-panel__merge {
Expand Down
Loading