import { ErrorPanel, PanelNote } from '@app/components' import { listPullCommits, type PullRef } from '@app/domains/pulls/model' import { useT } from '@app/i18n' import { fmtRelative, fmtTime, useAsync } from '@app/lib' import { useState } from 'react' import { Copyable } from './parts' export interface CommitsTabProps { refObj: PullRef onOpenCommit: (sha: string) => void } /** 提交页签:head…base 区间内的提交(后端给 MergeCommitDto)。 */ export function CommitsTab({ refObj, onOpenCommit }: CommitsTabProps) { const { t } = useT() const [tick, setTick] = useState(0) const commits = useAsync(() => listPullCommits(refObj), [refObj.space, refObj.repo, refObj.pull, tick]) const failure = commits.error as { code?: number; message?: string } | undefined if (commits.loading && !commits.data) return if (failure) return ( setTick((tick) => tick + 1)} /> ) const rows = commits.data ?? [] if (!rows.length) return return ( {rows.map((commit) => ( onOpenCommit(commit.sha)} className="block max-w-full truncate text-left text-[13.5px] font-medium leading-6 hover:underline" title={commit.subject} > {commit.subject || t('pull.commits.noSubject')} {commit.author_name || t('pull.commits.unknownAuthor')} <{commit.author_email}> ·{' '} {fmtRelative(commit.author_at)} {commit.parents.length > 1 ? ( {t('pull.commits.mergeCommit', { count: commit.parents.length })} ) : null} onOpenCommit(commit.sha)} className="rounded-md border border-shell-hairline px-2 py-1 text-[11.5px] text-shell-ink-muted transition-colors hover:text-shell-ink" > {t('pull.commits.view')} ))} ) }
{commit.author_name || t('pull.commits.unknownAuthor')} <{commit.author_email}> ·{' '} {fmtRelative(commit.author_at)}
{t('pull.commits.mergeCommit', { count: commit.parents.length })}