import { Color, Icon, List } from "@raycast/api"; import { NotificationActions } from "../../../NotificationActions"; import { Notification } from "../../../types"; import { GithubPullRequestPreview } from "../preview/GithubPullRequestPreview"; import { GithubPullRequestState, GithubPullRequestReviewDecision, GithubCheckConclusionState, GithubPullRequest, GithubCommitChecks, GithubCheckStatusState, GithubCheckSuite, } from "../types"; import { getGithubActorAccessory } from "../misc"; interface GithubPullRequestNotificationListItemProps { icon: string; notification: Notification; githubPullRequest: GithubPullRequest; } export function GithubPullRequestNotificationListItem({ icon, notification, githubPullRequest, }: GithubPullRequestNotificationListItemProps) { const subtitle = `${githubPullRequest.head_repository?.name_with_owner} #${githubPullRequest.number}`; const author = getGithubActorAccessory(githubPullRequest.author); const prChecks = getGithubPullRequestChecksAccessory(githubPullRequest.latest_commit); const review = getGithubPullRequestReviewAccessory(githubPullRequest.review_decision); const prStatus = getGithubPullRequestStateAccessory(githubPullRequest); const accessories: List.Item.Accessory[] = [ author, { date: new Date(githubPullRequest.updated_at), tooltip: `Updated at ${githubPullRequest.updated_at}`, }, ]; if (prStatus) { accessories.unshift(prStatus); } if (githubPullRequest.comments_count > 0) { accessories.unshift({ text: githubPullRequest.comments_count.toString(), icon: Icon.Bubble, tooltip: `${githubPullRequest.comments_count} comments`, }); } if (review) { accessories.unshift(review); } if (prChecks) { accessories.unshift(prChecks); } return ( } /> } /> ); } function getGithubPullRequestChecksAccessory(latestCommit: GithubCommitChecks): List.Item.Accessory | null { const progress = computePullRequestChecksProgress(latestCommit.check_suites); if (!progress) { return null; } switch (progress.status()) { case GithubCheckStatusState.Pending: return { icon: Icon.Pause, tooltip: "Pending" }; case GithubCheckStatusState.InProgress: return { icon: Icon.Pause, tooltip: "In progress" }; // TODO Spinner case GithubCheckStatusState.Completed: switch (progress.conclusion()) { case GithubCheckConclusionState.Success: return { icon: Icon.CheckCircle, tooltip: "Success" }; case GithubCheckConclusionState.Failure: return { icon: Icon.XMarkCircle, tooltip: "Failure" }; default: return { icon: Icon.QuestionMarkCircle, tooltip: "Neutral" }; } default: return { icon: Icon.QuestionMarkCircle, tooltip: "Neutral" }; } } class GithubChecksProgress { checksCount = 0; completedChecksCount = 0; failedChecksCount = 0; status(): GithubCheckStatusState { if (this.completedChecksCount === 0) { return GithubCheckStatusState.Pending; } if (this.completedChecksCount === this.checksCount) { return GithubCheckStatusState.Completed; } return GithubCheckStatusState.InProgress; } conclusion(): GithubCheckConclusionState { if (this.status() === GithubCheckStatusState.InProgress) { return GithubCheckConclusionState.Neutral; } if (this.failedChecksCount > 0) { return GithubCheckConclusionState.Failure; } return GithubCheckConclusionState.Success; } } function computePullRequestChecksProgress(checkSuites?: Array): GithubChecksProgress | null { if (checkSuites) { const progress = new GithubChecksProgress(); for (const checkSuite of checkSuites) { if (checkSuite.status !== GithubCheckStatusState.Queued) { for (const checkRun of checkSuite.check_runs) { progress.checksCount += 1; if (checkRun.status === GithubCheckStatusState.Completed) { progress.completedChecksCount += 1; if (checkRun.conclusion && checkRun.conclusion !== GithubCheckConclusionState.Success) { progress.failedChecksCount += 1; } } } } } if (progress.checksCount === 0) { return null; } return progress; } return null; } function getGithubPullRequestReviewAccessory( reviewDecision?: GithubPullRequestReviewDecision, ): List.Item.Accessory | null { switch (reviewDecision) { case GithubPullRequestReviewDecision.Approved: return { tag: { value: "Approved", color: Color.Green } }; case GithubPullRequestReviewDecision.ChangesRequested: return { tag: { value: "Changes requested", color: Color.Red } }; case GithubPullRequestReviewDecision.ReviewRequired: return { tag: { value: "Review required", color: Color.Orange } }; default: return null; } } function getGithubPullRequestStateAccessory(githubPullRequest: GithubPullRequest): List.Item.Accessory | null { switch (githubPullRequest.state) { case GithubPullRequestState.Open: if (githubPullRequest.is_draft) { return { icon: { source: "github-pullrequest-draft.svg", tintColor: Color.SecondaryText, }, }; } return { icon: { source: "github-pullrequest.svg", tintColor: Color.Green }, }; case GithubPullRequestState.Closed: return { icon: { source: "github-pullrequest-closed.svg", tintColor: Color.SecondaryText, }, }; case GithubPullRequestState.Merged: return { icon: { source: "github-pullrequest.svg", tintColor: Color.Magenta }, }; default: return null; } }