1import type { PullRequestActor } from "@t3tools/contracts";
2import { Image } from "expo-image";
3import { ActivityIndicator, View } from "react-native";
4
5import { AppText as Text } from "../../components/AppText";
6import { cn } from "../../lib/cn";
7import { EmptyState } from "../../components/EmptyState";
8
9export function PullRequestReadStatus(props: {
10 readonly pending: boolean;
11 readonly error: string | null;
12}) {
13 return props.pending ? (
14 <ActivityIndicator className="my-12" colorClassName="accent-icon" />
15 ) : props.error ? (
16 <EmptyState title="Couldn't load this pull request" detail={props.error} variant="plain" />
17 ) : null;
18}
19
20export function PullRequestAvatar(props: {
21 readonly actor: PullRequestActor | null;
22 readonly size?: number;
23}) {
24 const size = props.size ?? 24;
25 return props.actor?.avatarUrl ? (
26 <Image
27 source={{ uri: props.actor.avatarUrl }}
28 recyclingKey={props.actor.avatarUrl}
29 accessibilityLabel={props.actor.login}
30 style={{ width: size, height: size, borderRadius: size / 2 }}
31 cachePolicy="memory-disk"
32 />
33 ) : (
34 <View
35 className="items-center justify-center rounded-full bg-grouped-card"
36 style={{ width: size, height: size }}
37 >
38 <Text className="font-t3-medium text-foreground-muted" style={{ fontSize: size * 0.45 }}>
39 {props.actor?.login.slice(0, 1).toUpperCase() ?? "?"}
40 </Text>
41 </View>
42 );
43}
44
45export function PullRequestDiffStats(props: {
46 readonly additions: number;
47 readonly deletions: number;
48 readonly compact?: boolean;
49}) {
50 const textSize = props.compact ? "text-2xs" : "text-xs";
51 return (
52 <View className="shrink-0 flex-row items-center gap-2">
53 {!props.compact || props.additions > 0 ? (
54 <Text className={cn(textSize, "font-t3-medium tabular-nums text-adaptive-emerald-600-400")}>
55 +{props.additions.toLocaleString()}
56 </Text>
57 ) : null}
58 {!props.compact || props.deletions > 0 ? (
59 <Text className={cn(textSize, "font-t3-medium tabular-nums text-danger-foreground")}>
60 −{props.deletions.toLocaleString()}
61 </Text>
62 ) : null}
63 </View>
64 );
65}