diff --git a/apps/web/src/lib/composerContextRecords.test.ts b/apps/web/src/lib/composerContextRecords.test.ts index f612a302ac8c8..95a14d469c962 100644 --- a/apps/web/src/lib/composerContextRecords.test.ts +++ b/apps/web/src/lib/composerContextRecords.test.ts @@ -218,6 +218,14 @@ describe("composerContextRecords", () => { expect(image).toMatchObject({ attachmentId: "uploaded-image" }); }); + it("shortens a long annotation comment label without splitting an emoji", () => { + const record = previewAnnotationContextRecord({ + ...annotation, + comment: `${"a".repeat(46)}😀 and make the button bigger`, + }); + expect(record.label).toBe(`${"a".repeat(46)}…`); + }); + it("restores multiple edits on one target without parsing display strings", () => { const styleChanges = [ ...annotation.styleChanges, diff --git a/apps/web/src/lib/composerContextRecords.ts b/apps/web/src/lib/composerContextRecords.ts index c4f123f73dcc4..3f5c6c1da19a0 100644 --- a/apps/web/src/lib/composerContextRecords.ts +++ b/apps/web/src/lib/composerContextRecords.ts @@ -110,9 +110,12 @@ export function pullRequestContextKindLabel(comment: ReviewCommentPresentation): export function previewAnnotationContextLabel(annotation: PreviewAnnotationPayload): string { const comment = annotation.comment.trim().replace(/\s+/g, " "); if (comment) { - return comment.length > PREVIEW_LABEL_MAX_CHARS - ? `${comment.slice(0, PREVIEW_LABEL_MAX_CHARS - 1)}…` - : comment; + if (comment.length <= PREVIEW_LABEL_MAX_CHARS) return comment; + let end = PREVIEW_LABEL_MAX_CHARS - 1; + const previous = comment.charCodeAt(end - 1); + const next = comment.charCodeAt(end); + if (previous >= 0xd800 && previous <= 0xdbff && next >= 0xdc00 && next <= 0xdfff) end -= 1; + return `${comment.slice(0, end)}…`; } return annotation.pageTitle?.trim() || "Preview annotation"; }