Skip to content
Closed
Show file tree
Hide file tree
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
12 changes: 12 additions & 0 deletions packages/communication/src/__tests__/chat-messages.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 19 additions & 4 deletions packages/communication/src/chat-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ export type ThreadReplyRunningTasks = {
url: string;
};

const MAX_INLINE_THREAD_REPLY_PRS = 3;

export function buildThreadReplyFooterText({
taskUrl,
linkedPrs,
Expand All @@ -318,10 +320,23 @@ export function buildThreadReplyFooterText({
: `${runningTasks.count} tasks running`,
);
}
const prLinks = (linkedPrs ?? []).map((pr) =>
formatLink(`PR #${pr.prNumber}`, pr.prUrl),
);
if (prLinks.length > 0) items.push(prLinks.join(', '));
const prs = linkedPrs ?? [];
const prLinks = prs
.slice(0, MAX_INLINE_THREAD_REPLY_PRS)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The footer refresh path preserves PRs that have not yet been linked in the database by parsing every visible PR URL from the previous footer (mergeCarriedPullRequests). After this slice, a refresh can recover only the first three URLs; any fourth-or-later out-of-band PR is no longer in context.linkedPrs or the carried set, so the next refresh drops it and its N more PRs count. Preserve the omitted PR references somewhere refresh can rehydrate them, or avoid truncating the state-bearing footer representation.

.map((pr) => formatLink(`PR #${pr.prNumber}`, pr.prUrl));
if (prLinks.length > 0) {
const remainingPrCount = prs.length - prLinks.length;
items.push(
[
...prLinks,
...(remainingPrCount > 0
? [
`${remainingPrCount} more ${remainingPrCount === 1 ? 'PR' : 'PRs'}`,
]
: []),
].join(', '),
);
}

const taskNavigationUrl = new URL(taskUrl);
let webUrl = taskNavigationUrl;
Expand Down
12 changes: 12 additions & 0 deletions packages/slack/src/__tests__/thread-reply-footer-ops.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/slack/src/thread-reply-footer-ops.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const THREAD_REPLY_FOOTER_LOCK_TIMEOUT_MESSAGE =

function isSlackThreadReplyFooterText(text: string): boolean {
return (
/^Reply anytime(?: · (?:1 task|(?:[2-9]|\d{2,}) tasks) running)?(?: · <[^>]+\|PR #\d+>(?:, <[^>]+\|PR #\d+>)*)? · <[^>]+\|Open in Roomote>$/.test(
/^Reply anytime(?: · (?:1 task|(?:[2-9]|\d{2,}) tasks) running)?(?: · <[^>]+\|PR #\d+>(?:, <[^>]+\|PR #\d+>)*(?:, \d+ more PRs?)?)? · <[^>]+\|Open in Roomote>$/.test(
text,
) ||
/^_(?:Reply(?: with @-mention)? or use the <[^>]+\|web app>\.|Working on (?:<[^>]+\|PR(?:\s+#)?\d+>(?:, <[^>]+\|live preview>)?|a <[^>]+\|live preview>), reply(?: with @-mention)? or use the <[^>]+\|web app>\.)_$/.test(
Expand Down
Loading