Skip to content
Open
Changes from all commits
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
42 changes: 41 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,21 @@ <h3 class="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">Error<
}, FEEDBACK_DISMISS_DELAY);
}

function showSuccessToast(message) {
// Show a temporary global success message (toast)
const toast = document.createElement('div');
toast.className = 'fixed top-4 right-4 z-[100] flex items-start gap-2 rounded-lg border border-green-200 bg-green-50 px-4 py-3 text-sm text-green-900 shadow-lg dark:border-green-900 dark:bg-green-950/30 dark:text-green-400 max-w-md animate-slide-in';
toast.innerHTML = `
<span class="inline-flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full bg-green-100 text-xs font-bold text-green-700 dark:bg-green-900 dark:text-green-400">✓</span>
<div class="leading-5">${escapeHtml(message)}</div>
`;
document.body.appendChild(toast);
setTimeout(() => {
toast.classList.add('opacity-0', 'transition-opacity', 'duration-500');
setTimeout(() => toast.remove(), 500);
}, FEEDBACK_DISMISS_DELAY);
}

function showSectionMessage(message, type) {
// Show an inline feedback message in the Add PR section on the page
const section = document.getElementById('prUrlInput')?.closest('section');
Expand Down Expand Up @@ -2512,7 +2527,12 @@ <h3 class="text-xl font-semibold text-slate-900 dark:text-slate-100">${emptyTitl
</td>
<td class="px-2 py-3">${reviewBadge}</td>
<td class="px-2 py-3">${renderReviewerAvatars(pr.reviewers_json)}</td>
<td class="px-2 py-3 text-slate-700 dark:text-slate-300 text-xs truncate">${escapeHtml(mergeableText)}</td>
<td class="px-2 py-3 text-slate-700 dark:text-slate-300 text-xs">
<span class="inline-flex items-center gap-1">
${escapeHtml(mergeableText)}
${mergeableText === 'Conflicts' ? `<button class="conflict-message-btn inline-flex items-center justify-center rounded text-orange-500 hover:text-orange-700 dark:text-orange-400 dark:hover:text-orange-300 focus:outline-none focus:ring-1 focus:ring-orange-400" data-pr-url="${escapeHtml(pr.pr_url)}" data-author-login="${escapeHtml(pr.author_login)}" title="Open PR and copy a conflict resolution message to clipboard" aria-label="Copy conflict message and open PR"><i class="fas fa-comment-dots"></i></button>` : ''}
</span>
</td>
<td class="px-2 py-3 text-center text-slate-700 dark:text-slate-300 text-xs">${pr.files_changed}</td>
<td class="px-2 py-3 text-center text-slate-700 dark:text-slate-300 text-xs">${pr.commits_count || 0}</td>
<td class="px-2 py-3 text-center text-slate-700 dark:text-slate-300 text-xs">
Expand Down Expand Up @@ -2589,6 +2609,26 @@ <h3 class="text-xl font-semibold text-slate-900 dark:text-slate-100">${emptyTitl
</td>
`;

// Add click handler for the conflict message button
const conflictMessageBtn = row.querySelector('.conflict-message-btn');
if (conflictMessageBtn) {
conflictMessageBtn.addEventListener('click', async (e) => {
e.stopPropagation();
const prUrl = conflictMessageBtn.dataset.prUrl;
const authorLogin = conflictMessageBtn.dataset.authorLogin;
const authorMention = authorLogin && /^[a-zA-Z0-9_.-]+$/.test(authorLogin) ? `@${authorLogin}` : 'contributor';
const message = `Hi ${authorMention}, this PR has merge conflicts that need to be resolved before it can be merged. Could you please fix the conflicts? Thank you!`;
const prUrlWithComment = `${prUrl}?expand=1&body=${encodeURIComponent(message)}`;
try {
await navigator.clipboard.writeText(message);
showSuccessToast('Opening PR with conflict message pre-filled...');
} catch (err) {
console.error('Failed to copy conflict message:', err);
}
Comment on lines +2622 to +2627
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The success toast is only shown when navigator.clipboard.writeText succeeds. If clipboard access is denied/unavailable, the PR still opens but no toast is shown, which doesn’t match the described behavior of always confirming the action. Consider showing a success toast for the tab-open action regardless, and separately showing a warning/error toast if clipboard copy fails.

Copilot uses AI. Check for mistakes.
window.open(prUrlWithComment, '_blank', 'noopener,noreferrer');
Comment on lines +2615 to +2628
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

window.open(...) is called after await navigator.clipboard.writeText(...). Awaiting an async operation can cause the browser to treat the later window.open as not being directly user-initiated, which may trigger popup blocking and break the shortcut. Open the new tab synchronously within the click handler (before awaiting), or avoid await by handling the clipboard promise without delaying the window.open call.

Suggested change
conflictMessageBtn.addEventListener('click', async (e) => {
e.stopPropagation();
const prUrl = conflictMessageBtn.dataset.prUrl;
const authorLogin = conflictMessageBtn.dataset.authorLogin;
const authorMention = authorLogin && /^[a-zA-Z0-9_.-]+$/.test(authorLogin) ? `@${authorLogin}` : 'contributor';
const message = `Hi ${authorMention}, this PR has merge conflicts that need to be resolved before it can be merged. Could you please fix the conflicts? Thank you!`;
const prUrlWithComment = `${prUrl}?expand=1&body=${encodeURIComponent(message)}`;
try {
await navigator.clipboard.writeText(message);
showSuccessToast('Opening PR with conflict message pre-filled...');
} catch (err) {
console.error('Failed to copy conflict message:', err);
}
window.open(prUrlWithComment, '_blank', 'noopener,noreferrer');
conflictMessageBtn.addEventListener('click', (e) => {
e.stopPropagation();
const prUrl = conflictMessageBtn.dataset.prUrl;
const authorLogin = conflictMessageBtn.dataset.authorLogin;
const authorMention = authorLogin && /^[a-zA-Z0-9_.-]+$/.test(authorLogin) ? `@${authorLogin}` : 'contributor';
const message = `Hi ${authorMention}, this PR has merge conflicts that need to be resolved before it can be merged. Could you please fix the conflicts? Thank you!`;
const prUrlWithComment = `${prUrl}?expand=1&body=${encodeURIComponent(message)}`;
// Open the PR in a new tab synchronously in response to the click
window.open(prUrlWithComment, '_blank', 'noopener,noreferrer');
// Copy the message to the clipboard without delaying the window.open call
navigator.clipboard.writeText(message)
.then(() => {
showSuccessToast('Opening PR with conflict message pre-filled...');
})
.catch((err) => {
console.error('Failed to copy conflict message:', err);
});

Copilot uses AI. Check for mistakes.
});
}

// Add click handler to highlight the row when clicked
row.addEventListener('click', (e) => {
// Don't trigger row selection if clicking on the update button or links
Expand Down