summaryrefslogtreecommitdiff
path: root/packages/tweetdeck/src/components/ChatCard.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/tweetdeck/src/components/ChatCard.tsx')
-rw-r--r--packages/tweetdeck/src/components/ChatCard.tsx56
1 files changed, 56 insertions, 0 deletions
diff --git a/packages/tweetdeck/src/components/ChatCard.tsx b/packages/tweetdeck/src/components/ChatCard.tsx
new file mode 100644
index 0000000..d7d885c
--- /dev/null
+++ b/packages/tweetdeck/src/components/ChatCard.tsx
@@ -0,0 +1,56 @@
+import type { TwitterNotification } from "../lib/fetching/types";
+import { timeAgo } from "../lib/utils/time";
+
+interface ChatCardProps {
+ notification: TwitterNotification;
+ accent: string;
+}
+
+export function ChatCard({ notification, accent }: ChatCardProps) {
+ const firstUser = Object.values(notification.users)[0];
+ const timestamp = timeAgo(Number(notification.timestampMs));
+
+ return (
+ <article className="chat-card" style={{ borderColor: accent }}>
+ <div className="chat-avatar">
+ {firstUser?.profile_image_url_https ? (
+ <img src={firstUser.profile_image_url_https} alt={firstUser.name} loading="lazy" />
+ ) : (
+ <span>{firstUser?.name?.[0] ?? "?"}</span>
+ )}
+ </div>
+ <div className="chat-body">
+ <header>
+ <strong>{firstUser?.name ?? "Notification"}</strong>
+ {firstUser?.screen_name && <span className="muted">@{firstUser.screen_name}</span>}
+ <span className="muted dot" aria-hidden="true">
+ •
+ </span>
+ <span className="muted">{timestamp}</span>
+ </header>
+ <p>{highlight(notification.message.text)}</p>
+ </div>
+ </article>
+ );
+}
+
+function highlight(text: string) {
+ const parts = text.split(/([@#][A-Za-z0-9_]+)/g);
+ return parts.map((part, index) => {
+ if (part.startsWith("@")) {
+ return (
+ <span key={index} className="mention">
+ {part}
+ </span>
+ );
+ }
+ if (part.startsWith("#")) {
+ return (
+ <span key={index} className="hashtag">
+ {part}
+ </span>
+ );
+ }
+ return <span key={index}>{part}</span>;
+ });
+}