Add ⌘S hotkey to open a task's merge confirmation
This commit is contained in:
Vendored
+7
@@ -3,6 +3,7 @@ import { errorText, h, replace, showAlert } from "./dom.js";
|
||||
import { openSettings } from "./settings.js";
|
||||
import { activeTasks, currentSession, focusedProject, focusProject, focusTab, focusTask, lastVisits, onEach, state } from "./state.js";
|
||||
import { openStatus } from "./status.js";
|
||||
import { confirmMerge } from "./task.js";
|
||||
export function mountNavbar(root) {
|
||||
const status = h("button", { class: "nav-link" }, "Status");
|
||||
status.onclick = openStatus;
|
||||
@@ -32,6 +33,12 @@ export function mountNavbar(root) {
|
||||
e.preventDefault();
|
||||
focusTab("project");
|
||||
}
|
||||
else if (e.key === "s") {
|
||||
e.preventDefault();
|
||||
if (state.selectedTaskId) {
|
||||
void confirmMerge(state.selectedTaskId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
export function openSwitcher() {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+28
-14
@@ -80,21 +80,9 @@ function taskHead(rerender) {
|
||||
disabled: busy || held || unmerged?.taskId !== task.id || !unmerged.has,
|
||||
title: held
|
||||
? "Waiting for the merge in progress in this project to finish"
|
||||
: `The agent merges ${target} in, then byre squashes into one commit on ${target} and pushes it to origin; held while another task in the project is merging`,
|
||||
: `The agent merges ${target} in, then byre squashes into one commit on ${target} and pushes it to origin; held while another task in the project is merging (⌘S)`,
|
||||
}, held ? "Merge held" : "Merge");
|
||||
merge.onclick = async () => {
|
||||
let coAuthors;
|
||||
try {
|
||||
coAuthors = await get("/api/tasks/{taskId}/co-authors", { path: { taskId: task.id } });
|
||||
}
|
||||
catch (err) {
|
||||
void showAlert(errorText(err));
|
||||
return;
|
||||
}
|
||||
await confirmThen(mergeQuestion(task.merge_title, target, coAuthors), "Merge", false, async () => {
|
||||
await post("/api/tasks/{taskId}/merge", { path: { taskId: task.id } });
|
||||
});
|
||||
};
|
||||
merge.onclick = () => confirmMerge(task.id);
|
||||
const mergeIn = h("button", { disabled: busy, title: `Ask the agent to bring ${target} into this branch and resolve any conflicts` }, `Sync from ${target}`);
|
||||
mergeIn.onclick = async () => {
|
||||
mergeIn.disabled = true;
|
||||
@@ -882,6 +870,32 @@ function messageImages(ids) {
|
||||
return h("a", { href: src, target: "_blank", rel: "noopener" }, h("img", { src, alt: "attached image", loading: "lazy" }));
|
||||
}));
|
||||
}
|
||||
export async function confirmMerge(taskId) {
|
||||
const task = findTask(taskId);
|
||||
const sessionState = currentSession(taskId)?.state;
|
||||
if (!task || task.status !== "active" || task.merge_queued_at !== undefined || sessionState === "running" || sessionState === "queued") {
|
||||
return;
|
||||
}
|
||||
const target = state.projects.find((p) => p.id === task.project_id)?.default_branch ?? "the default branch";
|
||||
let coAuthors;
|
||||
try {
|
||||
const [unmerged, people] = await Promise.all([
|
||||
get("/api/tasks/{taskId}/unmerged", { path: { taskId } }),
|
||||
get("/api/tasks/{taskId}/co-authors", { path: { taskId } }),
|
||||
]);
|
||||
if (unmerged.commits === 0 && unmerged.files === 0) {
|
||||
return;
|
||||
}
|
||||
coAuthors = people;
|
||||
}
|
||||
catch (err) {
|
||||
void showAlert(errorText(err));
|
||||
return;
|
||||
}
|
||||
await confirmThen(mergeQuestion(task.merge_title, target, coAuthors), "Merge", false, async () => {
|
||||
await post("/api/tasks/{taskId}/merge", { path: { taskId } });
|
||||
});
|
||||
}
|
||||
function mergeQuestion(title, target, coAuthors) {
|
||||
const lines = [`Merge "${title}" into ${target}?`];
|
||||
const credited = coAuthors.filter((p) => p.git_name && p.git_email);
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@ import { errorText, h, replace, showAlert } from "./dom.js";
|
||||
import { openSettings } from "./settings.js";
|
||||
import { activeTasks, currentSession, focusedProject, focusProject, focusTab, focusTask, lastVisits, onEach, state } from "./state.js";
|
||||
import { openStatus } from "./status.js";
|
||||
import { confirmMerge } from "./task.js";
|
||||
|
||||
export function mountNavbar(root: HTMLElement): void {
|
||||
const status = h("button", { class: "nav-link" }, "Status");
|
||||
@@ -36,6 +37,11 @@ export function mountNavbar(root: HTMLElement): void {
|
||||
} else if (e.key === "p") {
|
||||
e.preventDefault();
|
||||
focusTab("project");
|
||||
} else if (e.key === "s") {
|
||||
e.preventDefault();
|
||||
if (state.selectedTaskId) {
|
||||
void confirmMerge(state.selectedTaskId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+28
-13
@@ -141,22 +141,11 @@ function taskHead(rerender: () => void): Head {
|
||||
disabled: busy || held || unmerged?.taskId !== task.id || !unmerged.has,
|
||||
title: held
|
||||
? "Waiting for the merge in progress in this project to finish"
|
||||
: `The agent merges ${target} in, then byre squashes into one commit on ${target} and pushes it to origin; held while another task in the project is merging`,
|
||||
: `The agent merges ${target} in, then byre squashes into one commit on ${target} and pushes it to origin; held while another task in the project is merging (⌘S)`,
|
||||
},
|
||||
held ? "Merge held" : "Merge",
|
||||
);
|
||||
merge.onclick = async () => {
|
||||
let coAuthors;
|
||||
try {
|
||||
coAuthors = await get("/api/tasks/{taskId}/co-authors", { path: { taskId: task.id } });
|
||||
} catch (err) {
|
||||
void showAlert(errorText(err));
|
||||
return;
|
||||
}
|
||||
await confirmThen(mergeQuestion(task.merge_title, target, coAuthors), "Merge", false, async () => {
|
||||
await post("/api/tasks/{taskId}/merge", { path: { taskId: task.id } });
|
||||
});
|
||||
};
|
||||
merge.onclick = () => confirmMerge(task.id);
|
||||
const mergeIn = h("button", { disabled: busy, title: `Ask the agent to bring ${target} into this branch and resolve any conflicts` }, `Sync from ${target}`);
|
||||
mergeIn.onclick = async () => {
|
||||
mergeIn.disabled = true;
|
||||
@@ -1058,6 +1047,32 @@ function messageImages(ids: unknown): HTMLElement | null {
|
||||
);
|
||||
}
|
||||
|
||||
export async function confirmMerge(taskId: string): Promise<void> {
|
||||
const task = findTask(taskId);
|
||||
const sessionState = currentSession(taskId)?.state;
|
||||
if (!task || task.status !== "active" || task.merge_queued_at !== undefined || sessionState === "running" || sessionState === "queued") {
|
||||
return;
|
||||
}
|
||||
const target = state.projects.find((p) => p.id === task.project_id)?.default_branch ?? "the default branch";
|
||||
let coAuthors;
|
||||
try {
|
||||
const [unmerged, people] = await Promise.all([
|
||||
get("/api/tasks/{taskId}/unmerged", { path: { taskId } }),
|
||||
get("/api/tasks/{taskId}/co-authors", { path: { taskId } }),
|
||||
]);
|
||||
if (unmerged.commits === 0 && unmerged.files === 0) {
|
||||
return;
|
||||
}
|
||||
coAuthors = people;
|
||||
} catch (err) {
|
||||
void showAlert(errorText(err));
|
||||
return;
|
||||
}
|
||||
await confirmThen(mergeQuestion(task.merge_title, target, coAuthors), "Merge", false, async () => {
|
||||
await post("/api/tasks/{taskId}/merge", { path: { taskId } });
|
||||
});
|
||||
}
|
||||
|
||||
function mergeQuestion(title: string, target: string, coAuthors: Participant[]): string {
|
||||
const lines = [`Merge "${title}" into ${target}?`];
|
||||
const credited = coAuthors.filter((p) => p.git_name && p.git_email);
|
||||
|
||||
Reference in New Issue
Block a user