diff options
Diffstat (limited to 'packages/tweetdeck/src/components/ChatCard.tsx')
| -rw-r--r-- | packages/tweetdeck/src/components/ChatCard.tsx | 56 |
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>; + }); +} |
