aboutsummaryrefslogtreecommitdiff
path: root/apps/web/components/twitter/render-tweet.tsx
blob: 0e7f2c1e2a1a0258dc4501a5101806996b59be64 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import type { Tweet } from "react-tweet/api";
import {
	type TwitterComponents,
	TweetContainer,
	TweetInReplyTo,
	TweetBody,
	TweetMedia,
	TweetInfo,
	QuotedTweet,
	enrichTweet,
	EnrichedTweet,
} from "react-tweet";
import clsx from "clsx";
import s from "./tweet-header.module.css";
import { VerifiedBadge } from "./verified-badge";

type Props = {
	tweet: Tweet | { error: string };
	components?: TwitterComponents;
};

type AvatarImgProps = {
	src: string;
	alt: string;
	width: number;
	height: number;
};
const AvatarImg = (props: AvatarImgProps) => <img {...props} />;

const TweetHeader = ({
	tweet,
	components,
}: {
	tweet: EnrichedTweet;
	components?: TwitterComponents;
}) => {
	const Img = components?.AvatarImg ?? AvatarImg;
	const { user } = tweet;

	return (
		<div className={s.header}>
			<a
				href={tweet.url}
				className={s.avatar}
				target="_blank"
				rel="noopener noreferrer"
			>
				<div
					className={clsx(
						s.avatarOverflow,
						user.profile_image_shape === "Square" && s.avatarSquare,
					)}
				>
					<Img
						src={user.profile_image_url_https}
						alt={user.name}
						width={48}
						height={48}
					/>
				</div>
				<div className={s.avatarOverflow}>
					<div className={s.avatarShadow}></div>
				</div>
			</a>
			<div className={s.author}>
				<a
					href={tweet.url}
					className={s.authorLink}
					target="_blank"
					rel="noopener noreferrer"
				>
					<div className={s.authorLinkText}>
						<span title={user.name}>{user.name}</span>
					</div>
					<VerifiedBadge user={user} className={s.authorVerified} />
				</a>
				<div className={s.authorMeta}>
					<a
						href={tweet.url}
						className={s.username}
						target="_blank"
						rel="noopener noreferrer"
					>
						<span title={`@${user.screen_name}`}>@{user.screen_name}</span>
					</a>
					<div className={s.authorFollow}>
						<span className={s.separator}>·</span>
						<a
							href={user.follow_url}
							className={s.follow}
							target="_blank"
							rel="noopener noreferrer"
						>
							Follow
						</a>
					</div>
				</div>
			</div>
		</div>
	);
};

export const MyTweet = ({ tweet: t, components }: Props) => {
	if ("error" in t) {
		return <div>{t.error}</div>;
	}

	const tweet = enrichTweet(t);
	return (
		<TweetContainer className="bg-transparent !m-0 !p-0 !z-0">
			<TweetHeader tweet={tweet} components={components} />
			{tweet.in_reply_to_status_id_str && <TweetInReplyTo tweet={tweet} />}
			<TweetBody tweet={tweet} />
			{tweet.mediaDetails?.length ? (
				<TweetMedia tweet={tweet} components={components} />
			) : null}
			{tweet.quoted_tweet && <QuotedTweet tweet={tweet.quoted_tweet} />}
			<TweetInfo tweet={tweet} />
		</TweetContainer>
	);
};