Bound jump-to-latest comment loading

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-04-30 12:23:01 -05:00
1 parent 9bf7b1d964
commit fa54d33559
3 files changed
+14 -3

No files matched your search

+8 -2
View File
@@ -124,6 +124,7 @@ interface IssueChatMessageContext {
onStopRun?: (runId: string) => Promise<void>;
stopRunLabel?: string;
stoppingRunLabel?: string;
stopRunVariant?: "stop" | "pause";
onInterruptQueued?: (runId: string) => Promise<void>;
onCancelQueued?: (commentId: string) => void;
onImageClick?: (src: string) => void;
@@ -280,6 +281,7 @@ interface IssueChatThreadProps {
onStopRun?: (runId: string) => Promise<void>;
stopRunLabel?: string;
stoppingRunLabel?: string;
stopRunVariant?: "stop" | "pause";
imageUploadHandler?: (file: File) => Promise<string>;
onAttachImage?: (file: File) => Promise<IssueAttachment | void>;
draftKey?: string;
@@ -1347,6 +1349,7 @@ function IssueChatAssistantMessage({
onStopRun,
stopRunLabel = "Stop run",
stoppingRunLabel = "Stopping...",
stopRunVariant = "stop",
} = useContext(IssueChatCtx);
const custom = message.metadata.custom as Record<string, unknown>;
const anchorId = typeof custom.anchorId === "string" ? custom.anchorId : undefined;
@@ -1541,7 +1544,7 @@ function IssueChatAssistantMessage({
<DropdownMenuItem
disabled={isStoppingRun}
className={cn(
stopRunLabel.toLowerCase().includes("pause")
stopRunVariant === "pause"
? "text-amber-700 focus:text-amber-800 dark:text-amber-300 dark:focus:text-amber-200"
: "text-red-700 focus:text-red-800 dark:text-red-300 dark:focus:text-red-200",
)}
@@ -1549,7 +1552,7 @@ function IssueChatAssistantMessage({
void onStopRun(runId);
}}
>
{stopRunLabel.toLowerCase().includes("pause") ? (
{stopRunVariant === "pause" ? (
<PauseCircle className="mr-2 h-3.5 w-3.5" />
) : (
<Square className="mr-2 h-3.5 w-3.5 fill-current" />
@@ -3087,6 +3090,7 @@ export function IssueChatThread({
onStopRun,
stopRunLabel,
stoppingRunLabel,
stopRunVariant,
imageUploadHandler,
onAttachImage,
draftKey,
@@ -3528,6 +3532,7 @@ export function IssueChatThread({
onStopRun: stableOnStopRun,
stopRunLabel,
stoppingRunLabel,
stopRunVariant,
onInterruptQueued: stableOnInterruptQueued,
onCancelQueued: stableOnCancelQueued,
onImageClick: stableOnImageClick,
@@ -3547,6 +3552,7 @@ export function IssueChatThread({
stableOnStopRun,
stopRunLabel,
stoppingRunLabel,
stopRunVariant,
stableOnInterruptQueued,
stableOnCancelQueued,
stableOnImageClick,
+3 -1
View File
@@ -162,6 +162,7 @@ export async function loadRemainingIssueCommentPages<T extends { id: string }>(p
pages: ReadonlyArray<ReadonlyArray<T>> | undefined;
pageParams: ReadonlyArray<string | null> | undefined;
pageSize: number;
maxPages?: number;
fetchPage: (afterCommentId: string) => Promise<ReadonlyArray<T>>;
}): Promise<{ pages: T[][]; pageParams: Array<string | null> }> {
const pages = (params.pages ?? []).map((page) => [...page]);
@@ -176,8 +177,9 @@ export async function loadRemainingIssueCommentPages<T extends { id: string }>(p
if (params.pageSize <= 0) return { pages, pageParams };
let cursor = getNextPageCursor(pages[pages.length - 1], params.pageSize);
const maxPages = Math.max(0, params.maxPages ?? Number.POSITIVE_INFINITY);
const seenCursors = new Set<string>();
while (cursor && !seenCursors.has(cursor)) {
while (cursor && !seenCursors.has(cursor) && seenCursors.size < maxPages) {
seenCursors.add(cursor);
const nextPage = [...await params.fetchPage(cursor)];
pages.push(nextPage);
+3
View File
@@ -158,6 +158,7 @@ type IssueDetailComment = (IssueComment | OptimisticIssueComment) & {
const FEEDBACK_TERMS_URL = import.meta.env.VITE_FEEDBACK_TERMS_URL?.trim() || "https://paperclip.ing/tos";
const ISSUE_COMMENT_PAGE_SIZE = 50;
const ISSUE_COMMENT_AUTOLOAD_LIMIT = ISSUE_COMMENT_PAGE_SIZE * 3;
const JUMP_TO_LATEST_MAX_COMMENT_PAGES = 10;
const TREE_CONTROL_MODE_LABEL: Record<IssueTreeControlMode, string> = {
pause: "Pause subtree",
resume: "Resume subtree",
@@ -858,6 +859,7 @@ const IssueDetailChatTab = memo(function IssueDetailChatTab({
onStopRun={onPauseWorkRun}
stopRunLabel="Pause work"
stoppingRunLabel="Pausing..."
stopRunVariant="pause"
onAcceptInteraction={onAcceptInteraction}
onRejectInteraction={onRejectInteraction}
onSubmitInteractionAnswers={(interaction, answers) =>
@@ -2702,6 +2704,7 @@ export function IssueDetail() {
pages: refreshed.data?.pages,
pageParams: refreshed.data?.pageParams as Array<string | null> | undefined,
pageSize: ISSUE_COMMENT_PAGE_SIZE,
maxPages: JUMP_TO_LATEST_MAX_COMMENT_PAGES,
fetchPage: (afterCommentId) =>
issuesApi.listComments(issueId!, {
order: "desc",