From 3c9fd2b1ecbbc53c9351efe2186e2e39ad822617 Mon Sep 17 00:00:00 2001 From: Scott Cooper Date: Fri, 31 Jul 2026 14:30:08 -0700 Subject: [PATCH] feat(issues): Show Seer avatar for created pull requests When the Seer PR creation activity is collapsed into the generic pull request reference, keep it as the activity actor so the timeline still shows who created the PR. Co-Authored-By: GPT-5 --- .../activityLineItem/activityFeedItem.ts | 1 + .../activityLineItem/index.tsx | 10 +++-- .../activitySection/index.spec.tsx | 1 + .../issueDetails/activitySection/index.tsx | 39 +++++++++++++------ 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/static/app/views/issueDetails/activitySection/activityLineItem/activityFeedItem.ts b/static/app/views/issueDetails/activitySection/activityLineItem/activityFeedItem.ts index 0190d526a928..3c537e5b8ead 100644 --- a/static/app/views/issueDetails/activitySection/activityLineItem/activityFeedItem.ts +++ b/static/app/views/issueDetails/activitySection/activityLineItem/activityFeedItem.ts @@ -29,6 +29,7 @@ export type ActivityFeedItem = | { activity: GroupActivity; type: 'activity'; + actorActivity?: GroupActivity; } | CollapsedSeerActivity; diff --git a/static/app/views/issueDetails/activitySection/activityLineItem/index.tsx b/static/app/views/issueDetails/activitySection/activityLineItem/index.tsx index 5e152566cc90..dc69b797430e 100644 --- a/static/app/views/issueDetails/activitySection/activityLineItem/index.tsx +++ b/static/app/views/issueDetails/activitySection/activityLineItem/index.tsx @@ -33,10 +33,12 @@ export function ActivityLine({item, group, timestampUnitStyle}: ActivityLineProp const timestamp = ( ); - const actorActivity = - item.type === GroupActivityType.SEER_ITERATION_COMPLETED - ? item.startedActivity - : activity; + let actorActivity = activity; + if (item.type === GroupActivityType.SEER_ITERATION_COMPLETED) { + actorActivity = item.startedActivity; + } else if (item.type === 'activity' && item.actorActivity) { + actorActivity = item.actorActivity; + } return ( diff --git a/static/app/views/issueDetails/activitySection/index.spec.tsx b/static/app/views/issueDetails/activitySection/index.spec.tsx index fb3293e9b550..f7425d8cabc2 100644 --- a/static/app/views/issueDetails/activitySection/index.spec.tsx +++ b/static/app/views/issueDetails/activitySection/index.spec.tsx @@ -1609,6 +1609,7 @@ describe('ActivitySection', () => { ); expect(await screen.findByText('Referenced in pull request')).toBeInTheDocument(); + expect(screen.getByRole('img', {name: 'Seer activity'})).toBeInTheDocument(); expect(screen.getAllByRole('link', {name: `#${pullRequest.id}`})).toHaveLength(1); }); diff --git a/static/app/views/issueDetails/activitySection/index.tsx b/static/app/views/issueDetails/activitySection/index.tsx index ec5566643666..8c9eb9932452 100644 --- a/static/app/views/issueDetails/activitySection/index.tsx +++ b/static/app/views/issueDetails/activitySection/index.tsx @@ -137,14 +137,24 @@ function isDuplicatePullRequestActivity( } } -function removeAdjacentDuplicatePullRequestActivities( - activities: GroupActivity[] -): GroupActivity[] { - return activities.filter( - (activity, index) => - !isDuplicatePullRequestActivity(activity, activities[index - 1]) && - !isDuplicatePullRequestActivity(activity, activities[index + 1]) - ); +function removeAdjacentDuplicatePullRequestActivities(activities: GroupActivity[]): { + activities: GroupActivity[]; + actorActivityById: Map; +} { + const actorActivityById = new Map(); + const filteredActivities = activities.filter((activity, index) => { + const duplicateActivity = [activities[index - 1], activities[index + 1]].find( + adjacentActivity => isDuplicatePullRequestActivity(activity, adjacentActivity) + ); + + if (activity.type === GroupActivityType.SEER_PR_CREATED && duplicateActivity) { + actorActivityById.set(duplicateActivity.id, activity); + } + + return !duplicateActivity; + }); + + return {activities: filteredActivities, actorActivityById}; } export function ActivitySection({ @@ -203,10 +213,15 @@ export function ActivitySection({ ? group.activity : group.activity.filter(item => !SEER_ACTIVITY_TYPES.has(item.type)); - const filteredActivities = removeAdjacentDuplicatePullRequestActivities( - visibleActivities - ).filter(item => !filterComments || item.type === GroupActivityType.NOTE); - const displayedActivities = collapseSeerActivityPairs(filteredActivities); + const {activities: deduplicatedActivities, actorActivityById} = + removeAdjacentDuplicatePullRequestActivities(visibleActivities); + const filteredActivities = deduplicatedActivities.filter( + item => !filterComments || item.type === GroupActivityType.NOTE + ); + const displayedActivities = collapseSeerActivityPairs(filteredActivities).map(item => { + const actorActivity = actorActivityById.get(item.activity.id); + return item.type === 'activity' && actorActivity ? {...item, actorActivity} : item; + }); const inputVariant = variant === 'sidebar' ? 'compact' : 'full'; const timestampUnitStyle = variant === 'sidebar' ? 'short' : undefined;