@select-org/post-components 2.1.3 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/PostCard.tsx","../src/utils/cn.ts","../src/components/PostHeader.tsx","../src/components/AppIcon.tsx","../src/utils/postTypeHint.ts","../src/utils/relativeTime.ts","../src/components/AutoLink.tsx","../src/components/PostBody.tsx","../src/components/PostEmail.tsx","../src/components/MediaView.tsx","../src/components/AsyncImage.tsx","../src/components/Loader.tsx","../src/components/PostPollLayout/pollUtils.ts","../src/components/PostPollLayout/PostPollIResultView.tsx","../src/components/PostPollLayout/PostPollIButtonView.tsx","../src/components/PostPollLayout/PostPollLayoutOne.tsx","../src/components/PostPollLayout/PostPollLayoutGrid.tsx","../src/components/PostPollView.tsx","../src/components/PostTextItem.tsx","../src/components/PostLinkItem.tsx","../src/components/PostEmbedView.tsx","../src/components/PostMediaLayout/MediaUploadStatusOverlay.tsx","../src/components/PostMediaLayout/PostMediaLayoutCore.tsx","../src/components/PostItemsView.tsx","../src/components/PostSectionsView.tsx","../src/utils/contentTypeConstants.ts","../src/components/PostSectionSourceInfoView.tsx","../src/components/PostFooter.tsx","../src/components/PostMediaLayout/uploadStats.ts","../src/components/PostUploadStrip.tsx","../src/components/EraseConfirmModal.tsx","../src/components/PostSectionsSummaryView.tsx","../src/modals/ReactionModal.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react'\nimport { cn } from '../utils/cn'\nimport { resolvePostContent } from '../resolver'\nimport PostHeader from './PostHeader'\nimport PostBody from './PostBody'\nimport PostItemsView from './PostItemsView'\nimport PostSectionsView from './PostSectionsView'\nimport PostFooter from './PostFooter'\nimport PostUploadStrip from './PostUploadStrip'\nimport EraseConfirmModal from './EraseConfirmModal'\nimport type { ItemData, LinkItemMetaData, MediaUploadStatus, MentionData, PollItemData, PollResult, SectionItem } from '../types'\nimport type { TipTapDocument } from '../types/tiptap'\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface PostCardProps {\n // Core post data\n post: {\n context_id: string\n body?: string\n htmlBody?: string\n jsonBody?: TipTapDocument | null\n textBody?: string\n items?: ItemData[] | LinkItemMetaData[] | PollItemData[]\n mentionData?: MentionData[]\n sections?: SectionItem[]\n poll_result?: PollResult\n postedAt: string\n postType: string\n is_pending?: boolean\n isFeatured?: boolean\n }\n\n // Author / group\n author: { id: string; name: string; avatar: string; avatarPlaceholder?: string }\n authorHref: string\n group?: { name: string; avatar?: string }\n groupHref?: string\n\n // Navigation\n postHref?: string\n linkComponent?: React.ComponentType<{ href: string; children: React.ReactNode; className?: string }>\n imageComponent?: React.ComponentType<{ src: string; alt: string; fill?: boolean; placeholder?: 'blur' | 'empty'; blurDataURL?: string; priority?: boolean; className?: string }>\n\n // Permissions\n /** Author's role in the group — drives the owner crown / admin shield badge. */\n isAdmin?: boolean\n /** Author's role in the group — drives the owner crown / admin shield badge. */\n isOwner?: boolean\n /**\n * Whether the *viewer* is the post's author. Lets the author preview their own\n * poll results before voting. Distinct from `isOwner` (which is the author's\n * group role, for the badge) — pass it explicitly. When omitted, the author\n * preview is simply off (the author sees results after voting, like anyone).\n */\n isPostOwner?: boolean\n isPostPreview?: boolean\n isPrivate?: boolean\n membersCount?: number\n\n // Cross-post / i18n\n crossPostGroup?: { name: string; href?: string }\n locale?: string\n translate?: (key: string, params?: { count?: number }) => string\n\n // Actions\n onPostPress?: () => void\n onErasePress?: () => void\n onCancelPost?: () => void\n onVotePress?: (item: ItemData) => void\n onCardPress?: () => void\n renderActionsMenu?: () => React.ReactNode\n renderReactionTrigger?: (props: { onOpen: () => void }) => React.ReactNode\n renderReactionModal?: (props: { isOpen: boolean; onClose: () => void; onSend: (emoji: string) => void }) => React.ReactNode\n\n // Content callbacks\n onNavigate?: (href: string, isInternal: boolean) => void\n supportDeepviewDomain?: string | string[]\n\n // Labels\n labels?: {\n cancelPost?: string\n sending?: string\n uploadingRemaining?: string\n uploadingDone?: string\n }\n\n // Display\n mode?: 'feed' | 'detail' | 'inbox' | 'draft'\n commentCount?: number\n unreadCommentCount?: number\n isSnoozed?: boolean\n onSnoozeToggle?: () => void\n mediaItemStatuses?: Record<string, MediaUploadStatus>\n showFooterLink?: boolean\n footerLinkLabel?: string\n footerLinkHref?: string\n className?: string\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst PostCard: React.FC<PostCardProps> = ({\n post,\n author,\n authorHref,\n group,\n groupHref,\n postHref,\n linkComponent,\n imageComponent,\n isAdmin,\n isOwner,\n isPostOwner,\n isPostPreview,\n isPrivate,\n membersCount,\n crossPostGroup,\n locale,\n translate,\n onPostPress,\n onErasePress,\n onCancelPost,\n onVotePress,\n onCardPress,\n renderActionsMenu,\n renderReactionTrigger,\n renderReactionModal,\n onNavigate,\n supportDeepviewDomain,\n labels,\n mode = 'feed',\n commentCount = 0,\n unreadCommentCount = 0,\n isSnoozed = false,\n onSnoozeToggle,\n mediaItemStatuses,\n showFooterLink = false,\n footerLinkLabel,\n footerLinkHref,\n className,\n}) => {\n const [eraseModalOpen, setEraseModalOpen] = useState(false)\n\n const isPending = !!post.is_pending\n const isPostDetail = mode === 'detail'\n const sendingLabel = labels?.sending ?? 'Sending...'\n\n // Build a PostDataMetaData-compatible shape from the flat post prop\n const contextData = useMemo(\n () => ({\n body: post.body ?? '',\n htmlBody: post.htmlBody,\n jsonBody: post.jsonBody,\n textBody: post.textBody,\n items: post.items,\n mentionData: post.mentionData,\n sections: post.sections,\n }),\n [post.body, post.htmlBody, post.jsonBody, post.textBody, post.items, post.mentionData, post.sections]\n )\n\n const isEmailPost = Boolean(post.htmlBody && !post.jsonBody)\n\n const resolvedContent = useMemo(\n () =>\n resolvePostContent(contextData, {\n postType: post.postType,\n pollResult: post.poll_result ?? null,\n postSpecialType: post.isFeatured ? 1 : 0,\n mode: isPostDetail ? 'detail' : (mode as 'feed' | 'inbox' | 'draft'),\n isEmailPost,\n }),\n [contextData, post.postType, post.poll_result, post.isFeatured, isPostDetail, mode, isEmailPost]\n )\n\n const handleErasePress = () => {\n setEraseModalOpen(true)\n }\n\n const handleEraseConfirm = () => {\n setEraseModalOpen(false)\n onErasePress?.()\n }\n\n const handleEraseCancel = () => {\n setEraseModalOpen(false)\n }\n\n const handleCardClick = (e: React.MouseEvent<HTMLElement>) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n if (isPending) return\n onPostPress?.()\n }\n\n const handleCardKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n e.stopPropagation()\n if (isPending) return\n onPostPress?.()\n }\n }\n\n return (\n <article\n className={cn(\n 'w-full flex flex-col box-border bg-background',\n !isPostDetail &&\n 'cursor-pointer sm:border border-border rounded-xl sm:rounded-2xl overflow-hidden shadow-sm hover:shadow-md transition-shadow duration-300 relative mt-6',\n isPostDetail && 'cursor-auto rounded-t-2xl w-full',\n post.isFeatured && !isPostDetail && 'bg-highlight-surface border-highlight-border sm:border-t-4',\n isPending && 'cursor-default',\n className\n )}\n onClick={!isPostDetail && onPostPress ? handleCardClick : undefined}\n onKeyDown={!isPostDetail && !isPending && onPostPress ? handleCardKeyDown : undefined}\n tabIndex={!isPostDetail && !isPending && onPostPress ? 0 : undefined}\n role={!isPostDetail && !isPending && onPostPress ? 'button' : undefined}\n aria-label={!isPostDetail && !isPending && onPostPress ? 'View post details' : undefined}\n >\n {/* Screen-reader-only link for keyboard / assistive tech */}\n {!isPostDetail && !isPending && postHref && linkComponent && (\n React.createElement(linkComponent, {\n href: postHref,\n className: 'sr-only',\n children: 'View post details',\n })\n )}\n\n {!isPostDetail && !isPending && postHref && !linkComponent && (\n <a href={postHref} className=\"sr-only\" onClick={(e) => e.stopPropagation()}>\n View post details\n </a>\n )}\n\n {/* Pending loading bar */}\n {isPending && (\n <div className=\"absolute top-0 left-0 w-full z-10\">\n <div\n className=\"h-1 w-full overflow-hidden rounded bg-muted\"\n aria-label={sendingLabel}\n data-testid=\"post-loader\"\n >\n <div className=\"h-full animate-pulse bg-action-primary\" />\n </div>\n </div>\n )}\n\n {/* Erase confirm modal */}\n {!isPending && eraseModalOpen && (\n <EraseConfirmModal\n isOpen={eraseModalOpen}\n itemType=\"Post\"\n onYesPress={handleEraseConfirm}\n onNoPress={handleEraseCancel}\n handleClose={handleEraseCancel}\n />\n )}\n\n {/* Main content — dimmed while pending */}\n <div className={cn(isPending && 'opacity-50')}>\n <PostHeader\n author={author}\n authorHref={authorHref}\n group={group}\n groupHref={groupHref}\n postedAt={post.postedAt}\n postType={post.postType}\n isFeatured={post.isFeatured}\n isPostPreview={isPostPreview}\n isPostDetail={isPostDetail}\n isAdmin={isAdmin}\n isOwner={isOwner}\n isPrivate={isPrivate}\n membersCount={membersCount}\n crossPostGroup={crossPostGroup}\n locale={locale}\n translate={translate}\n onErasePress={onErasePress ? handleErasePress : undefined}\n onCancelPost={onCancelPost}\n renderActionsMenu={renderActionsMenu}\n linkComponent={linkComponent}\n imageComponent={imageComponent}\n labels={labels}\n />\n\n <PostBody\n textContent={resolvedContent.textContent}\n showFull={isPostDetail}\n isPostDetail={isPostDetail}\n isRichContent={resolvedContent.isRichContent}\n isEmailPost={isEmailPost}\n hideEmailDescription={\n isEmailPost &&\n !isPostDetail &&\n resolvedContent.primaryContent?.type === 'media'\n }\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n\n {resolvedContent.sections && (\n <PostSectionsView\n sections={resolvedContent.sections.sections}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress ?? (() => {})}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n imageComponent={imageComponent}\n />\n )}\n\n <PostItemsView\n primaryContent={resolvedContent.primaryContent}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress ?? (() => {})}\n onVotePress={onVotePress ?? (() => {})}\n isPostOwner={isPostOwner}\n parentId={post.context_id}\n isCommentScope={false}\n imageComponent={imageComponent}\n mediaItemStatuses={mediaItemStatuses}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n\n {/* Per-item upload progress strip */}\n <PostUploadStrip\n statuses={mediaItemStatuses}\n labels={{\n uploadingRemaining: labels?.uploadingRemaining,\n uploadingDone: labels?.uploadingDone,\n }}\n />\n </div>\n\n {/* Footer — pointer events disabled while pending */}\n <div className={cn(isPending && 'opacity-50 pointer-events-none')}>\n <PostFooter\n // On the post-detail page the comment icon would link to the page\n // you're already on — suppress it by withholding the href there.\n postHref={isPostDetail ? undefined : postHref}\n commentCount={commentCount}\n unreadCommentCount={unreadCommentCount}\n isSnoozed={isSnoozed}\n onSnoozeToggle={onSnoozeToggle}\n showFooterLink={showFooterLink}\n footerLinkLabel={footerLinkLabel}\n footerLinkHref={footerLinkHref}\n linkComponent={linkComponent}\n renderReactionTrigger={renderReactionTrigger}\n renderReactionModal={renderReactionModal}\n />\n </div>\n </article>\n )\n}\n\nexport default PostCard\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import React from 'react'\nimport {\n Avatar,\n AvatarImage,\n AvatarFallback,\n AvatarBadge,\n} from '@select-org/ui'\nimport AppIcon from './AppIcon'\nimport { getPostTypeHint, POST_TYPE_HINT_DEFAULTS } from '../utils/postTypeHint'\nimport { formatRelativeTime } from '../utils/relativeTime'\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface PostHeaderProps {\n author: {\n id: string\n name: string\n avatar: string\n avatarPlaceholder?: string\n }\n authorHref: string\n group?: { name: string; avatar?: string }\n groupHref?: string\n postedAt: string // ISO timestamp\n postType: string\n isPrivate?: boolean\n membersCount?: number\n crossPostGroup?: { name: string; href?: string }\n locale?: string\n translate?: (key: string, params?: { count?: number }) => string\n isFeatured?: boolean\n isPostPreview?: boolean // true for draft / ToUpload posts — render spans not links\n isPostDetail?: boolean // on the detail page the author name is the document's <h2>\n isAdmin?: boolean\n isOwner?: boolean\n onErasePress?: () => void\n onCancelPost?: () => void\n renderActionsMenu?: () => React.ReactNode\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n imageComponent?: React.ComponentType<{\n src: string\n alt: string\n fill?: boolean\n placeholder?: 'blur' | 'empty'\n blurDataURL?: string\n priority?: boolean\n className?: string\n }>\n labels?: {\n cancelPost?: string\n }\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst PostHeader: React.FC<PostHeaderProps> = ({\n author,\n authorHref,\n group,\n groupHref,\n postedAt,\n postType,\n isPrivate = false,\n membersCount,\n crossPostGroup,\n locale,\n translate,\n isFeatured = false,\n isPostPreview = false,\n isPostDetail = false,\n isAdmin = false,\n isOwner = false,\n onErasePress,\n onCancelPost,\n renderActionsMenu,\n linkComponent: LinkComponent,\n imageComponent,\n labels,\n}) => {\n const cancelLabel = labels?.cancelPost ?? 'Cancel'\n\n // Humanized post-type hint (translate seam + English defaults)\n const { key: hintKey, params: hintParams } = getPostTypeHint(postType, {\n isInGroup: !!group,\n isOwner,\n isPrivate,\n membersCount,\n })\n const hintText =\n translate?.(hintKey, hintParams) ??\n POST_TYPE_HINT_DEFAULTS[hintKey]?.(hintParams) ??\n hintKey\n\n // Resolve the badge variant — owner takes priority over admin\n const badgeVariant: 'owner' | 'admin' | undefined = isOwner\n ? 'owner'\n : isAdmin\n ? 'admin'\n : undefined\n\n // Author name — span (preview) or link\n const authorNameNode = isPostPreview ? (\n <span className=\"flex text-base font-semibold leading-[100%] text-foreground\">\n {author.name}\n </span>\n ) : LinkComponent ? (\n <LinkComponent\n href={authorHref}\n className=\"flex text-base font-semibold leading-[100%] text-foreground hover:opacity-70 bg-transparent border-none p-0 cursor-pointer no-underline\"\n >\n {author.name}\n </LinkComponent>\n ) : (\n <a\n href={authorHref}\n onClick={(e) => e.stopPropagation()}\n className=\"flex text-base font-semibold leading-[100%] text-foreground hover:opacity-70 bg-transparent border-none p-0 cursor-pointer no-underline\"\n aria-label={`View ${author.name}'s profile`}\n >\n {author.name}\n </a>\n )\n\n // Group link node\n const groupLinkNode =\n group && groupHref ? (\n isPostPreview ? (\n <span className=\"text-action-primary font-medium\">#{group.name}</span>\n ) : LinkComponent ? (\n <LinkComponent\n href={groupHref}\n className=\"text-action-primary font-medium no-underline hover:underline cursor-pointer bg-transparent border-none p-0\"\n >\n #{group.name}\n </LinkComponent>\n ) : (\n <a\n href={groupHref}\n onClick={(e) => e.stopPropagation()}\n className=\"text-action-primary font-medium no-underline hover:underline cursor-pointer bg-transparent border-none p-0\"\n title={group.name}\n aria-label={`View group ${group.name}`}\n >\n #{group.name}\n </a>\n )\n ) : null\n\n return (\n <section className=\"not-prose relative flex flex-col justify-start p-4 pb-3\">\n <section className=\"flex items-center gap-3\">\n {/* Author avatar */}\n <Avatar\n size=\"md\"\n disabled={isPostPreview}\n className=\"shrink-0 ring-1 ring-border-subtle\"\n >\n <AvatarImage\n src={author.avatar}\n alt={`${author.name}'s profile picture`}\n placeholder={author.avatarPlaceholder}\n imageComponent={imageComponent}\n />\n <AvatarFallback name={author.name} />\n {badgeVariant && <AvatarBadge variant={badgeVariant} />}\n </Avatar>\n\n {/* Meta */}\n <section className=\"flex flex-1 flex-col justify-center min-w-0\">\n {/* Top row: name + featured star + timestamp */}\n <section className=\"flex items-baseline justify-between gap-2\">\n <div className=\"flex items-center gap-1.5 min-w-0\">\n {/* On the detail page the post is the page's main content, so the\n author/post line is the document <h2> (sits under the page <h1>).\n In list contexts (feed/inbox) it's a plain <div> to avoid\n polluting the heading outline with one heading per card. */}\n {isPostDetail ? (\n <h2 className=\"font-semibold text-foreground truncate\">\n {authorNameNode}\n </h2>\n ) : (\n <div className=\"font-semibold text-foreground truncate\">\n {authorNameNode}\n </div>\n )}\n\n {isFeatured && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={14}\n height={14}\n className=\"text-highlight fill-highlight shrink-0\"\n aria-label=\"Featured post\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n )}\n\n {postedAt && (\n <>\n <span className=\"text-muted-foreground font-bold shrink-0\">\n &middot;\n </span>\n <time\n title={postedAt}\n className=\"text-xs text-muted-foreground whitespace-nowrap shrink-0\"\n dateTime={postedAt}\n >\n {formatRelativeTime(postedAt, locale ?? 'en')}\n </time>\n </>\n )}\n </div>\n </section>\n\n {/* Bottom row: post type hint + optional group link + cross-post via */}\n <div className=\"text-xs text-muted-foreground truncate mt-0.5\">\n <span>{hintText}</span>\n {groupLinkNode && (\n <>\n <span className=\"mx-1\"></span>\n {groupLinkNode}\n </>\n )}\n {crossPostGroup && (\n <>\n <span className=\"mx-1\">via</span>\n {LinkComponent && crossPostGroup.href ? (\n <LinkComponent\n href={crossPostGroup.href}\n className=\"text-action-primary font-medium hover:underline no-underline\"\n >\n #{crossPostGroup.name}\n </LinkComponent>\n ) : crossPostGroup.href ? (\n <a\n href={crossPostGroup.href}\n onClick={(e) => e.stopPropagation()}\n className=\"text-action-primary font-medium hover:underline no-underline\"\n >\n #{crossPostGroup.name}\n </a>\n ) : (\n <span className=\"text-action-primary font-medium\">\n #{crossPostGroup.name}\n </span>\n )}\n </>\n )}\n </div>\n </section>\n </section>\n\n {/* Top-right slot: actions menu OR cancel button */}\n {isPostPreview ? (\n onCancelPost && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onCancelPost()\n }}\n aria-label={cancelLabel}\n data-testid=\"cancel-pending-post\"\n className=\"absolute right-4 top-4 leading-none rounded-full p-1.5 transition-colors hover:bg-feedback-danger/10 hover:text-feedback-danger\"\n >\n <AppIcon name=\"cancel\" width={16} height={16} strokeWidth={1.75} />\n </button>\n )\n ) : renderActionsMenu ? (\n <div className=\"absolute right-2 top-2\">{renderActionsMenu()}</div>\n ) : onErasePress ? (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onErasePress()\n }}\n aria-label=\"Delete post\"\n className=\"absolute right-4 top-4 leading-none rounded-full p-1.5 transition-colors hover:bg-feedback-danger/10 hover:text-feedback-danger\"\n >\n <AppIcon name=\"chatErase\" width={16} height={16} strokeWidth={1.75} />\n </button>\n ) : null}\n </section>\n )\n}\n\nexport default PostHeader\n","import {\n AlarmClock,\n Check,\n CheckCircle2,\n CirclePlay,\n ExternalLink,\n LoaderCircle,\n MessageCircleMore,\n Smile,\n ThumbsDown,\n ThumbsUp,\n Trash2,\n TriangleAlert,\n Video,\n X,\n} from 'lucide-react'\nimport type { LucideProps } from 'lucide-react'\n\n// AppIcon subset used by post-components\nconst ICON_MAP = {\n video: Video,\n circlePlay: CirclePlay,\n cancel: X,\n externalLink: ExternalLink,\n sendEmoji: Smile,\n alarmClock: AlarmClock,\n messageCircleMore: MessageCircleMore,\n chatErase: Trash2,\n checkCircle2: CheckCircle2,\n thumbUp: ThumbsUp,\n thumbDown: ThumbsDown,\n check: Check,\n loader: LoaderCircle,\n triangleAlert: TriangleAlert,\n}\n\nexport type AppIconName = keyof typeof ICON_MAP\n\ninterface AppIconProps extends LucideProps {\n name: AppIconName\n}\n\nexport default function AppIcon({ name, ...props }: AppIconProps) {\n const Icon = ICON_MAP[name]\n if (!Icon) return null\n return <Icon {...props} />\n}\n","// Framework-agnostic humanized post-type hint.\n//\n// Ported from the web client's `toPostTypeHint`\n// (src/utils/PostUtils.ts). Returns the SAME i18n keys + an optional\n// `params.count` for plural cases, so a consumer's `translate(key, params)`\n// resolves identically. No React, no i18n lib — pure logic + English defaults.\n//\n// Machine post-type strings (from the web client Constants):\n// new:post:image -> NEW_POST_IMAGE\n// new:post:media -> NEW_POST_MEDIA\n// new:post:link -> NEW_POST_LINK\n// new:post:poll -> NEW_POST_POLL\n// new:post:text -> NEW_POST_MESSAGE\n// new:post:thread -> NEW_POST_THREAD\n// mediaItemToUpload -> MEDIA_ITEM_TO_UPLOAD (treated as media)\n\nexport interface PostTypeHintContext {\n isInGroup?: boolean\n isOwner?: boolean\n isPrivate?: boolean\n membersCount?: number\n /** Mirrors the web client's `isMetaDesc` branch (SEO/meta-description copy). */\n isMetaDesc?: boolean\n}\n\nexport interface PostTypeHint {\n key: string\n params?: { count?: number }\n}\n\nconst MEDIA_TYPES = new Set([\n 'new:post:media',\n 'new:post:image',\n 'mediaItemToUpload',\n])\n\nexport function getPostTypeHint(\n postType: string,\n ctx: PostTypeHintContext = {}\n): PostTypeHint {\n const {\n isInGroup = false,\n isOwner = false,\n isPrivate = false,\n membersCount = 0,\n isMetaDesc = false,\n } = ctx\n\n const isMedia = MEDIA_TYPES.has(postType)\n\n if (isInGroup) {\n if (isMetaDesc) {\n // SEO / meta-description copy\n if (isMedia)\n return { key: 'post_detail_meta_description_type_image_post' }\n switch (postType) {\n case 'new:post:link':\n return { key: 'post_detail_meta_description_type_link_post' }\n case 'new:post:poll':\n return { key: 'post_detail_meta_description_type_poll_post' }\n case 'new:post:thread':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_thread_post',\n }\n case 'new:post:text':\n default:\n return { key: 'post_detail_meta_description_type_message_post' }\n }\n }\n // who sent to a group\n if (isMedia)\n return { key: 'post_detail_one_liner_receive_and_send_group_image_post' }\n switch (postType) {\n case 'new:post:link':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_link_post',\n }\n case 'new:post:poll':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_poll_post',\n }\n case 'new:post:thread':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_thread_post',\n }\n case 'new:post:text':\n default:\n return {\n key: 'post_detail_one_liner_receive_and_send_group_message_post',\n }\n }\n }\n\n if (isOwner) {\n // me sent to others\n return membersCount > 1\n ? sentPlural(postType, membersCount)\n : sentSingular(postType)\n }\n\n if (isPrivate) {\n // who sent to me with 1:1\n if (isMedia)\n return { key: 'post_detail_one_liner_receive_private_image_post' }\n switch (postType) {\n case 'new:post:link':\n return { key: 'post_detail_one_liner_receive_private_link_post' }\n case 'new:post:poll':\n return { key: 'post_detail_one_liner_receive_private_poll_post' }\n case 'new:post:thread':\n case 'new:post:text':\n default:\n return { key: 'post_detail_one_liner_receive_message_post' }\n }\n }\n\n // who sent to me with 1:M\n return membersCount > 1\n ? sentPlural(postType, membersCount)\n : sentSingular(postType)\n}\n\nfunction sentPlural(postType: string, count: number): PostTypeHint {\n const params = { count }\n if (MEDIA_TYPES.has(postType))\n return { key: 'post_detail_one_liner_send_private_image_post_plural', params }\n switch (postType) {\n case 'new:post:link':\n return {\n key: 'post_detail_one_liner_send_private_link_post_plural',\n params,\n }\n case 'new:post:poll':\n return {\n key: 'post_detail_one_liner_send_private_link_poll_plural',\n params,\n }\n case 'new:post:thread':\n case 'new:post:text':\n default:\n return { key: 'post_detail_one_liner_send_message_post_plural', params }\n }\n}\n\nfunction sentSingular(postType: string): PostTypeHint {\n if (MEDIA_TYPES.has(postType))\n return { key: 'post_detail_one_liner_send_private_image_post_singular' }\n switch (postType) {\n case 'new:post:link':\n return { key: 'post_detail_one_liner_send_private_link_post_singular' }\n case 'new:post:poll':\n return { key: 'post_detail_one_liner_send_private_link_poll_singular' }\n case 'new:post:thread':\n case 'new:post:text':\n default:\n return { key: 'post_detail_one_liner_send_message_post_singular' }\n }\n}\n\n// English fallback strings — ONE per key getPostTypeHint can return.\n// Every branch above is covered here.\nexport const POST_TYPE_HINT_DEFAULTS: Record<\n string,\n (p?: { count?: number }) => string\n> = {\n // in-group (one-liner)\n post_detail_one_liner_receive_and_send_group_image_post: () =>\n 'shared a media post in group',\n post_detail_one_liner_receive_and_send_group_link_post: () =>\n 'shared a link post in group',\n post_detail_one_liner_receive_and_send_group_poll_post: () =>\n 'shared a poll in group',\n post_detail_one_liner_receive_and_send_group_thread_post: () =>\n 'shared a thread in group',\n post_detail_one_liner_receive_and_send_group_message_post: () =>\n 'shared a post in group',\n\n // in-group (meta description)\n post_detail_meta_description_type_image_post: () => 'A media post',\n post_detail_meta_description_type_link_post: () => 'A link post',\n post_detail_meta_description_type_poll_post: () => 'A poll',\n post_detail_meta_description_type_message_post: () => 'A post',\n\n // owner / 1:M sent — plural\n post_detail_one_liner_send_private_image_post_plural: (p) =>\n `sent a media post to ${p?.count ?? 0} people`,\n post_detail_one_liner_send_private_link_post_plural: (p) =>\n `sent a link post to ${p?.count ?? 0} people`,\n post_detail_one_liner_send_private_link_poll_plural: (p) =>\n `sent a poll to ${p?.count ?? 0} people`,\n post_detail_one_liner_send_message_post_plural: (p) =>\n `sent a post to ${p?.count ?? 0} people`,\n\n // owner / 1:M sent — singular\n post_detail_one_liner_send_private_image_post_singular: () =>\n 'sent a media post',\n post_detail_one_liner_send_private_link_post_singular: () =>\n 'sent a link post',\n post_detail_one_liner_send_private_link_poll_singular: () => 'sent a poll',\n post_detail_one_liner_send_message_post_singular: () => 'sent a post',\n\n // private 1:1 received\n post_detail_one_liner_receive_private_image_post: () =>\n 'sent you a media post',\n post_detail_one_liner_receive_private_link_post: () => 'sent you a link post',\n post_detail_one_liner_receive_private_poll_post: () => 'sent you a poll',\n post_detail_one_liner_receive_message_post: () => 'sent you a post',\n}\n","const UNITS: [Intl.RelativeTimeFormatUnit, number][] = [\n ['year', 31_536_000],\n ['month', 2_592_000],\n ['week', 604_800],\n ['day', 86_400],\n ['hour', 3_600],\n ['minute', 60],\n]\n\nexport function formatRelativeTime(iso: string, locale: string = 'en'): string {\n const diffMs = Date.now() - new Date(iso).getTime()\n const seconds = Math.round(diffMs / 1000)\n if (Math.abs(seconds) < 60) return 'just now'\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' })\n for (const [unit, secs] of UNITS) {\n if (Math.abs(seconds) >= secs) {\n const value = Math.round(seconds / secs)\n return rtf.format(-value, unit) // negative = past\n }\n }\n return 'just now'\n}\n","/*!\n * React Native Autolink\n *\n * Copyright 2016-2018 Josh Swan\n * Released under the MIT license\n * https://github.com/joshswan/react-native-autolink/blob/master/LICENSE\n *\n * Simplified and improved by Dean, to support mention list.\n * Ported to design-system post-components: routing and config dependencies removed.\n */\n\nimport React, { useCallback, useMemo } from 'react'\nimport Autolinker, { Match } from 'autolinker'\nimport { truncateSmart } from 'autolinker/dist/commonjs/truncate/truncate-smart'\nimport { truncateEnd } from 'autolinker/dist/commonjs/truncate/truncate-end'\nimport { truncateMiddle } from 'autolinker/dist/commonjs/truncate/truncate-middle'\nimport { MentionData, FormatMentionData } from '../types'\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst MENTION_TYPE = {\n MENTION: 'mention',\n HASHTAG: 'hashtag',\n} as const\n\n// ---------------------------------------------------------------------------\n// Utilities (ported from InputValidator.ts / helpers.tsx)\n// ---------------------------------------------------------------------------\n\nimport emojiRegex from 'emoji-regex'\n\nconst EMOJI_REGEX = emojiRegex()\n\nexport const getPureEmojiSize = (body: string): number => {\n let match: RegExpExecArray | null\n let emojiCount = 0\n let emojiSize = 0\n\n while ((match = EMOJI_REGEX.exec(body))) {\n const emoji = match[0]\n emojiSize += emoji.length\n emojiCount += 1\n }\n\n if (emojiSize === body.length) {\n return emojiCount\n }\n return 0\n}\n\nexport const checkMentionDataIndex = (\n mentionData: MentionData[] = [],\n copyMentionData: MentionData[] = [],\n body = ''\n): FormatMentionData[] => {\n let mentionBody = body\n const newMentionData = [...mentionData, ...copyMentionData]\n let lastMentionData: { index: number; endIndex: number } = { index: 0, endIndex: 0 }\n const formatNewMention: FormatMentionData[] = []\n\n for (let i = 0; i < newMentionData.length; i++) {\n const mention = { ...newMentionData[i] }\n\n if (mention.name && typeof mention.name === 'string') {\n mention.name = mention.name.trim()\n } else {\n continue\n }\n\n if (mentionBody.indexOf(mention.name) === -1) {\n continue\n }\n\n const type = mention.type\n const name = (type === MENTION_TYPE.MENTION ? '@' : '#') + mention.name\n const index = mentionBody.indexOf(name) + lastMentionData.endIndex\n const endIndex = index + name.length\n mentionBody = body.substr(endIndex, body.length)\n lastMentionData = { index, endIndex }\n\n formatNewMention.push({\n name,\n type,\n index,\n endIndex,\n data: mention,\n })\n }\n\n return formatNewMention\n}\n\nconst isLinkInternal = (\n url: string,\n supportDeepviewDomain: string | string[]\n): boolean => {\n if (!url) return false\n const domains = Array.isArray(supportDeepviewDomain)\n ? supportDeepviewDomain\n : supportDeepviewDomain\n ? [supportDeepviewDomain]\n : []\n return domains.some((d) => d.length > 0 && url.includes(d))\n}\n\n// ---------------------------------------------------------------------------\n// getUrl helper (exported for reuse by PostLinkItem etc.)\n// ---------------------------------------------------------------------------\n\nexport const getUrl = (match: any, phone?: any): [string] => {\n const type = match.getType()\n\n switch (type) {\n case 'email': {\n return [`mailto:${encodeURIComponent(match.getEmail())}`]\n }\n case 'phone': {\n const number = match.getNumber()\n switch (phone) {\n case 'sms':\n case 'text':\n return [`sms:${number}`]\n default:\n return [`tel:${number}`]\n }\n }\n case 'url': {\n return [match.getAnchorHref()]\n }\n default: {\n return [match.getMatchedText()]\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// truncate helper (attached to AutoLink below)\n// ---------------------------------------------------------------------------\n\ntype TruncateOptions = {\n truncate?: number\n truncateChars?: string\n truncateLocation?: 'smart' | 'end' | 'middle'\n}\n\nconst truncate = (\n text: string,\n { truncate: len = 32, truncateChars = '..', truncateLocation = 'smart' }: TruncateOptions = {}\n): string => {\n let fn: (text: string, length: number, ellipsisChars: string) => string\n\n switch (truncateLocation) {\n case 'end':\n fn = truncateEnd\n break\n case 'middle':\n fn = truncateMiddle\n break\n default:\n fn = truncateSmart\n }\n\n return fn(text, len, truncateChars)\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\ninterface AutoLinkProps {\n text: string\n mentionData?: MentionData[]\n onNavigate?: (href: string, isInternal: boolean) => void\n // When provided, internal mention links (@user / #group) render THROUGH this\n // component so the host app owns navigation: the web client passes its <Link>\n // (= router.push + a real href), the embed passes an <a> that absolutizes the\n // relative href to the Select app origin. Falls back to a raw <a> + onNavigate\n // when absent (backward-compatible for callers that haven't adopted it).\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n // pass-through display props\n phone?: any\n email?: any\n stripPrefix?: boolean\n style?: React.CSSProperties\n mentionClassName?: string\n className?: string\n}\n\nconst AutoLink = ({\n text: textProp,\n mentionData = [],\n onNavigate,\n linkComponent,\n supportDeepviewDomain = '',\n phone = true,\n email = true,\n stripPrefix = false,\n style = { fontSize: 12 },\n mentionClassName: mentionClassNameProp,\n className,\n}: AutoLinkProps) => {\n const mentionClassName = useMemo(\n () => mentionClassNameProp || 'font-bold text-action-primary',\n [mentionClassNameProp]\n )\n\n const handleNavigate = useCallback(\n (href: string, internal: boolean) => {\n if (onNavigate) {\n onNavigate(href, internal)\n } else if (internal) {\n window.location.href = href\n } else {\n window.open(href, '_blank')\n }\n },\n [onNavigate]\n )\n\n const renderDefaultLink = useCallback(\n (text: string, match: any, index: number) => {\n const [url] = getUrl(match, phone)\n const internal = isLinkInternal(url, supportDeepviewDomain)\n return (\n <a\n key={`${index}-autolink`}\n target=\"_blank\"\n rel={`noreferrer noopener${!internal ? ' nofollow' : ''}`}\n href={url}\n className=\"items-center text-link\"\n onClick={(e) => {\n e.stopPropagation()\n handleNavigate(url, internal)\n }}\n >\n {truncate(text, { truncate: 27, truncateLocation: 'end' })}\n </a>\n )\n },\n [phone, supportDeepviewDomain, handleNavigate]\n )\n\n const renderLink = useCallback(\n (text: string, match: Match, index: number) => {\n const [url] = getUrl(match, phone)\n if (isLinkInternal(url, supportDeepviewDomain)) {\n const internal = true\n return (\n <a\n key={`${index}-deeplink`}\n href={url}\n className=\"items-center text-link\"\n style={{ alignSelf: 'center' }}\n onClick={(e) => {\n e.stopPropagation()\n handleNavigate(url, internal)\n }}\n >\n {text}\n </a>\n )\n }\n return renderDefaultLink(text, match, index)\n },\n [phone, supportDeepviewDomain, renderDefaultLink, handleNavigate]\n )\n\n const renderMentionData = useCallback(\n (fmData: FormatMentionData, key: any) => {\n const href =\n fmData.type === MENTION_TYPE.HASHTAG\n ? `/groups/${fmData.data.selectId}`\n : `/users/${fmData.data.selectId || fmData.data.id}`\n\n const className = `no-underline hover:underline context-menu-ios-disable cursor-pointer ${mentionClassName}`\n\n // With a linkComponent, IT owns navigation (router.push / native nav) and\n // renders the href. The DS only stops the click from bubbling to the\n // card's press handler — calling handleNavigate too would double-navigate.\n // The linkComponent type doesn't accept an onClick, so wrap it in a span\n // (inline → no effect on text flow) that swallows the propagation.\n if (linkComponent) {\n const LinkComponent = linkComponent\n return (\n <span\n key={key + fmData.index}\n onClick={(e) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n }}\n >\n <LinkComponent href={href} className={className}>\n {fmData.name}\n </LinkComponent>\n </span>\n )\n }\n\n return (\n <a\n key={key + fmData.index}\n className={className}\n href={href}\n onClick={(e) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n handleNavigate(href, true)\n }}\n >\n {fmData.name}\n </a>\n )\n },\n [mentionClassName, handleNavigate, linkComponent]\n )\n\n const renderTextNodes = useCallback(() => {\n let text = textProp\n\n const uid = Math.floor(Math.random() * 0x10000000000).toString(16)\n const tokenRegexp = new RegExp(`(@__ELEMENT-${uid}-\\\\d+__@)`, 'g')\n\n const generateToken = (() => {\n let counter = 0\n return () => `@__ELEMENT-${uid}-${counter++}__@`\n })()\n\n const matches: Record<string, any> = {}\n\n try {\n text = Autolinker.link(text || '', {\n email,\n phone,\n urls: {\n schemeMatches: true,\n wwwMatches: true,\n tldMatches: true,\n } as any,\n stripPrefix,\n replaceFn: (match) => {\n const token = generateToken()\n matches[token] = match\n return token\n },\n })\n } catch {\n return null\n }\n\n const newNodes: React.ReactNode[] = []\n\n text\n .split(tokenRegexp)\n .filter((part) => !!part)\n .forEach((part, index) => {\n const match = matches[part]\n if (!match) {\n if (!mentionData || mentionData.length === 0) {\n newNodes.push(part)\n } else {\n const newMentionData = checkMentionDataIndex(mentionData, [], part)\n if (!newMentionData || newMentionData.length === 0) {\n newNodes.push(part)\n return\n }\n\n for (let j = 0; j < newMentionData.length; j++) {\n const curMentionData = newMentionData[j]\n\n if (j === 0) {\n const word = part.substring(0, curMentionData.index)\n newNodes.push(word)\n }\n\n newNodes.push(renderMentionData(curMentionData, part + index))\n\n const nextMentionData =\n j < newMentionData.length ? newMentionData[j + 1] : null\n if (nextMentionData) {\n const word = part.substring(curMentionData.endIndex, nextMentionData.index)\n newNodes.push(word)\n } else {\n const word = part.substring(curMentionData.endIndex, part.length)\n newNodes.push(word)\n }\n }\n }\n return\n }\n\n switch (match.getType()) {\n case 'email':\n case 'phone':\n case 'url':\n newNodes.push(renderLink(match.getAnchorText(), match, index))\n break\n default:\n newNodes.push(part)\n break\n }\n })\n\n let textStyle: React.CSSProperties | undefined = style\n const fontSize = style && (style as any).fontSize ? (style as any).fontSize : 12\n const pureEmojiCount = getPureEmojiSize(text.trim())\n if (pureEmojiCount === 1) {\n textStyle = { ...style, fontSize: fontSize * 2.5 }\n } else if (pureEmojiCount === 2) {\n textStyle = { ...style, fontSize: fontSize * 2 }\n } else if (pureEmojiCount === 3) {\n textStyle = { ...style, fontSize: fontSize * 1.5 }\n }\n\n return (\n <div style={textStyle} className={className}>\n {newNodes}\n </div>\n )\n }, [\n style,\n email,\n phone,\n stripPrefix,\n mentionData,\n textProp,\n className,\n renderLink,\n renderMentionData,\n ])\n\n return renderTextNodes()\n}\n\nAutoLink.truncate = truncate\n\nexport default AutoLink\n","import AutoLink from './AutoLink'\nimport { hasMeaningfulHtml } from '../resolver/postContentResolver'\nimport type { ResolvedTextContent } from '../resolver/postContentResolver'\nimport { cn } from '../utils/cn'\nimport DOMPurify from 'dompurify'\nimport React, { useMemo } from 'react'\nimport PostEmail from './PostEmail'\n\ninterface Props {\n textContent: ResolvedTextContent\n showFull?: boolean\n isPostDetail: boolean\n isRichContent?: boolean\n hideEmailDescription?: boolean\n isEmailPost?: boolean\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n}\n\nconst PURIFY_CONFIG = {\n ALLOWED_TAGS: [\n 'p',\n 'br',\n 'b',\n 'i',\n 'em',\n 'strong',\n 'a',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'blockquote',\n 'code',\n 'pre',\n 'span',\n 'div',\n 'img',\n 'video',\n 'figure',\n 'figcaption',\n 'table',\n 'thead',\n 'tbody',\n 'tr',\n 'th',\n 'td',\n 'hr',\n 'sub',\n 'sup',\n 's',\n 'u',\n ],\n ALLOWED_ATTR: [\n 'href',\n 'controls',\n 'target',\n 'rel',\n 'class',\n 'id',\n 'src',\n 'alt',\n 'title',\n 'width',\n 'height',\n 'data-*',\n ],\n ALLOW_DATA_ATTR: true,\n ADD_ATTR: ['target'],\n FORBID_TAGS: ['script', 'style', 'iframe', 'object', 'embed', 'form'],\n FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover'],\n}\n\nconst VOID_TAGS = new Set([\n 'BR',\n 'HR',\n 'IMG',\n 'VIDEO',\n 'INPUT',\n 'AREA',\n 'BASE',\n 'COL',\n 'LINK',\n 'META',\n 'PARAM',\n 'SOURCE',\n 'TRACK',\n 'WBR',\n])\n\nconst removeEmpty = (el: Element): void => {\n Array.from(el.children).forEach(removeEmpty)\n if (VOID_TAGS.has(el.tagName)) return\n if (!el.textContent?.trim() && el.children.length === 0) el.remove()\n}\n\nconst PostBody: React.FC<Props> = ({\n textContent,\n showFull = true,\n isPostDetail,\n isRichContent = false,\n hideEmailDescription = false,\n isEmailPost = false,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n}) => {\n const { plain, html, truncatedPlain, mentionData } = textContent\n\n const { sanitizedHtml, feedSanitizedHtml } = useMemo(() => {\n if (!html) return { sanitizedHtml: null, feedSanitizedHtml: null }\n\n const sanitized = DOMPurify.sanitize(html, PURIFY_CONFIG)\n\n // Feed mode: keep only the first media element to avoid flooding the feed.\n if (typeof document === 'undefined') {\n return { sanitizedHtml: sanitized, feedSanitizedHtml: sanitized }\n }\n\n const feedContainer = document.createElement('div')\n feedContainer.innerHTML = sanitized\n let keptOne = false\n feedContainer.querySelectorAll('img, video').forEach((el) => {\n if (!keptOne) {\n keptOne = true\n } else {\n el.remove()\n }\n })\n removeEmpty(feedContainer)\n return {\n sanitizedHtml: sanitized,\n feedSanitizedHtml: feedContainer.innerHTML,\n }\n }, [html])\n\n const { subject } = textContent\n const displayText = showFull ? plain : truncatedPlain\n const hasHtml = !!sanitizedHtml\n const hasMeaningfulHtmlText = hasMeaningfulHtml(sanitizedHtml)\n\n // Memoise the dangerouslySetInnerHTML elements so React sees the same React\n // element reference across renders and skips reconciling the prose subtree.\n // Without this, a re-render of PostBody re-creates the inner <div>'s element\n // descriptor; React diffs it, re-applies innerHTML, and the inner <video>\n // node is replaced — losing readyState and triggering a fresh metadata load.\n const detailProseElement = useMemo(\n () =>\n sanitizedHtml ? (\n <div\n className=\"prose prose-p:my-2! prose-a:text-action-primary! prose-a:no-underline! prose-img:my-4! prose-video:my-4! px-5! pb-4! max-w-full leading-relaxed overflow-hidden\"\n dangerouslySetInnerHTML={{ __html: sanitizedHtml }}\n />\n ) : null,\n [sanitizedHtml]\n )\n\n const feedProseElement = useMemo(\n () =>\n feedSanitizedHtml ? (\n <div\n className=\"prose *:px-4! *:data-[media='true']:px-0! *:data-link-preview:mx-4! [&>[data-media='true']>img]:rounded-none! [&>[data-media='true']>video]:rounded-none! [&>[data-media='true']>video]:size-full! prose-video:size-full! *:data-[media='true']:my-2 [&>div]:last-of-type:mb-0! prose-img:my-0! prose-img:w-full prose-video:my-0! prose-p:my-2! prose-a:text-action-primary! prose-a:no-underline! pb-4 max-w-full leading-relaxed line-clamp-4 overflow-hidden\"\n dangerouslySetInnerHTML={{ __html: feedSanitizedHtml }}\n />\n ) : null,\n [feedSanitizedHtml]\n )\n\n // If there's no text at all (neither plain nor html), render nothing\n if ((!displayText || typeof displayText !== 'string') && !hasHtml) {\n return null\n }\n\n const renderAutoLink = () => {\n if (!displayText || typeof displayText !== 'string') return null\n return (\n <AutoLink\n text={displayText}\n mentionData={mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n />\n )\n }\n\n if (isPostDetail) {\n if (isEmailPost && html) {\n return (\n <div className=\"relative flex-1 max-h-screen w-full overflow-x-hidden overflow-y-auto xl:px-0 px-5\">\n <h1 className=\"text-2xl font-semibold text-gray-900 leading-snug mt-5 mb-3 px-5\">\n {subject}\n </h1>\n <PostEmail html={html} />\n </div>\n )\n }\n\n return (\n <div className=\"flex-1\">\n {/* Keep plain text visible when htmlBody has no meaningful text (e.g. media-only html). */}\n {!hasMeaningfulHtmlText && <div>{renderAutoLink()}</div>}\n {sanitizedHtml && hasMeaningfulHtmlText && (\n <div data-theme=\"select-post-builder\" className=\"w-full max-w-full\">\n {detailProseElement}\n </div>\n )}\n </div>\n )\n }\n\n if (isRichContent && feedSanitizedHtml && hasMeaningfulHtmlText) {\n return (\n <div className={cn('flex-1 pb-4')} data-theme=\"select-post-builder\">\n {feedProseElement}\n </div>\n )\n }\n\n // Email post feed preview: subject line title + teaser body.\n if (subject) {\n return (\n <div className=\"flex-1 px-4 pb-4\">\n <h1 className=\"text-2xl font-semibold text-gray-900 leading-snug mb-1\">\n {subject}\n </h1>\n {!hideEmailDescription &&\n displayText &&\n typeof displayText === 'string' && (\n <AutoLink\n text={displayText}\n mentionData={mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n className=\"whitespace-normal leading-relaxed text-gray-600 line-clamp-3\"\n style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}\n />\n )}\n </div>\n )\n }\n\n // Feed default: plain text preview.\n return (\n <div className=\"flex-1\">\n <div>{renderAutoLink()}</div>\n </div>\n )\n}\n\nexport default PostBody\n","import React, { useEffect, useMemo, useRef } from 'react'\nimport DOMPurify from 'dompurify'\n\nconst EMAIL_PURIFY_CONFIG = {\n ALLOWED_TAGS: [\n // Structure\n 'html',\n 'head',\n 'body',\n 'style',\n // Layout (email is table-based)\n 'table',\n 'thead',\n 'tbody',\n 'tr',\n 'th',\n 'td',\n // Text\n 'p',\n 'span',\n 'div',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'b',\n 'strong',\n 'i',\n 'em',\n 'u',\n 'sub',\n 'sup',\n 'br',\n 'ul',\n 'ol',\n 'li',\n // Media & links\n 'a',\n 'img',\n ],\n ALLOWED_ATTR: [\n // Styling — critical for email\n 'style',\n 'class',\n 'bgcolor',\n 'color',\n // Table layout attributes (email-specific)\n 'width',\n 'height',\n 'align',\n 'valign',\n 'cellpadding',\n 'cellspacing',\n 'border',\n 'colspan',\n 'rowspan',\n // Images\n 'src',\n 'alt',\n // Links\n 'href',\n 'target',\n 'rel',\n // Accessibility\n 'role',\n 'aria-label',\n 'aria-roledescription',\n // Email-specific\n 'data-open-tracking',\n 'data-read-online-tooltip',\n ],\n ALLOW_DATA_ATTR: false,\n FORCE_BODY: false,\n WHOLE_DOCUMENT: true, // preserves <head> with <style>\n}\n\nconst sanitizeEmailHtml = (rawHtml: string) => {\n const clean = DOMPurify.sanitize(rawHtml, EMAIL_PURIFY_CONFIG)\n const doc = new DOMParser().parseFromString(clean, 'text/html')\n\n if (!doc.head) {\n const head = doc.createElement('head')\n doc.documentElement.insertBefore(head, doc.body)\n }\n\n const base = doc.createElement('base')\n base.setAttribute('target', '_blank')\n doc.head.appendChild(base)\n\n const style = doc.createElement('style')\n style.textContent = `\n html, body {\n margin: 0;\n padding: 0;\n }\n\n @media only screen and (max-width: 640px) {\n table[style*=\"min-width\"] {\n min-width: 0 !important;\n width: 100% !important;\n max-width: 100% !important;\n }\n\n td[style*=\"min-width\"],\n th[style*=\"min-width\"],\n div[style*=\"min-width\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n box-sizing: border-box !important;\n }\n\n img {\n max-width: 100% !important;\n height: auto !important;\n }\n }`\n\n doc.head.appendChild(style)\n\n doc.querySelectorAll('a[href]').forEach((a) => {\n a.setAttribute('target', '_blank')\n a.setAttribute('rel', 'noopener noreferrer nofollow')\n })\n\n return '<!DOCTYPE html>\\n' + doc.documentElement.outerHTML\n}\n\nconst PostEmail: React.FC<{ html: string }> = ({ html }) => {\n const ref = useRef<HTMLIFrameElement>(null)\n const cleanHtml = useMemo(() => sanitizeEmailHtml(html), [html])\n\n useEffect(() => {\n const iframe = ref.current\n if (!iframe) return\n\n let resizeObserver: ResizeObserver | null = null\n let rafId: number | null = null\n let timeoutIds: number[] = []\n\n const resizeIframe = () => {\n try {\n const doc = iframe.contentDocument\n if (!doc) return\n\n const body = doc.body\n const height = Math.max(\n Math.ceil(body.scrollHeight),\n Math.ceil(body.offsetHeight),\n Math.ceil(body.getBoundingClientRect().height)\n )\n\n iframe.style.height = `${height + 2}px`\n } catch {\n // ignore\n }\n }\n\n const scheduleResize = () => {\n if (rafId) cancelAnimationFrame(rafId)\n rafId = requestAnimationFrame(resizeIframe)\n }\n\n const handleLoad = () => {\n scheduleResize()\n\n try {\n const doc = iframe.contentDocument\n if (!doc) return\n\n Array.from(doc.images).forEach((img) => {\n img.addEventListener('load', scheduleResize)\n img.addEventListener('error', scheduleResize)\n })\n\n resizeObserver = new ResizeObserver(() => {\n scheduleResize()\n })\n\n resizeObserver.observe(doc.body)\n\n timeoutIds = [\n window.setTimeout(scheduleResize, 50),\n window.setTimeout(scheduleResize, 150),\n window.setTimeout(scheduleResize, 300),\n window.setTimeout(scheduleResize, 600),\n ]\n } catch {\n // ignore\n }\n }\n\n const handleResize = () => {\n scheduleResize()\n }\n\n iframe.addEventListener('load', handleLoad)\n window.addEventListener('resize', handleResize)\n\n return () => {\n iframe.removeEventListener('load', handleLoad)\n window.removeEventListener('resize', handleResize)\n\n if (rafId) cancelAnimationFrame(rafId)\n timeoutIds.forEach(clearTimeout)\n resizeObserver?.disconnect()\n\n try {\n const doc = iframe.contentDocument\n if (!doc) return\n\n Array.from(doc.images).forEach((img) => {\n img.removeEventListener('load', scheduleResize)\n img.removeEventListener('error', scheduleResize)\n })\n } catch {\n // ignore\n }\n }\n }, [cleanHtml])\n\n return (\n <iframe\n ref={ref}\n srcDoc={cleanHtml}\n sandbox=\"allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation\"\n className=\"block w-full border-0\"\n />\n )\n}\n\nexport default PostEmail\n","import React, { useMemo, FC } from 'react'\nimport { ItemData, PollItemData } from '../types'\nimport AsyncImage from './AsyncImage'\nimport Loader from './Loader'\nimport { postItemType } from '../utils/postItemType'\n\ninterface MediaProps {\n item: ItemData | PollItemData\n className: string\n handleLightbox?: (e: React.MouseEvent) => void\n additionalImagesCount?: number\n ratio?: number\n data?: ItemData[]\n isPostDetail?: boolean\n onCardPress?: () => void\n}\n\nconst MediaView: FC<MediaProps> = ({\n item,\n className,\n handleLightbox,\n additionalImagesCount,\n ratio,\n data,\n isPostDetail,\n onCardPress,\n}) => {\n const mediaSrc = useMemo(() => {\n if (\n item.type === postItemType.IMAGE_ITEM_TO_UPLOAD ||\n item.type === postItemType.MEDIA_ITEM_TO_UPLOAD\n ) {\n return URL.createObjectURL(item.file)\n }\n return item.sources?.original?.url ?? ''\n }, [item.file, item.sources?.original?.url, item.type])\n\n if (item.type === postItemType.POLL_TEXT_ITEM) {\n const textViewClass = `${className} aspect-square`\n return (\n <div\n key={(item as PollItemData).key}\n onClick={onCardPress}\n className={textViewClass}\n style={{\n backgroundColor: (item as PollItemData).option_color,\n }}\n >\n <div className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2\">\n <p className=\"text-center text-lg font-bold text-background\">\n {(item as PollItemData).text}\n </p>\n </div>\n </div>\n )\n }\n\n if (\n item.type === postItemType.IMAGE_ITEM ||\n item.type === postItemType.POLL_IMAGE_ITEM ||\n item.type === postItemType.GIF_ITEM ||\n item.type === postItemType.IMAGE_ITEM_TO_UPLOAD ||\n item.type === postItemType.MEDIA_ITEM ||\n item.type === postItemType.MEDIA_ITEM_TO_UPLOAD ||\n item.type === postItemType.POLL_MEDIA_ITEM\n ) {\n return (\n <div key={item.key} onClick={handleLightbox} className={className}>\n {item.type.includes('ToUpload') && <Loader type=\"upload_loader\" />}\n <AsyncImage\n alt={mediaSrc}\n src={mediaSrc}\n className={className}\n ratio={ratio}\n item={item}\n data={data || []}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n />\n {additionalImagesCount && (\n <div className=\"absolute right-1 top-0\">\n <p className=\"text-4xl font-bold text-muted-foreground\">{`+${additionalImagesCount}`}</p>\n </div>\n )}\n </div>\n )\n }\n\n return null\n}\n\nexport default MediaView\n","/* eslint-disable @next/next/no-img-element */\nimport React, { useCallback, useMemo } from 'react'\nimport { Gallery, Item } from 'react-photoswipe-gallery'\nimport { postItemType } from '../utils/postItemType'\nimport 'photoswipe/dist/photoswipe.css'\nimport Loader from './Loader'\nimport AppIcon from './AppIcon'\nimport { ItemData, PollItemData } from '../types'\n\ninterface Props {\n data?: ItemData[]\n item: PollItemData | ItemData\n onCardPress?: () => void\n src?: string\n alt?: string\n className?: string\n ratio: number | undefined\n isPostDetail?: boolean\n}\n\ninterface Placeholder {\n isBase64: boolean\n url: string\n}\n\nconst isVideo = (url: string) => {\n return (\n url?.toLowerCase().endsWith('.mp4') ||\n url?.toLowerCase().endsWith('.webm') ||\n url?.toLowerCase().endsWith('.ogg')\n )\n}\n\nconst isImage = (url: string) => {\n return (\n url?.toLowerCase().endsWith('.jpeg') ||\n url?.toLowerCase().endsWith('.jpg') ||\n url?.toLowerCase().endsWith('.png') ||\n url?.toLowerCase().endsWith('.webp') ||\n url?.toLowerCase().endsWith('.gif') ||\n url?.toLowerCase().endsWith('.avif')\n )\n}\n\nconst calVideoRatio = (width: number, height: number) => {\n let ratio = 1\n if (width > 0 && height > 0) {\n ratio = width / height\n if (ratio < 0.7) {\n ratio = 0.7\n }\n }\n return `${ratio}`\n}\n\nconst AsyncImage: React.FC<Props> = ({\n data,\n ratio,\n className,\n isPostDetail,\n item,\n onCardPress,\n src = '',\n alt,\n}) => {\n const {\n placeholder = {\n isBase64: false,\n url: '',\n },\n }: { placeholder: Placeholder } = item.sources || {}\n\n const placeholderUrl = useMemo(() => {\n const url = placeholder.isBase64\n ? `data:${item.imageType};base64,${placeholder.url}`\n : placeholder.url\n return url\n }, [placeholder.isBase64, placeholder.url, item.imageType])\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (onCardPress) {\n onCardPress()\n }\n },\n [onCardPress]\n )\n\n const showUploadImg = (item: PollItemData | ItemData) => {\n return item.imageType === 'image/heic' ? (\n <img\n src={src}\n alt={alt ?? ''}\n className={className}\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n />\n ) : (\n <div\n className={className}\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n ></div>\n )\n }\n\n const uploadVideoPost = item.type.includes('ToUpload')\n const showUploadingMedia = () => (\n <div\n className=\"relative h-full w-full\"\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n >\n {uploadVideoPost && <Loader type=\"upload_loader\" />}\n <video\n title=\"Video Upload Preview\"\n width={'100%'}\n height={'100%'}\n className={className}\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n >\n {item.file instanceof Blob && (\n <source src={URL.createObjectURL(item.file as Blob)} type={(item.file as File).type} />\n )}\n </video>\n <AppIcon\n name=\"video\"\n className={`absolute bottom-2 left-2 text-background`}\n />\n </div>\n )\n\n const renderMediaItem = useCallback(\n (media: ItemData) => {\n const originalInfo = media?.sources?.original || {}\n let thumbnailInfo = media?.sources?.thumbnail\n if (\n originalInfo?.url?.endsWith('gif') ||\n !isImage(media?.sources?.thumbnail?.url)\n ) {\n thumbnailInfo = originalInfo\n }\n\n const aspectRatio =\n `${ratio}` ||\n calVideoRatio(originalInfo.width, originalInfo.height) ||\n 'auto'\n const hasStableKeys = Boolean(media.key && item.key)\n const isCurrentItem = hasStableKeys\n ? media.key === item.key\n : originalInfo.url === src\n const display = isCurrentItem ? 'block' : 'none'\n\n const isBlobVideo =\n originalInfo?.url?.startsWith('blob:') &&\n typeof media.imageType === 'string' &&\n media.imageType.startsWith('video/')\n\n if (isBlobVideo) {\n return (\n <div\n key={media.key}\n onClick={handleClick}\n className={className + ' media-item'}\n style={{ aspectRatio, display }}\n >\n <video\n src={originalInfo.url}\n muted\n playsInline\n preload=\"metadata\"\n className={className}\n style={{\n aspectRatio,\n display: 'block',\n width: '100%',\n height: '100%',\n }}\n />\n <AppIcon\n name=\"video\"\n className=\"absolute bottom-2 left-2 text-background\"\n />\n <AppIcon\n name=\"circlePlay\"\n className=\"size-10 bg-foreground/20 hover:bg-foreground/40 transition-colors duration-300 rounded-full absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-background\"\n />\n </div>\n )\n }\n\n if (isVideo(originalInfo.url)) {\n return (\n <Item\n key={media.key}\n content={\n <div\n className=\"flex h-full w-full items-center justify-center\"\n style={{\n aspectRatio,\n }}\n >\n <video\n height={'100%'}\n width={'100%'}\n className=\"aspect-video\"\n controls\n autoPlay\n >\n <source src={originalInfo.url} type={media.imageType} />\n </video>\n </div>\n }\n >\n {({ ref, open }) => (\n <div onClick={isPostDetail ? open : handleClick}>\n <img\n src={thumbnailInfo.url}\n ref={ref as React.Ref<HTMLImageElement>}\n alt={alt ?? ''}\n className={className + ' media-item '}\n style={{\n aspectRatio,\n display,\n }}\n onClick={isPostDetail ? open : handleClick}\n />\n <AppIcon\n name=\"video\"\n className={`absolute bottom-2 left-2 text-background`}\n onClick={isPostDetail ? open : handleClick}\n ref={ref as React.Ref<HTMLImageElement>}\n style={{\n aspectRatio,\n display,\n }}\n />\n <AppIcon\n name=\"circlePlay\"\n className={`size-10 bg-foreground/20 hover:bg-foreground/40 transition-colors duration-300 rounded-full absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-background`}\n onClick={isPostDetail ? open : handleClick}\n ref={ref as React.Ref<HTMLImageElement>}\n style={{\n aspectRatio,\n display,\n }}\n />\n </div>\n )}\n </Item>\n )\n }\n\n return (\n <Item\n key={media.key}\n width={originalInfo.width}\n height={originalInfo.height}\n original={originalInfo.url}\n thumbnail={thumbnailInfo.url}\n >\n {({ open, ref }) => (\n <img\n onClick={isPostDetail ? open : handleClick}\n ref={ref as React.Ref<HTMLImageElement>}\n src={originalInfo.url || thumbnailInfo.url}\n alt={alt ?? ''}\n className={className}\n style={{\n aspectRatio,\n display,\n }}\n />\n )}\n </Item>\n )\n },\n [className, handleClick, isPostDetail, item.key, ratio, src]\n )\n\n const handleMediaItems = () => {\n return (\n <Gallery options={{ showHideAnimationType: 'fade' }}>\n {data?.map((media: ItemData) => renderMediaItem(media))}\n </Gallery>\n )\n }\n\n return (\n <div\n style={{\n backgroundImage: `url(${placeholderUrl})`,\n }}\n className=\"h-full w-full bg-cover bg-center bg-no-repeat\"\n >\n {item.type === postItemType.MEDIA_ITEM_TO_UPLOAD && showUploadingMedia()}\n {item.type === postItemType.IMAGE_ITEM_TO_UPLOAD && showUploadImg(item)}\n {item.type !== postItemType.IMAGE_ITEM_TO_UPLOAD &&\n item.type !== postItemType.MEDIA_ITEM_TO_UPLOAD &&\n handleMediaItems()}\n </div>\n )\n}\n\nexport default AsyncImage\n","import React from 'react'\n\ninterface LoaderProps {\n type?: string\n fullScreen?: boolean\n}\n\nconst Loader: React.FC<LoaderProps> = ({\n type = 'page_loader',\n fullScreen = false,\n}) => {\n const style: Record<string, string> = {\n page_loader: 'after:border-border after:border-t-action-primary',\n upload_loader:\n 'after:border-foreground after:border-t-background bg-foreground rounded-full',\n }\n const showLoader = () => {\n return (\n <div className=\"absolute left-1/2 top-1/2 z-20 -translate-x-1/2 -translate-y-1/2\">\n <div\n className={`after:contents-[''] flex h-full items-center justify-center after:h-10 after:w-10 after:animate-spin after:rounded-[50%] after:border-4 ${style[type]} `}\n ></div>\n </div>\n )\n }\n if (fullScreen) {\n return (\n <div className=\"h-screen-safe-14 lg:h-screen-safe-16\">{showLoader()}</div>\n )\n }\n return showLoader()\n}\n\nexport default Loader\n","import type { PollItemData, PollResult } from '../../types'\n\nexport const getOptionRateV2 = (\n item: PollItemData,\n voteResult: PollResult | null\n): string => {\n if (!voteResult) return '0%'\n const voteItem = voteResult.options.find(\n (option) => option.option_id === item.option_id\n )\n const totalCount = voteResult.options.reduce(\n (total, option) => total + option.count,\n 0\n )\n if (voteItem && totalCount > 0) {\n return ((voteItem.count / totalCount) * 100).toFixed(0) + '%'\n }\n return '0%'\n}\n\nexport const getVoteInfo = (\n item: PollItemData,\n voteResult: PollResult | null\n): { rate: string; isAppOwnerVoted: boolean; isVoteItem: boolean } => {\n const isAppOwnerVoted = !!voteResult?.user_vote_option_id\n const isVoteItem = !!voteResult?.options.find(\n (option) =>\n option.option_id === item.option_id &&\n option.option_id === voteResult.user_vote_option_id\n )\n return {\n rate: getOptionRateV2(item, voteResult),\n isAppOwnerVoted,\n isVoteItem,\n }\n}\n","import React from 'react'\nimport AppIcon from '../AppIcon'\nimport type { PollItemData, PollResult } from '../../types'\nimport { getVoteInfo } from './pollUtils'\n\ntype Props = {\n type: 'NORMAL' | 'SINGLE_LEFT' | 'SINGLE_RIGHT'\n index: number\n item: PollItemData\n voteResult: PollResult | null\n isPostOwner?: boolean\n}\n\nconst PostPollIResultView: React.FC<Props> = ({\n type,\n item,\n voteResult,\n isPostOwner,\n}) => {\n const voteInfo = getVoteInfo(item, voteResult)\n const textCss = voteInfo.isVoteItem ? '#FFFFFF' : item.option_color\n const backgroundCss = voteInfo.isVoteItem ? item.option_color : '#FFFFFF'\n const totalVotes =\n voteResult?.options.reduce((sum, o) => sum + o.count, 0) ?? 0\n\n if ((!voteInfo.isAppOwnerVoted && !isPostOwner) || totalVotes === 0) {\n return null\n }\n\n if (type === 'SINGLE_LEFT') {\n return (\n <div\n className=\"absolute top-0 m-6 flex flex-row items-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md\"\n style={{ backgroundColor: backgroundCss }}\n >\n <p className=\"text-sm font-bold\" style={{ color: textCss }}>\n {voteInfo.rate}\n </p>\n <AppIcon\n name=\"thumbUp\"\n size={16}\n className=\"ml-2\"\n style={{ color: textCss }}\n />\n </div>\n )\n }\n\n if (type === 'SINGLE_RIGHT') {\n return (\n <div\n className=\"absolute right-0 top-0 m-6 flex flex-row items-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md\"\n style={{ backgroundColor: backgroundCss }}\n >\n <p className=\"text-sm font-bold\" style={{ color: textCss }}>\n {voteInfo.rate}\n </p>\n <AppIcon\n name=\"thumbDown\"\n size={16}\n className=\"ml-2\"\n style={{ color: textCss }}\n />\n </div>\n )\n }\n\n return (\n <div\n className=\"absolute top-0 m-3 flex items-center justify-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md\"\n style={{ backgroundColor: backgroundCss }}\n >\n <p className=\"text-sm font-bold\" style={{ color: textCss }}>\n {voteInfo.rate}\n </p>\n </div>\n )\n}\n\nexport default PostPollIResultView\n","import React from 'react'\nimport AppIcon from '../AppIcon'\nimport type { PollItemData, PollResult } from '../../types'\nimport { getVoteInfo } from './pollUtils'\n\ninterface Props {\n type: 'NORMAL' | 'SINGLE_LEFT' | 'SINGLE_RIGHT'\n onVotePress: (item: PollItemData) => void\n item: PollItemData\n voteResult: PollResult | null\n}\n\nconst PostPollIButtonView: React.FC<Props> = ({\n type,\n item,\n voteResult,\n onVotePress,\n}) => {\n const voteInfo = getVoteInfo(item, voteResult)\n\n const handleVoting = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n if (!voteInfo.isVoteItem) onVotePress(item)\n }\n\n const voteLabel = voteInfo.isVoteItem\n ? `Voted: ${item.text || 'this option'}`\n : `Vote for ${item.text || 'this option'}`\n\n if (type === 'SINGLE_LEFT') {\n const nonVoteClassName =\n 'absolute bottom-0 left-0 m-6 flex size-11 items-center justify-center rounded-full bg-black/30 backdrop-blur-sm border border-background/20 cursor-pointer transition-all duration-200 hover:bg-black/50'\n\n const voteClassName =\n 'absolute bottom-0 left-0 m-6 flex size-11 items-center justify-center rounded-full bg-background shadow-lg cursor-pointer transition-all duration-200'\n return (\n <button\n className={voteInfo.isVoteItem ? voteClassName : nonVoteClassName}\n onClick={handleVoting}\n aria-label={voteLabel}\n aria-pressed={voteInfo.isVoteItem}\n >\n <AppIcon\n name=\"thumbUp\"\n size={20}\n aria-hidden=\"true\"\n className={voteInfo.isVoteItem ? '' : 'text-white'}\n style={voteInfo.isVoteItem ? { color: item.option_color } : {}}\n />\n </button>\n )\n }\n\n if (type === 'SINGLE_RIGHT') {\n const nonVoteClassName =\n 'absolute bottom-0 right-0 m-6 flex size-11 items-center justify-center rounded-full bg-black/30 backdrop-blur-sm border border-background/20 cursor-pointer transition-all duration-200 hover:bg-black/50'\n\n const voteClassName =\n 'absolute bottom-0 right-0 m-6 flex size-11 items-center justify-center rounded-full bg-background shadow-lg cursor-pointer transition-all duration-200'\n return (\n <button\n className={voteInfo.isVoteItem ? voteClassName : nonVoteClassName}\n onClick={handleVoting}\n aria-label={voteLabel}\n aria-pressed={voteInfo.isVoteItem}\n >\n <AppIcon\n name=\"thumbDown\"\n size={20}\n aria-hidden=\"true\"\n className={voteInfo.isVoteItem ? '' : 'text-white'}\n style={voteInfo.isVoteItem ? { color: item.option_color } : {}}\n />\n </button>\n )\n }\n\n const nonVoteClassName =\n 'absolute bottom-3 right-3 rounded-full p-1 backdrop-blur-md border border-background/40 bg-background/20 hover:bg-background/30 scale-100 transition-all duration-300 z-20 cursor-pointer'\n\n const voteClassName =\n 'absolute bottom-3 right-3 rounded-full p-1 backdrop-blur-md border border-action-primary bg-action-primary scale-110 transition-all duration-300 z-20 cursor-pointer'\n\n return (\n <button\n className={voteInfo.isVoteItem ? voteClassName : nonVoteClassName}\n style={\n voteInfo.isVoteItem && item.option_color\n ? {\n backgroundColor: item.option_color,\n borderColor: item.option_color,\n }\n : undefined\n }\n onClick={handleVoting}\n aria-label={voteLabel}\n aria-pressed={voteInfo.isVoteItem}\n >\n <AppIcon\n name=\"checkCircle2\"\n aria-hidden=\"true\"\n className={`size-8 ${voteInfo.isVoteItem ? 'text-white' : 'text-white/90 drop-shadow-md'}`}\n />\n </button>\n )\n}\n\nexport default PostPollIButtonView\n","import React from 'react'\nimport type { PollItemData, PollResult } from '../../types'\nimport MediaView from '../MediaView'\nimport PostPollIResultView from './PostPollIResultView'\nimport PostPollIButtonView from './PostPollIButtonView'\n\ninterface Props {\n items: PollItemData[]\n voteResult: PollResult | null\n onVotePress: (item: PollItemData) => void\n onCardPress: () => void\n isPostDetail: boolean\n isInboxCard?: boolean\n isPostOwner?: boolean\n}\n\nconst PostPollLayoutOne: React.FC<Props> = ({\n items,\n voteResult,\n onVotePress,\n onCardPress,\n isPostDetail,\n isInboxCard,\n isPostOwner,\n}) => {\n const { sources } = items[0]\n let ratio = 1\n if (!isInboxCard && sources && sources.original) {\n const { width, height } = sources.original\n if (width > 0 && height > 0) {\n ratio = width / height\n if (ratio < 0.7) {\n // to avoid the layout too high\n ratio = 0.7\n }\n }\n }\n\n const className = 'object-cover w-full'\n return (\n <div className=\"not-prose relative w-full box-border\">\n <div className=\"relative w-full bg-gray-100\">\n <MediaView\n item={items[0]}\n className={className}\n data={[items[0]]}\n ratio={ratio}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n />\n <PostPollIResultView\n type=\"SINGLE_LEFT\"\n item={items[0]}\n index={0}\n voteResult={voteResult}\n isPostOwner={isPostOwner}\n />\n <PostPollIButtonView\n type=\"SINGLE_LEFT\"\n item={items[0]}\n voteResult={voteResult}\n onVotePress={onVotePress}\n />\n <PostPollIResultView\n type=\"SINGLE_RIGHT\"\n item={items[1]}\n index={1}\n voteResult={voteResult}\n isPostOwner={isPostOwner}\n />\n <PostPollIButtonView\n type=\"SINGLE_RIGHT\"\n item={items[1]}\n voteResult={voteResult}\n onVotePress={onVotePress}\n />\n </div>\n </div>\n )\n}\n\nexport default PostPollLayoutOne\n","import React from 'react'\nimport type { PollItemData, PollResult } from '../../types'\nimport MediaView from '../MediaView'\nimport PostPollIResultView from './PostPollIResultView'\nimport PostPollIButtonView from './PostPollIButtonView'\n\ninterface Props {\n items: PollItemData[]\n voteResult: PollResult | null\n onVotePress: (item: PollItemData) => void\n onCardPress: () => void\n isPostDetail: boolean\n isPostOwner?: boolean\n}\n\nconst GRID_CLASS: Record<number, string> = {\n 2: 'grid grid-flow-col grid-cols-2 grid-rows-1 gap-0.5 bg-gray-100',\n 3: 'grid grid-cols-2 grid-rows-1 gap-0.5 bg-gray-100',\n 4: 'grid grid-flow-row grid-cols-2 grid-rows-2 gap-0.5 bg-gray-100',\n}\n\nconst PostPollLayoutGrid: React.FC<Props> = ({\n items,\n voteResult,\n onVotePress,\n onCardPress,\n isPostDetail,\n isPostOwner,\n}) => {\n const gridClass = GRID_CLASS[items.length] ?? GRID_CLASS[4]\n\n return (\n <div className=\"not-prose w-full box-border\">\n <div className={gridClass}>\n {items.map((item, index) => (\n <div key={item.option_id || index} className=\"relative group\">\n <MediaView\n item={item}\n className=\"aspect-[1] col-span-1 object-cover w-full\"\n data={items}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n />\n <PostPollIResultView\n type=\"NORMAL\"\n item={item}\n index={index}\n voteResult={voteResult}\n isPostOwner={isPostOwner}\n />\n <PostPollIButtonView\n type=\"NORMAL\"\n item={item}\n voteResult={voteResult}\n onVotePress={onVotePress}\n />\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nexport default PostPollLayoutGrid\n","import React from 'react'\nimport { PollItemData } from '../types'\nimport PostPollLayoutOne from './PostPollLayout/PostPollLayoutOne'\nimport PostPollLayoutGrid from './PostPollLayout/PostPollLayoutGrid'\nimport { PollResult } from '../types'\n\ninterface Props {\n items: PollItemData[]\n voteResult: PollResult | null\n onVotePress: (item: PollItemData) => void\n onCardPress: () => void\n isPostDetail: boolean\n isInboxCard?: boolean\n isPostOwner?: boolean\n}\n\nconst PostPollView: React.FC<Props> = ({\n items,\n voteResult,\n onVotePress,\n onCardPress,\n isPostDetail,\n isInboxCard,\n isPostOwner,\n}) => {\n const isSingleChoicePoll = items.length === 2 && items[0].key === items[1].key\n\n if (isSingleChoicePoll) {\n return (\n <PostPollLayoutOne\n isInboxCard={isInboxCard}\n onVotePress={onVotePress}\n items={items}\n voteResult={voteResult}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n isPostOwner={isPostOwner}\n />\n )\n }\n\n if (items.length >= 2 && items.length <= 4) {\n return (\n <PostPollLayoutGrid\n onVotePress={onVotePress}\n items={items}\n voteResult={voteResult}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n isPostOwner={isPostOwner}\n />\n )\n }\n\n return null\n}\n\nexport default PostPollView\n","import React from 'react'\nimport TruncateText from '../resolver/TruncateText'\nimport AutoLink from './AutoLink'\nimport type { TextItemContent } from '../resolver/postContentResolver'\nimport type { MentionData } from '../types'\n\ninterface Props {\n textItems: TextItemContent['items']\n showFullText: boolean\n isPostDetail: boolean\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n}\n\nconst PostTextItem: React.FC<Props> = ({\n textItems,\n showFullText,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n}) => {\n return (\n <div className=\"flex-1\">\n <div>\n {textItems.map((item, index) => {\n const text = 'text' in item ? (item.text ?? '') : ''\n const key = 'key' in item ? item.key : index\n const mentionData =\n 'mentionData' in item\n ? (item.mentionData as MentionData[])\n : undefined\n return (\n <AutoLink\n key={key}\n text={showFullText ? text : TruncateText(text, 300)}\n mentionData={mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n />\n )\n })}\n </div>\n </div>\n )\n}\n\nexport default PostTextItem\n","import React, { useState } from 'react'\nimport { cn } from '../utils/cn'\nimport AppIcon from './AppIcon'\nimport { LinkItemMetaData } from '../types'\n\n// Helper to extract host from URL\nconst getHostFromUrl = (url?: string): string => {\n if (!url) return ''\n try {\n return new URL(url).host\n } catch {\n return url\n }\n}\n\n// Helper to determine link rel attribute\nconst getLinkRel = (\n host: string,\n supportDeepviewDomain: string | string[] = ''\n): string => {\n const domains = Array.isArray(supportDeepviewDomain)\n ? supportDeepviewDomain\n : supportDeepviewDomain\n ? [supportDeepviewDomain]\n : []\n const isInternal = domains.some((d) => d.length > 0 && host.includes(d))\n return isInternal ? 'noreferrer' : 'noreferrer nofollow'\n}\n\ninterface PostLinkItemProps {\n linkItems: LinkItemMetaData[]\n imageComponent?: React.ComponentType<{ src: string; alt: string; className?: string }>\n onCloseClick?: () => void\n type?: 'preview' | 'display'\n supportDeepviewDomain?: string | string[]\n}\n\nconst PostLinkItem: React.FC<PostLinkItemProps> = ({\n linkItems,\n imageComponent: ImageComponent,\n onCloseClick,\n type = 'display',\n supportDeepviewDomain = '',\n}) => {\n const [imageError, setImageError] = useState(false)\n\n if (linkItems.length === 0) {\n return null\n }\n\n const { linkUrl, linkTitle, linkDesc, linkImage } = linkItems[0] || {}\n const host = getHostFromUrl(linkUrl)\n const linkRel = getLinkRel(host, supportDeepviewDomain)\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n if (linkUrl) window.open(linkUrl, '_blank', 'noopener,noreferrer')\n }\n\n // Render image (with fallback to plain img if no imageComponent provided)\n const renderImage = (\n src: string,\n alt: string,\n aspectClassName: string,\n containerClassName: string\n ) => {\n if (imageError || !src) return null\n\n return (\n <div className={containerClassName}>\n <div className={aspectClassName}>\n {ImageComponent ? (\n <ImageComponent\n src={src}\n alt={alt}\n className=\"w-full h-full object-cover rounded-t-md\"\n />\n ) : (\n <img\n src={src}\n alt={alt}\n className=\"w-full h-full object-cover rounded-t-md\"\n onError={() => setImageError(true)}\n />\n )}\n </div>\n </div>\n )\n }\n\n // Legacy card style — used in comments\n if (type === 'preview') {\n const aspectRatio =\n linkImage &&\n linkImage.height > linkImage.width &&\n linkImage.height / linkImage.width > 0.7\n ? 'aspect-[0.7]'\n : 'aspect-video'\n\n return (\n <section\n className=\"not-prose min-w-96 relative cursor-pointer rounded-lg border border-border bg-background\"\n onClick={handleClick}\n role=\"link\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick(e as unknown as React.MouseEvent)\n }\n }}\n >\n {linkImage?.url && !imageError && (\n <div className=\"relative w-full\">\n {ImageComponent ? (\n <div className={`relative w-full ${aspectRatio}`}>\n <ImageComponent\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover rounded-t-md\"\n />\n </div>\n ) : (\n <div className={`relative w-full ${aspectRatio}`}>\n <img\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover rounded-t-md\"\n onError={() => setImageError(true)}\n />\n </div>\n )}\n </div>\n )}\n {typeof onCloseClick === 'function' && (\n <AppIcon\n name=\"cancel\"\n onClick={(e) => {\n e.stopPropagation()\n onCloseClick()\n }}\n className=\"absolute -right-2 -top-3 rounded-full bg-background size-4.5 hover:cursor-pointer hover:opacity-70\"\n />\n )}\n <section className=\"flex flex-col gap-1 p-3\">\n <a href={linkUrl} className=\"hidden\" rel={linkRel} tabIndex={-1} />\n <p\n className=\"wrap-break-word text-xs font-normal leading-4 text-muted-foreground\"\n data-test-id=\"post-link-host\"\n >\n {host}\n </p>\n <p\n className=\"text-clip-1 text-ellipsis wrap-break-word text-base leading-6\"\n data-test-id=\"post-link-title\"\n >\n {linkTitle}\n </p>\n <p\n className=\"text-clip-2 text-ellipsis wrap-break-word text-xs font-normal leading-5 tracking-tight text-muted-foreground\"\n data-test-id=\"post-link-desc\"\n >\n {linkDesc}\n </p>\n </section>\n </section>\n )\n }\n\n // New overlay style — used in posts and embed fallbacks\n return (\n <section\n className={cn('not-prose relative cursor-pointer group overflow-hidden')}\n onClick={handleClick}\n role=\"link\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick(e as unknown as React.MouseEvent)\n }\n }}\n >\n <div className=\"aspect-video relative\">\n <div className=\"max-w-200 max-h-100 size-full relative\">\n {linkImage?.url && !imageError && (\n <>\n {ImageComponent ? (\n <ImageComponent\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover transition-transform duration-700 group-hover:scale-105\"\n />\n ) : (\n <img\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover transition-transform duration-700 group-hover:scale-105\"\n onError={() => setImageError(true)}\n />\n )}\n </>\n )}\n </div>\n <div className=\"absolute inset-0 bg-linear-to-t from-black/90 via-black/40 to-transparent opacity-90 group-hover:opacity-100 transition-opacity\"></div>\n {typeof onCloseClick === 'function' && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onCloseClick()\n }}\n className=\"absolute top-2 right-2 bg-black/40 text-white rounded-full p-1 hover:bg-black/60 cursor-pointer border-none flex items-center justify-center transition-colors shadow-sm z-10\"\n aria-label=\"Remove link preview\"\n >\n <AppIcon name=\"cancel\" size={16} strokeWidth={2} />\n </button>\n )}\n <div className=\"absolute bottom-0 left-0 right-0 p-5 transform transition-transform duration-300 z-10 pointer-events-none\">\n <a\n href={linkUrl}\n className=\"hidden pointer-events-auto\"\n rel={linkRel}\n tabIndex={-1}\n />\n <div className=\"flex items-center gap-2 text-xs text-white/70 mb-2\">\n <AppIcon name=\"externalLink\" className=\"w-3.5 h-3.5\" />\n <span className=\"uppercase tracking-wider font-medium\">{host}</span>\n </div>\n <h3 className=\"font-semibold text-white text-xl leading-tight mb-1.5 group-hover:text-action-primary transition-colors line-clamp-2\">\n {linkTitle}\n </h3>\n {linkDesc && (\n <p className=\"text-white/70 text-sm line-clamp-2\">{linkDesc}</p>\n )}\n </div>\n </div>\n </section>\n )\n}\n\nexport default PostLinkItem\n","import React, { useMemo, useState } from 'react'\nimport PostLinkItem from './PostLinkItem'\nimport type { EmbedContent } from '../resolver/postContentResolver'\nimport { SPOTIFY_HEIGHT } from '../resolver/constants/embeds'\n\ninterface Props {\n embed: EmbedContent\n}\n\nconst TRUSTED_HOSTS: Record<string, string[]> = {\n youtube: ['www.youtube.com', 'youtube.com'],\n spotify: ['open.spotify.com'],\n}\n\nconst isTrustedEmbedUrl = (provider: string, url: string) => {\n try {\n const u = new URL(url)\n if (u.protocol !== 'https:') return false\n const allowed = TRUSTED_HOSTS[provider] ?? []\n return allowed.includes(u.hostname.toLowerCase())\n } catch {\n return false\n }\n}\n\nconst PostEmbedView: React.FC<Props> = ({ embed }) => {\n const [hasError, setHasError] = useState(false)\n\n const canRender = useMemo(() => {\n return (\n !hasError &&\n !!embed.embedUrl &&\n isTrustedEmbedUrl(embed.provider, embed.embedUrl)\n )\n }, [hasError, embed.embedUrl, embed.provider])\n\n const linkItem = {\n linkUrl: embed.originalUrl,\n linkTitle: embed.preview?.title || embed.originalUrl,\n linkDesc: embed.preview?.description || '',\n linkImage: embed.preview?.image ?? undefined,\n linkIcon: '',\n type: 'linkItem',\n } as const\n\n if (!canRender) return <PostLinkItem linkItems={[linkItem]} />\n\n const isYouTube = embed.provider === 'youtube'\n const isSpotify = embed.provider === 'spotify'\n\n return (\n <div className=\"w-full px-4 pb-4 not-first:pt-4\">\n <div\n className=\"relative w-full overflow-hidden rounded-xl\"\n style={{ height: embed.height || SPOTIFY_HEIGHT }}\n >\n <iframe\n src={embed.embedUrl}\n className=\"absolute inset-0 h-full w-full\"\n loading=\"lazy\"\n sandbox=\"allow-scripts allow-same-origin allow-presentation\"\n allow={\n isYouTube\n ? 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n : isSpotify\n ? 'autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture'\n : ''\n }\n allowFullScreen={isYouTube}\n referrerPolicy=\"no-referrer-when-downgrade\"\n title={embed.preview?.title || `${embed.provider} embed`}\n style={{ border: 0 }}\n onError={() => setHasError(true)}\n />\n </div>\n </div>\n )\n}\n\nexport default PostEmbedView\n","import React from 'react'\nimport type { MediaUploadStatus } from '../../types'\nimport AppIcon from '../AppIcon'\n\ninterface Props {\n status?: MediaUploadStatus\n /** Tile width in px. Status text is hidden when < 100. */\n tileWidth?: number\n}\n\nconst MediaUploadStatusOverlay: React.FC<Props> = ({ status, tileWidth }) => {\n if (!status) return null\n\n const showText = !tileWidth || tileWidth >= 100\n\n if (status === 'uploading' || status === 'processing') {\n return (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 bg-overlay-scrim\">\n <AppIcon name=\"loader\" className=\"size-6 animate-spin text-background\" />\n {showText && (\n <span className=\"text-xs font-medium text-background\">\n {status === 'uploading' ? 'Uploading' : 'Processing'}\n </span>\n )}\n </div>\n )\n }\n\n if (status === 'uploaded') {\n return (\n <div className=\"absolute inset-0 flex items-center justify-center bg-feedback-success/15\">\n <div className=\"flex size-8 items-center justify-center rounded-full bg-foreground/60\">\n <AppIcon name=\"check\" className=\"size-5 text-background\" />\n </div>\n </div>\n )\n }\n\n // status === 'error'\n return (\n <div className=\"absolute inset-0 flex items-center justify-center bg-feedback-danger/20\">\n <div className=\"flex size-8 items-center justify-center rounded-full bg-foreground/60\">\n <span className=\"text-base font-bold text-background\">!</span>\n </div>\n </div>\n )\n}\n\nexport default MediaUploadStatusOverlay\n","import React from 'react'\nimport type { ItemData, MediaUploadStatus } from '../../types'\nimport MediaView from '../MediaView'\nimport MediaUploadStatusOverlay from './MediaUploadStatusOverlay'\n\n// Types\ninterface PostMediaLayoutProps {\n items: ItemData[]\n parentId?: string\n isPostDetail?: boolean\n onCardPress?: () => void\n mediaItemStatuses?: Record<string, MediaUploadStatus>\n}\n\ninterface GridLayout {\n gridColsClass: string\n gridSpan: number[]\n colSpanClasses: string[]\n itemRatio: number[]\n}\n\nconst gridLayoutData: Record<number, GridLayout> = {\n 1: {\n gridColsClass: 'grid-cols-1',\n gridSpan: [1],\n colSpanClasses: ['col-span-1'],\n itemRatio: [1],\n },\n 2: {\n gridColsClass: 'grid-cols-2',\n gridSpan: [1, 1],\n colSpanClasses: ['col-span-1', 'col-span-1'],\n itemRatio: [1, 1],\n },\n 3: {\n gridColsClass: 'grid-cols-2',\n gridSpan: [2, 1, 1],\n colSpanClasses: ['col-span-2', 'col-span-1', 'col-span-1'],\n itemRatio: [1.5, 1.5, 1.5],\n },\n 4: {\n gridColsClass: 'grid-cols-2',\n gridSpan: [1, 1, 1, 1],\n colSpanClasses: ['col-span-1', 'col-span-1', 'col-span-1', 'col-span-1'],\n itemRatio: [1, 1, 1, 1],\n },\n 5: {\n gridColsClass: 'grid-cols-6',\n gridSpan: [3, 3, 2, 2, 2],\n colSpanClasses: [\n 'col-span-3',\n 'col-span-3',\n 'col-span-2',\n 'col-span-2',\n 'col-span-2',\n ],\n itemRatio: [1.5, 1.5, 1, 1, 1],\n },\n}\n\nexport const PostMediaLayoutCore: React.FC<PostMediaLayoutProps> = ({\n items,\n parentId: _parentId,\n isPostDetail,\n onCardPress,\n mediaItemStatuses,\n}) => {\n if (!items?.length) {\n return null\n }\n\n const slicedData = items.slice(0, 5)\n const { gridColsClass, colSpanClasses, itemRatio } =\n gridLayoutData[slicedData.length]\n\n return (\n <div className=\"not-prose w-full box-border\">\n <div\n className={`grid ${gridColsClass} cursor-pointer grid-rows-1 gap-0.5 bg-muted`}\n >\n {slicedData.map((slicedItem, index) => {\n let ratio = 1\n if (slicedData.length === 1) {\n const { width, height } = slicedItem.type.includes('ToUpload')\n ? (slicedItem.file as any)\n : (slicedItem.sources?.original ?? {})\n\n const safeWidth = width ?? 1\n const safeHeight = height ?? 1\n\n ratio = safeWidth / safeHeight\n if (ratio < 0.7) {\n ratio = 0.7\n }\n } else {\n ratio = itemRatio[index]\n }\n\n const className = `w-full h-full relative ${colSpanClasses[index]} object-cover`\n return (\n <div key={index} className={`relative ${colSpanClasses[index]}`}>\n <MediaView\n item={slicedItem}\n ratio={ratio}\n className={className}\n additionalImagesCount={\n index === slicedData.length - 1 && items.length > 5\n ? items.length - slicedData.length\n : undefined\n }\n data={items}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n />\n <MediaUploadStatusOverlay\n status={mediaItemStatuses?.[slicedItem.key]}\n />\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n\nexport default PostMediaLayoutCore\n","import React from 'react'\nimport type { PollItemData, MediaUploadStatus } from '../types'\nimport PostPollView from './PostPollView'\nimport PostTextItem from './PostTextItem'\nimport PostLinkItem from './PostLinkItem'\nimport PostEmbedView from './PostEmbedView'\nimport PostMediaLayout from './PostMediaLayout/PostMediaLayoutCore'\nimport type { PrimaryContent } from '../resolver/postContentResolver'\n\ninterface Props {\n primaryContent: PrimaryContent\n isPostDetail: boolean\n onCardPress: () => void\n onVotePress: (item: PollItemData) => void\n isPostOwner?: boolean\n parentId?: string\n isCommentScope?: boolean\n imageComponent?: React.ComponentType<{ src: string; alt: string; className?: string }>\n mediaItemStatuses?: Record<string, MediaUploadStatus>\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n}\n\nconst PostItemsView: React.FC<Props> = ({\n primaryContent,\n isPostDetail,\n onCardPress,\n onVotePress,\n isPostOwner,\n parentId,\n isCommentScope,\n imageComponent,\n mediaItemStatuses,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n}) => {\n if (!primaryContent) return null\n\n switch (primaryContent.type) {\n case 'embed':\n return <PostEmbedView embed={primaryContent} />\n\n case 'poll':\n return (\n <PostPollView\n items={primaryContent.items}\n voteResult={primaryContent.pollResult}\n onVotePress={onVotePress}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n isPostOwner={isPostOwner}\n />\n )\n\n case 'link':\n return (\n <PostLinkItem\n linkItems={[\n {\n linkUrl: primaryContent.linkUrl,\n linkTitle: primaryContent.title,\n linkDesc: primaryContent.description,\n linkImage: primaryContent.image ?? undefined,\n linkIcon: '',\n type: 'linkItem',\n },\n ]}\n imageComponent={imageComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )\n\n case 'media':\n return (\n <PostMediaLayout\n items={primaryContent.items}\n parentId={parentId}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n mediaItemStatuses={mediaItemStatuses}\n />\n )\n\n case 'textItem':\n return (\n <PostTextItem\n textItems={primaryContent.items}\n showFullText={isPostDetail}\n isPostDetail={isPostDetail}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )\n\n default:\n return null\n }\n}\n\nexport default PostItemsView\n","import React, { useCallback } from 'react'\nimport { contentTypeConstants } from '../utils/contentTypeConstants'\nimport AutoLink from './AutoLink'\nimport PostSectionSourceInfoView from './PostSectionSourceInfoView'\nimport PostMediaLayout from './PostMediaLayout/PostMediaLayoutCore'\nimport type { SectionItem } from '../resolver/postContentResolver'\n\ninterface Props {\n sections: SectionItem[]\n isPostDetail: boolean\n onCardPress: () => void\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n imageComponent?: React.ComponentType<{\n src: string\n alt: string\n fill?: boolean\n placeholder?: 'blur' | 'empty'\n blurDataURL?: string\n priority?: boolean\n className?: string\n }>\n}\n\nconst PostSectionsView: React.FC<Props> = ({\n sections,\n isPostDetail,\n onCardPress,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n imageComponent,\n}) => {\n const renderSectionItem = useCallback(\n (section: SectionItem, index: number) => {\n const { type, data } = section\n if (type === contentTypeConstants.NEW_POST_MESSAGE) {\n return (\n <AutoLink\n key={`${index} - ${data.body}`}\n text={data.body || ''}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={data.mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )\n }\n if (type === contentTypeConstants.NEW_POST_MEDIA) {\n return (\n <div key={`${index} - ${data.body}`} className=\"my-3\">\n {data.sourceInfo && (\n <PostSectionSourceInfoView\n sourceInfo={data.sourceInfo}\n imageComponent={imageComponent}\n />\n )}\n {data.body && (\n <AutoLink\n key={`${index} - ${data.body}`}\n text={data.body || ''}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={data.mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )}\n {data.items && (\n <PostMediaLayout\n items={data.items}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n />\n )}\n </div>\n )\n }\n return null\n },\n [isPostDetail, onCardPress, onNavigate, supportDeepviewDomain, imageComponent]\n )\n\n if (!sections || sections.length === 0) {\n return null\n }\n\n return (\n <div className=\"space-y-2\">\n {sections.map((section, index) => {\n return renderSectionItem(section, index)\n })}\n </div>\n )\n}\n\nexport default PostSectionsView\n","// Verbatim port of contentTypeConstants (and its dependency contentTypeRules)\n// from web client src/Constants.ts\n// These values must match the backend exactly — do not rename or change values.\n\nconst contentTypeRules = {\n NEW_MESSAGE: 'new:message',\n NEW_POST: 'new:post',\n NEW_COMMENT: 'new:comment',\n EVENT: 'event',\n} as const\n\nexport const contentTypeConstants = {\n TO_BE_DELETE: 'tobedelete',\n NEW_GROUP: 'new:group',\n LOAD_MORE_CONTENT: 'loadMoreContent',\n NEW_MESSAGE: `${contentTypeRules.NEW_MESSAGE}:text`,\n NEW_MESSAGE_GUGGY: `${contentTypeRules.NEW_MESSAGE}:gif`,\n NEW_MESSAGE_VOICE: `${contentTypeRules.NEW_MESSAGE}:voice`,\n NEW_POST_IMAGE: `${contentTypeRules.NEW_POST}:image`,\n NEW_POST_MEDIA: `${contentTypeRules.NEW_POST}:media`,\n NEW_POST_POLL: `${contentTypeRules.NEW_POST}:poll`,\n NEW_POST_LINK: `${contentTypeRules.NEW_POST}:link`,\n NEW_POST_MESSAGE: `${contentTypeRules.NEW_POST}:text`,\n NEW_POST_THREAD: `${contentTypeRules.NEW_POST}:thread`,\n NEW_COMMENT: `${contentTypeRules.NEW_COMMENT}`,\n NEW_COMMENT_GUGGY: `${contentTypeRules.NEW_COMMENT}:gif`,\n NEW_COMMENT_VOICE: `${contentTypeRules.NEW_COMMENT}:voice`,\n NEW_COMMENT_IMAGE: `${contentTypeRules.NEW_COMMENT}:image`,\n NEW_COMMENT_MEDIA: `${contentTypeRules.NEW_COMMENT}:media`,\n ERASE_MESSAGE: 'erase:message',\n EVENT_POLL_VOTE: 'event:poll:vote',\n EVENT_NEW_GREETING_POST: 'event:greeting:post',\n EVENT_UPDATE_GROUP: 'event:update:group',\n EVENT_ERASE_GROUP_CONTENT: 'event:erase:group:content',\n EVENT_ERASE_GROUP_COMMENT: 'event:erase:group:comment',\n EVENT_NOT_A_CONTACT: 'event:not:contact',\n EVENT_SCREENSHOT: 'event:screenshot',\n EVENT_COMMENT_SCREENSHOT: 'event:comment:screenshot',\n EVENT_TOAST_CONVERSATION: 'event:toast:conversation',\n EVENT_TOAST_POST: 'event:toast:post',\n UPDATE_GROUP_NAME: 'group:update:name',\n UPDATE_GROUP_DESCRIPTION: 'group:update:description',\n UPDATE_GROUP_BACKGROUND: 'group:update:background',\n UPDATE_GROUP_DEFAULT_DEEPLINK: 'group:update:default_deeplink',\n UPDATE_GROUP_AVATAR: 'group:update:avatar',\n UPDATE_GROUP_NEW_USERS: 'group:new:users',\n UPDATE_GROUP_REMOVE_USERS: 'group:remove:users',\n UPDATE_GROUP_USER_LEAVE: 'group:remove:users:leave',\n UPDATE_GROUP_NEW_OWNER: 'group:new:owner',\n UPDATE_GROUP_SELECT_ID: 'group:update:select_id',\n UPDATE_GROUP_SHOW_HISTORY: 'group:update:show_history',\n UPDATE_GROUP_SHARE_TO_PUBLIC: 'group:update:share_to_public',\n UPDATE_GROUP_PERMISSION: 'group:update:permission',\n UPDATE_GROUP_NEW_FEATURED: 'group:new:featured',\n UPDATE_GROUP_FEATURED_IN_GROUP: 'group:featured:in:group',\n UPDATE_GROUP_FEATURED_BY_USER: 'group:featured:by:user',\n UPDATE_RELATIONSHIP: 'update:relationship',\n NEW_GROUP_REQUEST: 'group:request:new',\n NEW_GROUP_REQUEST_ACCEPTED: 'group:request:accepted',\n REMOVE_GROUP_ADMIN: 'group:remove:admin',\n ADD_GROUP_ADMIN: 'group:new:admin',\n UPDATE_CONTENT: 'update:content',\n NEW_GROUP_REQUEST_REMOVE: 'group:request:removed',\n AGGREGATED_MESSAGE_TIME: 'aggregated:message:time',\n REQUEST_IMAGE_DOWNLOAD: 'request:image:download',\n} as const\n","import React from 'react'\nimport { Avatar, AvatarImage, AvatarFallback } from '@select-org/ui'\n\ninterface Props {\n sourceInfo?: {\n avatar: string\n username: string\n url: string\n }\n imageComponent?: React.ComponentType<{\n src: string\n alt: string\n fill?: boolean\n placeholder?: 'blur' | 'empty'\n blurDataURL?: string\n priority?: boolean\n className?: string\n }>\n}\n\nconst PostSectionSourceInfoView: React.FC<Props> = ({\n sourceInfo,\n imageComponent,\n}) => {\n if (!sourceInfo) {\n return null\n }\n\n return (\n <div className=\"mx-4 mb-3 mt-3 border-b border-gray-100 pb-3\">\n <div className=\"flex flex-row items-center\">\n {/* Use the DS Avatar (same as PostHeader) so the source avatar gets the\n shared circular shape, the imageComponent seam, and the initials-based\n fallback (initials lib + deterministic colour) — matching the original\n web AvatarCard with initials. */}\n <Avatar size=\"sm\" className=\"shrink-0 ring-1 ring-border-subtle\">\n <AvatarImage\n src={sourceInfo.avatar}\n alt={sourceInfo.username}\n imageComponent={imageComponent}\n />\n <AvatarFallback name={sourceInfo.username} className=\"text-xs\" />\n </Avatar>\n <div className=\"ml-2 flex-col justify-center flex\">\n <div className=\"text-sm font-semibold text-foreground leading-none\">\n {sourceInfo.username}\n </div>\n <div className=\"text-xs text-muted-foreground mt-1 leading-none\">\n {sourceInfo.url}\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default PostSectionSourceInfoView\n","import React, { useState } from 'react'\nimport { NotificationBadge } from '@select-org/ui'\nimport { cn } from '../utils/cn'\nimport AppIcon from './AppIcon'\n\ninterface PostFooterProps {\n postHref?: string\n commentCount?: number\n unreadCommentCount?: number\n showFooterLink?: boolean\n footerLinkLabel?: string\n footerLinkHref?: string\n isSnoozed?: boolean\n onSnoozeToggle?: () => void\n /**\n * Custom link renderer (e.g. Next.js `<Link>`) for the comment and footer\n * links. Falls back to a native `<a>`. Passing this is important inside SPAs:\n * a native `<a>` triggers a full-page reload, whereas the consumer's router\n * link performs a soft client-side navigation.\n */\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n renderReactionTrigger?: (props: { onOpen: () => void }) => React.ReactNode\n renderReactionModal?: (props: {\n isOpen: boolean\n onClose: () => void\n onSend: (emoji: string) => void\n }) => React.ReactNode\n}\n\nconst PostFooter: React.FC<PostFooterProps> = ({\n postHref,\n commentCount = 0,\n unreadCommentCount = 0,\n showFooterLink = false,\n footerLinkLabel = 'Open in app',\n footerLinkHref = '/',\n isSnoozed = false,\n onSnoozeToggle,\n linkComponent: LinkComponent,\n renderReactionTrigger,\n renderReactionModal,\n}) => {\n const [isReactionOpen, setIsReactionOpen] = useState(false)\n\n const handleOpen = () => setIsReactionOpen(true)\n const handleClose = () => setIsReactionOpen(false)\n\n const commentButtonClass =\n 'relative text-muted-foreground hover:text-foreground hover:bg-muted p-2 rounded-full transition-all flex items-center justify-center cursor-pointer bg-transparent border-none select-none'\n\n const commentAriaLabel = `View comments${commentCount > 0 ? `, ${commentCount} comment${commentCount !== 1 ? 's' : ''}` : ''}`\n\n const commentBadge =\n commentCount > 0 ? (\n <span className=\"absolute top-0 right-0 -mt-0.5 -mr-0.5\">\n <NotificationBadge\n count={unreadCommentCount > 0 ? unreadCommentCount : commentCount}\n variant={unreadCommentCount > 0 ? 'solid' : 'neutral'}\n size=\"sm\"\n className=\"ring-2 ring-background\"\n />\n </span>\n ) : null\n\n return (\n <section className=\"flex items-center justify-between p-2 px-4 border-t border-border/50\">\n <div className=\"relative flex items-center gap-1\">\n {renderReactionTrigger ? (\n renderReactionTrigger({ onOpen: handleOpen })\n ) : (\n <button\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n handleOpen()\n }}\n className=\"text-muted-foreground hover:text-foreground hover:bg-muted p-2 rounded-full transition-all cursor-pointer bg-transparent border-none select-none\"\n aria-label=\"Add reaction\"\n aria-expanded={isReactionOpen}\n aria-haspopup=\"true\"\n >\n <AppIcon name=\"sendEmoji\" aria-hidden=\"true\" />\n </button>\n )}\n\n {onSnoozeToggle && (\n <button\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n onSnoozeToggle()\n }}\n className={cn(\n 'p-2 rounded-full hover:bg-muted transition-all cursor-pointer bg-transparent border-none select-none',\n isSnoozed\n ? 'text-feedback-warning'\n : 'text-muted-foreground hover:text-foreground'\n )}\n aria-label={isSnoozed ? 'Unsnooze post' : 'Snooze post'}\n title={isSnoozed ? 'Unsnooze post' : 'Snooze post (30 min)'}\n >\n <AppIcon name=\"alarmClock\" />\n </button>\n )}\n\n {renderReactionModal && (\n <div className=\"z-50 absolute bottom-full left-0 mb-2\">\n {renderReactionModal({\n isOpen: isReactionOpen,\n onClose: handleClose,\n onSend: (emoji: string) => {\n handleClose()\n },\n })}\n </div>\n )}\n </div>\n\n {/* The comment icon is purely a \"view comments\" navigation affordance.\n Without a postHref there's nowhere to go (e.g. the post-detail page,\n which is the destination), so render nothing rather than a dead,\n non-interactive icon button. */}\n {postHref && (\n <div className=\"relative flex items-center ml-auto\">\n {LinkComponent ? (\n <LinkComponent\n href={postHref}\n className={cn(commentButtonClass, 'no-underline')}\n >\n <AppIcon name=\"messageCircleMore\" aria-hidden=\"true\" />\n {/* The LinkComponent contract takes no aria-label, and this link\n is icon-only — provide an accessible name via sr-only text. */}\n <span className=\"sr-only\">{commentAriaLabel}</span>\n {commentBadge}\n </LinkComponent>\n ) : (\n <a\n href={postHref}\n className={cn(commentButtonClass, 'no-underline')}\n onClick={(e) => {\n e.stopPropagation()\n }}\n aria-label={commentAriaLabel}\n >\n <AppIcon name=\"messageCircleMore\" aria-hidden=\"true\" />\n {commentBadge}\n </a>\n )}\n </div>\n )}\n\n {showFooterLink &&\n (() => {\n const footerLinkClass =\n 'bg-action-primary/5 hover:bg-action-primary/10 transition-colors w-full text-center py-3 text-sm font-medium text-action-primary no-underline rounded-b-xl border-t border-action-primary/10'\n return (\n <section className=\"flex justify-center -mx-5 -mb-2.5 mt-2.5\">\n {LinkComponent ? (\n <LinkComponent href={footerLinkHref} className={footerLinkClass}>\n {footerLinkLabel}\n </LinkComponent>\n ) : (\n <a href={footerLinkHref} className={footerLinkClass}>\n {footerLinkLabel}\n </a>\n )}\n </section>\n )\n })()}\n </section>\n )\n}\n\nexport default PostFooter\n","import type { MediaUploadStatus } from '../../types'\n\nexport interface UploadStats {\n inFlight: number\n done: number\n failed: number\n total: number\n}\n\n/**\n * Count per-item upload statuses into an aggregate for the upload strip.\n * `uploading` and `processing` both count as in-flight; `total` is the sum\n * of the three buckets (entries with no recognized status are ignored).\n */\nexport function deriveUploadStats(\n statuses: Record<string, MediaUploadStatus> | undefined\n): UploadStats {\n let inFlight = 0\n let done = 0\n let failed = 0\n for (const s of Object.values(statuses ?? {})) {\n if (s === 'uploading' || s === 'processing') inFlight++\n else if (s === 'uploaded') done++\n else if (s === 'error') failed++\n }\n return { inFlight, done, failed, total: inFlight + done + failed }\n}\n","import React from 'react'\nimport { cn } from '../utils/cn'\nimport AppIcon from './AppIcon'\nimport type { MediaUploadStatus } from '../types'\nimport { deriveUploadStats } from './PostMediaLayout/uploadStats'\n\ninterface Props {\n statuses?: Record<string, MediaUploadStatus>\n labels?: {\n /** Template with `{count}` replaced by the remaining in-flight number. */\n uploadingRemaining?: string\n /** Shown when nothing is in flight but failures remain. */\n uploadingDone?: string\n }\n}\n\nconst PostUploadStrip: React.FC<Props> = ({ statuses, labels }) => {\n const stats = deriveUploadStats(statuses)\n\n // Meaningful only while uploads are in flight or have failed.\n if (stats.total === 0) return null\n if (stats.inFlight === 0 && stats.failed === 0) return null\n\n const hasError = stats.failed > 0\n const remaining = stats.inFlight\n\n const remainingTemplate = labels?.uploadingRemaining ?? 'Uploading {count} more'\n const doneLabel = labels?.uploadingDone ?? 'All uploaded'\n const progressLabel =\n remaining > 0\n ? remainingTemplate.replace('{count}', String(remaining))\n : doneLabel\n\n return (\n <div\n className={cn(\n 'not-prose flex items-center gap-2.5 border-t border-border px-5 py-2.5',\n hasError ? 'bg-feedback-danger/8' : 'bg-feedback-info/8'\n )}\n >\n {remaining > 0 ? (\n <AppIcon\n name=\"loader\"\n className={cn(\n 'size-4 shrink-0 animate-spin',\n hasError ? 'text-feedback-danger' : 'text-feedback-info'\n )}\n />\n ) : (\n <AppIcon\n name=\"triangleAlert\"\n className=\"size-4 shrink-0 text-feedback-danger\"\n />\n )}\n <span\n className={cn(\n 'truncate text-xs font-medium',\n hasError ? 'text-feedback-danger' : 'text-feedback-info'\n )}\n >\n {progressLabel}\n </span>\n <span\n className={cn(\n 'ml-auto shrink-0 text-[11px]',\n hasError ? 'text-feedback-danger/80' : 'text-feedback-info/80'\n )}\n >\n {stats.done} / {stats.total}\n {hasError && ` · ${stats.failed} failed`}\n </span>\n </div>\n )\n}\n\nexport default PostUploadStrip\n","import React, { useEffect, useState } from 'react'\nimport AppIcon from './AppIcon'\n\ninterface Props {\n backgroundColor?: string\n onYesPress: (e?: React.MouseEvent) => void\n onNoPress: (e?: React.MouseEvent) => void\n fontColor?: string\n itemType?: string\n isOpen: boolean\n handleClose: () => void\n}\n\nconst EraseConfirmModal: React.FC<Props> = ({\n onYesPress,\n onNoPress,\n itemType = 'comment',\n isOpen,\n handleClose,\n}) => {\n const [first, setFirst] = useState(true)\n const [second, setSecond] = useState(false)\n\n // Lock scroll and handle Escape key when open\n useEffect(() => {\n if (!isOpen) return\n const closeOnEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') handleClose()\n }\n document.body.addEventListener('keydown', closeOnEscape)\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n document.body.style.overflow = 'hidden'\n document.body.style.paddingRight = `${scrollbarWidth}px`\n return () => {\n document.body.removeEventListener('keydown', closeOnEscape)\n document.body.style.overflow = ''\n document.body.style.paddingRight = ''\n }\n }, [isOpen, handleClose])\n\n if (!isOpen) return null\n\n const handleFirst = (e: React.MouseEvent) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n setFirst(false)\n setSecond(true)\n }\n\n const handleNoPress = (e: React.MouseEvent) => {\n onNoPress(e)\n setFirst(true)\n setSecond(false)\n }\n\n const eraseLabel = itemType === 'Post' ? 'Erase post' : 'Erase comment'\n const confirmTitle =\n itemType === 'Post'\n ? 'Are you sure you want to erase this post?'\n : 'Are you sure you want to erase this comment?'\n const confirmBody =\n itemType === 'Post'\n ? 'This action cannot be undone.'\n : 'This action cannot be undone.'\n\n return (\n <div>\n {/* Backdrop */}\n <div className=\"fixed left-0 top-0 z-50 h-screen w-full bg-black/50\" />\n {/* Modal container */}\n <div\n className=\"fixed left-0 top-0 z-50 flex h-screen w-full items-center justify-center p-4\"\n onClick={(e) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n }}\n >\n <div className=\"rounded-3xl bg-background px-8 py-6 text-center shadow-3\">\n {first && (\n <div\n className=\"flex w-[256px] flex-col justify-around\"\n onClick={(e) => e.stopPropagation()}\n >\n <div\n className=\"mb-4 flex flex-row items-center hover:cursor-pointer hover:opacity-50\"\n data-testid=\"modal-erase-post\"\n onClick={(e) => handleFirst(e)}\n >\n <div>\n <AppIcon name=\"chatErase\" className=\"size-7.5 cursor-pointer\" />\n </div>\n <p className=\"ml-3 text-lg\">{eraseLabel}</p>\n </div>\n <div\n className=\"flex flex-row items-center hover:cursor-pointer hover:opacity-50\"\n onClick={handleNoPress}\n >\n <div>\n <AppIcon name=\"cancel\" className=\"cursor-pointer size-6\" />\n </div>\n <p className=\"ml-3 text-lg\">Cancel</p>\n </div>\n </div>\n )}\n {second && (\n <div\n onClick={(e) => e.stopPropagation()}\n className=\"flex w-[296px] flex-col items-center justify-around\"\n >\n <div className=\"mb-4\">\n <h4 className=\"mb-2 text-lg font-bold\">{confirmTitle}</h4>\n <p className=\"text-muted-foreground\">{confirmBody}</p>\n </div>\n <div className=\"flex items-center justify-around\">\n <button\n className=\"mr-6 py-2 text-muted-foreground\"\n onClick={handleNoPress}\n >\n Cancel\n </button>\n <button\n className=\"rounded-3xl bg-action-primary px-6 py-2 font-semibold text-white\"\n onClick={onYesPress}\n data-testid=\"confirm-modal-erase\"\n >\n Erase\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n\nexport default EraseConfirmModal\n","import React, { useCallback, useMemo } from 'react'\nimport { contentTypeConstants } from '../utils/contentTypeConstants'\nimport AutoLink from './AutoLink'\nimport PostMediaLayout from './PostMediaLayout/PostMediaLayoutCore'\nimport type { ItemData } from '../types'\nimport type { SectionItem } from '../resolver/postContentResolver'\n\ninterface Props {\n fontColor?: string\n sections: SectionItem[]\n onCardPress?: () => void\n}\n\nconst BODY_SIZE = 80\n\nconst PostSectionsSummaryView: React.FC<Props> = ({\n sections,\n fontColor,\n onCardPress,\n}) => {\n const imageItems: ItemData[] = useMemo(() => {\n if (!sections || sections.length === 0) return []\n return sections.reduce((items: ItemData[], section: SectionItem) => {\n if (section.type === contentTypeConstants.NEW_POST_MEDIA) {\n return items.concat((section.data.items as ItemData[]) || [])\n }\n return items\n }, [])\n }, [sections])\n\n const textBody = useMemo(() => {\n if (!sections || sections.length === 0) return ''\n const allBody = sections.reduce((body: string, section: SectionItem) => {\n if (\n section.type === contentTypeConstants.NEW_POST_MEDIA &&\n section.data.body\n ) {\n return body + (body ? '\\n' : '') + section.data.body\n }\n return body\n }, '')\n return allBody ? `${allBody.slice(0, BODY_SIZE)}...` : ''\n }, [sections])\n\n const renderSectionItem = useCallback(\n (section: SectionItem, index: number) => {\n const { type, data } = section\n if (type === contentTypeConstants.NEW_POST_MESSAGE) {\n return (\n <AutoLink\n key={`${index} - ${data.body}`}\n text={data.body || ''}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n color: fontColor || 'var(--color-foreground)',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={data.mentionData}\n />\n )\n }\n return null\n },\n [fontColor]\n )\n\n if (!sections || sections.length === 0) {\n return null\n }\n\n return (\n <div className=\"flex-col\">\n {sections.map((section, index) => {\n return renderSectionItem(section, index)\n })}\n {textBody && (\n <AutoLink\n key=\"body\"\n text={textBody}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n color: fontColor || 'var(--color-foreground)',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={[]}\n />\n )}\n <PostMediaLayout\n items={imageItems}\n />\n </div>\n )\n}\n\nexport default PostSectionsSummaryView\n","import React, { useRef, useEffect } from 'react'\n\ninterface ReactionModalProps {\n isOpen: boolean\n close: () => void\n sendReaction: (emoji: string) => void\n onAnalyticsEvent?: (event: string, data?: Record<string, unknown>) => void\n}\n\nconst reactionList = ['👍', '😍', '😂', '😱', '😭', '😎']\n\nconst ReactionModal = ({ isOpen, close, sendReaction, onAnalyticsEvent }: ReactionModalProps) => {\n const ref = useRef<HTMLDivElement>(null)\n\n // Combined effect for analytics and outside click - only active when modal is open\n useEffect(() => {\n if (!isOpen) return\n\n onAnalyticsEvent?.('reaction')\n\n const handleOutsideClick = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n close()\n }\n }\n document.addEventListener('click', handleOutsideClick)\n return () => {\n document.removeEventListener('click', handleOutsideClick)\n }\n }, [isOpen, close, onAnalyticsEvent])\n\n if (!isOpen) return null\n\n return (\n <div className=\"z-500 flex items-center justify-center\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Reaction picker\">\n <div ref={ref} className=\"rounded-3xl bg-muted p-2\">\n <div className=\"flex justify-around\">\n {reactionList.map((reaction, index) => {\n return (\n <button\n type=\"button\"\n key={reaction + index}\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n onAnalyticsEvent?.('reaction_send')\n sendReaction(reaction)\n close()\n }}\n className=\"cursor-pointer px-2 text-3xl hover:scale-125 transition-transform\"\n >\n {reaction}\n </button>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n\nexport { ReactionModal }\n"],"mappings":"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","names":["React","useMemo","useState","jsx","jsx","className","DOMPurify","useMemo","useMemo","jsx","jsx","jsxs","useMemo","DOMPurify","useMemo","useCallback","useMemo","jsx","jsx","jsxs","useMemo","useCallback","item","jsx","jsxs","useMemo","jsx","jsxs","jsx","nonVoteClassName","voteClassName","jsx","jsxs","jsx","jsxs","jsx","jsx","Fragment","jsx","jsxs","useMemo","useState","jsx","useState","useMemo","jsx","jsxs","jsx","jsxs","jsx","useCallback","Avatar","AvatarImage","AvatarFallback","jsx","jsxs","jsx","jsxs","useCallback","useState","jsx","jsxs","useState","jsx","jsxs","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","useState","useMemo","React","useCallback","useMemo","jsx","jsxs","useMemo","useCallback","useRef","useEffect","jsx"]}
1
+ {"version":3,"sources":["../src/components/PostCard.tsx","../src/utils/cn.ts","../src/components/PostHeader.tsx","../src/components/AppIcon.tsx","../src/utils/postTypeHint.ts","../src/utils/relativeTime.ts","../src/components/AutoLink.tsx","../src/components/PostBody.tsx","../src/components/PostEmail.tsx","../src/components/MediaView.tsx","../src/components/AsyncImage.tsx","../src/components/Loader.tsx","../src/components/PostPollLayout/pollUtils.ts","../src/components/PostPollLayout/PostPollIResultView.tsx","../src/components/PostPollLayout/PostPollIButtonView.tsx","../src/components/PostPollLayout/PostPollLayoutOne.tsx","../src/components/PostPollLayout/PostPollLayoutGrid.tsx","../src/components/PostPollView.tsx","../src/components/PostTextItem.tsx","../src/components/PostLinkItem.tsx","../src/components/PostEmbedView.tsx","../src/components/PostMediaLayout/MediaUploadStatusOverlay.tsx","../src/components/PostMediaLayout/PostMediaLayoutCore.tsx","../src/components/PostItemsView.tsx","../src/components/PostSectionsView.tsx","../src/utils/contentTypeConstants.ts","../src/components/PostSectionSourceInfoView.tsx","../src/components/PostFooter.tsx","../src/components/PostMediaLayout/uploadStats.ts","../src/components/PostUploadStrip.tsx","../src/components/EraseConfirmModal.tsx","../src/components/PostSectionsSummaryView.tsx","../src/modals/ReactionModal.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react'\nimport { cn } from '../utils/cn'\nimport { resolvePostContent } from '../resolver'\nimport PostHeader from './PostHeader'\nimport PostBody from './PostBody'\nimport PostItemsView from './PostItemsView'\nimport PostSectionsView from './PostSectionsView'\nimport PostFooter from './PostFooter'\nimport PostUploadStrip from './PostUploadStrip'\nimport EraseConfirmModal from './EraseConfirmModal'\nimport type { ItemData, LinkItemMetaData, MediaUploadStatus, MentionData, PollItemData, PollResult, SectionItem } from '../types'\nimport type { TipTapDocument } from '../types/tiptap'\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface PostCardProps {\n // Core post data\n post: {\n context_id: string\n body?: string\n htmlBody?: string\n jsonBody?: TipTapDocument | null\n textBody?: string\n items?: ItemData[] | LinkItemMetaData[] | PollItemData[]\n mentionData?: MentionData[]\n sections?: SectionItem[]\n poll_result?: PollResult\n postedAt: string\n postType: string\n is_pending?: boolean\n isFeatured?: boolean\n }\n\n // Author / group\n author: { id: string; name: string; avatar: string; avatarPlaceholder?: string }\n authorHref: string\n group?: { name: string; avatar?: string }\n groupHref?: string\n\n // Navigation\n postHref?: string\n linkComponent?: React.ComponentType<{ href: string; children: React.ReactNode; className?: string }>\n imageComponent?: React.ComponentType<{ src: string; alt: string; fill?: boolean; placeholder?: 'blur' | 'empty'; blurDataURL?: string; priority?: boolean; className?: string }>\n\n // Permissions\n /** Author's role in the group — drives the owner crown / admin shield badge. */\n isAdmin?: boolean\n /** Author's role in the group — drives the owner crown / admin shield badge. */\n isOwner?: boolean\n /**\n * Whether the *viewer* is the post's author. Lets the author preview their own\n * poll results before voting. Distinct from `isOwner` (which is the author's\n * group role, for the badge) — pass it explicitly. When omitted, the author\n * preview is simply off (the author sees results after voting, like anyone).\n */\n isPostOwner?: boolean\n isPostPreview?: boolean\n isPrivate?: boolean\n membersCount?: number\n\n // Cross-post / i18n\n crossPostGroup?: { name: string; href?: string }\n locale?: string\n translate?: (key: string, params?: { count?: number }) => string\n\n // Actions\n onPostPress?: () => void\n onErasePress?: () => void\n onCancelPost?: () => void\n onVotePress?: (item: ItemData) => void\n onCardPress?: () => void\n renderActionsMenu?: () => React.ReactNode\n renderReactionTrigger?: (props: { onOpen: () => void }) => React.ReactNode\n renderReactionModal?: (props: { isOpen: boolean; onClose: () => void; onSend: (emoji: string) => void }) => React.ReactNode\n\n // Content callbacks\n onNavigate?: (href: string, isInternal: boolean) => void\n supportDeepviewDomain?: string | string[]\n\n // Labels\n labels?: {\n cancelPost?: string\n sending?: string\n uploadingRemaining?: string\n uploadingDone?: string\n }\n\n // Display\n mode?: 'feed' | 'detail' | 'inbox' | 'draft'\n commentCount?: number\n unreadCommentCount?: number\n isSnoozed?: boolean\n onSnoozeToggle?: () => void\n mediaItemStatuses?: Record<string, MediaUploadStatus>\n showFooterLink?: boolean\n footerLinkLabel?: string\n footerLinkHref?: string\n className?: string\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst PostCard: React.FC<PostCardProps> = ({\n post,\n author,\n authorHref,\n group,\n groupHref,\n postHref,\n linkComponent,\n imageComponent,\n isAdmin,\n isOwner,\n isPostOwner,\n isPostPreview,\n isPrivate,\n membersCount,\n crossPostGroup,\n locale,\n translate,\n onPostPress,\n onErasePress,\n onCancelPost,\n onVotePress,\n onCardPress,\n renderActionsMenu,\n renderReactionTrigger,\n renderReactionModal,\n onNavigate,\n supportDeepviewDomain,\n labels,\n mode = 'feed',\n commentCount = 0,\n unreadCommentCount = 0,\n isSnoozed = false,\n onSnoozeToggle,\n mediaItemStatuses,\n showFooterLink = false,\n footerLinkLabel,\n footerLinkHref,\n className,\n}) => {\n const [eraseModalOpen, setEraseModalOpen] = useState(false)\n\n const isPending = !!post.is_pending\n const isPostDetail = mode === 'detail'\n const sendingLabel = labels?.sending ?? 'Sending...'\n\n // Build a PostDataMetaData-compatible shape from the flat post prop\n const contextData = useMemo(\n () => ({\n body: post.body ?? '',\n htmlBody: post.htmlBody,\n jsonBody: post.jsonBody,\n textBody: post.textBody,\n items: post.items,\n mentionData: post.mentionData,\n sections: post.sections,\n }),\n [post.body, post.htmlBody, post.jsonBody, post.textBody, post.items, post.mentionData, post.sections]\n )\n\n const isEmailPost = Boolean(post.htmlBody && !post.jsonBody)\n\n const resolvedContent = useMemo(\n () =>\n resolvePostContent(contextData, {\n postType: post.postType,\n pollResult: post.poll_result ?? null,\n postSpecialType: post.isFeatured ? 1 : 0,\n mode: isPostDetail ? 'detail' : (mode as 'feed' | 'inbox' | 'draft'),\n isEmailPost,\n }),\n [contextData, post.postType, post.poll_result, post.isFeatured, isPostDetail, mode, isEmailPost]\n )\n\n const handleErasePress = () => {\n setEraseModalOpen(true)\n }\n\n const handleEraseConfirm = () => {\n setEraseModalOpen(false)\n onErasePress?.()\n }\n\n const handleEraseCancel = () => {\n setEraseModalOpen(false)\n }\n\n const handleCardClick = (e: React.MouseEvent<HTMLElement>) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n if (isPending) return\n onPostPress?.()\n }\n\n const handleCardKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n e.stopPropagation()\n if (isPending) return\n onPostPress?.()\n }\n }\n\n return (\n <article\n className={cn(\n 'w-full flex flex-col box-border bg-background',\n !isPostDetail &&\n 'cursor-pointer sm:border border-border rounded-xl sm:rounded-2xl overflow-hidden shadow-sm hover:shadow-md transition-shadow duration-300 relative mt-6',\n isPostDetail && 'cursor-auto rounded-t-2xl w-full',\n post.isFeatured && !isPostDetail && 'bg-highlight-surface border-highlight-border sm:border-t-4',\n isPending && 'cursor-default',\n className\n )}\n onClick={!isPostDetail && onPostPress ? handleCardClick : undefined}\n onKeyDown={!isPostDetail && !isPending && onPostPress ? handleCardKeyDown : undefined}\n tabIndex={!isPostDetail && !isPending && onPostPress ? 0 : undefined}\n role={!isPostDetail && !isPending && onPostPress ? 'button' : undefined}\n aria-label={!isPostDetail && !isPending && onPostPress ? 'View post details' : undefined}\n >\n {/* Screen-reader-only link for keyboard / assistive tech */}\n {!isPostDetail && !isPending && postHref && linkComponent && (\n React.createElement(linkComponent, {\n href: postHref,\n className: 'sr-only',\n children: 'View post details',\n })\n )}\n\n {!isPostDetail && !isPending && postHref && !linkComponent && (\n <a href={postHref} className=\"sr-only\" onClick={(e) => e.stopPropagation()}>\n View post details\n </a>\n )}\n\n {/* Pending loading bar */}\n {isPending && (\n <div className=\"absolute top-0 left-0 w-full z-10\">\n <div\n className=\"h-1 w-full overflow-hidden rounded bg-muted\"\n role=\"progressbar\"\n aria-label={sendingLabel}\n data-testid=\"post-loader\"\n >\n <div className=\"animate-indeterminate h-full w-1/3 rounded bg-action-primary\" />\n </div>\n </div>\n )}\n\n {/* Erase confirm modal */}\n {!isPending && eraseModalOpen && (\n <EraseConfirmModal\n isOpen={eraseModalOpen}\n itemType=\"Post\"\n onYesPress={handleEraseConfirm}\n onNoPress={handleEraseCancel}\n handleClose={handleEraseCancel}\n />\n )}\n\n {/* Main content — dimmed while pending */}\n <div className={cn(isPending && 'opacity-50')}>\n <PostHeader\n author={author}\n authorHref={authorHref}\n group={group}\n groupHref={groupHref}\n postedAt={post.postedAt}\n postType={post.postType}\n isFeatured={post.isFeatured}\n isPostPreview={isPostPreview}\n isPostDetail={isPostDetail}\n isAdmin={isAdmin}\n isOwner={isOwner}\n isPrivate={isPrivate}\n membersCount={membersCount}\n crossPostGroup={crossPostGroup}\n locale={locale}\n translate={translate}\n onErasePress={onErasePress ? handleErasePress : undefined}\n onCancelPost={onCancelPost}\n renderActionsMenu={renderActionsMenu}\n linkComponent={linkComponent}\n imageComponent={imageComponent}\n labels={labels}\n />\n\n <PostBody\n textContent={resolvedContent.textContent}\n showFull={isPostDetail}\n isPostDetail={isPostDetail}\n isRichContent={resolvedContent.isRichContent}\n isEmailPost={isEmailPost}\n hideEmailDescription={\n isEmailPost &&\n !isPostDetail &&\n resolvedContent.primaryContent?.type === 'media'\n }\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n\n {resolvedContent.sections && (\n <PostSectionsView\n sections={resolvedContent.sections.sections}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress ?? (() => {})}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n imageComponent={imageComponent}\n />\n )}\n\n <PostItemsView\n primaryContent={resolvedContent.primaryContent}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress ?? (() => {})}\n onVotePress={onVotePress ?? (() => {})}\n isPostOwner={isPostOwner}\n parentId={post.context_id}\n isCommentScope={false}\n imageComponent={imageComponent}\n mediaItemStatuses={mediaItemStatuses}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n\n {/* Per-item upload progress strip */}\n <PostUploadStrip\n statuses={mediaItemStatuses}\n labels={{\n uploadingRemaining: labels?.uploadingRemaining,\n uploadingDone: labels?.uploadingDone,\n }}\n />\n </div>\n\n {/* Footer — pointer events disabled while pending */}\n <div className={cn(isPending && 'opacity-50 pointer-events-none')}>\n <PostFooter\n // On the post-detail page the comment icon would link to the page\n // you're already on — suppress it by withholding the href there.\n postHref={isPostDetail ? undefined : postHref}\n commentCount={commentCount}\n unreadCommentCount={unreadCommentCount}\n isSnoozed={isSnoozed}\n onSnoozeToggle={onSnoozeToggle}\n showFooterLink={showFooterLink}\n footerLinkLabel={footerLinkLabel}\n footerLinkHref={footerLinkHref}\n linkComponent={linkComponent}\n renderReactionTrigger={renderReactionTrigger}\n renderReactionModal={renderReactionModal}\n />\n </div>\n </article>\n )\n}\n\nexport default PostCard\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import React from 'react'\nimport {\n Avatar,\n AvatarImage,\n AvatarFallback,\n AvatarBadge,\n} from '@select-org/ui'\nimport AppIcon from './AppIcon'\nimport { getPostTypeHint, POST_TYPE_HINT_DEFAULTS } from '../utils/postTypeHint'\nimport { formatRelativeTime } from '../utils/relativeTime'\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface PostHeaderProps {\n author: {\n id: string\n name: string\n avatar: string\n avatarPlaceholder?: string\n }\n authorHref: string\n group?: { name: string; avatar?: string }\n groupHref?: string\n postedAt: string // ISO timestamp\n postType: string\n isPrivate?: boolean\n membersCount?: number\n crossPostGroup?: { name: string; href?: string }\n locale?: string\n translate?: (key: string, params?: { count?: number }) => string\n isFeatured?: boolean\n isPostPreview?: boolean // true for draft / ToUpload posts — render spans not links\n isPostDetail?: boolean // on the detail page the author name is the document's <h2>\n isAdmin?: boolean\n isOwner?: boolean\n onErasePress?: () => void\n onCancelPost?: () => void\n renderActionsMenu?: () => React.ReactNode\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n imageComponent?: React.ComponentType<{\n src: string\n alt: string\n fill?: boolean\n placeholder?: 'blur' | 'empty'\n blurDataURL?: string\n priority?: boolean\n className?: string\n }>\n labels?: {\n cancelPost?: string\n }\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst PostHeader: React.FC<PostHeaderProps> = ({\n author,\n authorHref,\n group,\n groupHref,\n postedAt,\n postType,\n isPrivate = false,\n membersCount,\n crossPostGroup,\n locale,\n translate,\n isFeatured = false,\n isPostPreview = false,\n isPostDetail = false,\n isAdmin = false,\n isOwner = false,\n onErasePress,\n onCancelPost,\n renderActionsMenu,\n linkComponent: LinkComponent,\n imageComponent,\n labels,\n}) => {\n const cancelLabel = labels?.cancelPost ?? 'Cancel'\n\n // Humanized post-type hint (translate seam + English defaults)\n const { key: hintKey, params: hintParams } = getPostTypeHint(postType, {\n isInGroup: !!group,\n isOwner,\n isPrivate,\n membersCount,\n })\n const hintText =\n translate?.(hintKey, hintParams) ??\n POST_TYPE_HINT_DEFAULTS[hintKey]?.(hintParams) ??\n hintKey\n\n // Resolve the badge variant — owner takes priority over admin\n const badgeVariant: 'owner' | 'admin' | undefined = isOwner\n ? 'owner'\n : isAdmin\n ? 'admin'\n : undefined\n\n // Author name — span (preview) or link\n const authorNameNode = isPostPreview ? (\n <span className=\"flex text-base font-semibold leading-[100%] text-foreground\">\n {author.name}\n </span>\n ) : LinkComponent ? (\n <LinkComponent\n href={authorHref}\n className=\"flex text-base font-semibold leading-[100%] text-foreground hover:opacity-70 bg-transparent border-none p-0 cursor-pointer no-underline\"\n >\n {author.name}\n </LinkComponent>\n ) : (\n <a\n href={authorHref}\n onClick={(e) => e.stopPropagation()}\n className=\"flex text-base font-semibold leading-[100%] text-foreground hover:opacity-70 bg-transparent border-none p-0 cursor-pointer no-underline\"\n aria-label={`View ${author.name}'s profile`}\n >\n {author.name}\n </a>\n )\n\n // Group link node\n const groupLinkNode =\n group && groupHref ? (\n isPostPreview ? (\n <span className=\"text-action-primary font-medium\">#{group.name}</span>\n ) : LinkComponent ? (\n <LinkComponent\n href={groupHref}\n className=\"text-action-primary font-medium no-underline hover:underline cursor-pointer bg-transparent border-none p-0\"\n >\n #{group.name}\n </LinkComponent>\n ) : (\n <a\n href={groupHref}\n onClick={(e) => e.stopPropagation()}\n className=\"text-action-primary font-medium no-underline hover:underline cursor-pointer bg-transparent border-none p-0\"\n title={group.name}\n aria-label={`View group ${group.name}`}\n >\n #{group.name}\n </a>\n )\n ) : null\n\n return (\n <section className=\"not-prose relative flex flex-col justify-start p-4 pb-3\">\n <section className=\"flex items-center gap-3\">\n {/* Author avatar */}\n <Avatar\n size=\"md\"\n disabled={isPostPreview}\n className=\"shrink-0 ring-1 ring-border-subtle\"\n >\n <AvatarImage\n src={author.avatar}\n alt={`${author.name}'s profile picture`}\n placeholder={author.avatarPlaceholder}\n imageComponent={imageComponent}\n />\n <AvatarFallback name={author.name} />\n {badgeVariant && <AvatarBadge variant={badgeVariant} />}\n </Avatar>\n\n {/* Meta */}\n <section className=\"flex flex-1 flex-col justify-center min-w-0\">\n {/* Top row: name + featured star + timestamp */}\n <section className=\"flex items-baseline justify-between gap-2\">\n <div className=\"flex items-center gap-1.5 min-w-0\">\n {/* On the detail page the post is the page's main content, so the\n author/post line is the document <h2> (sits under the page <h1>).\n In list contexts (feed/inbox) it's a plain <div> to avoid\n polluting the heading outline with one heading per card. */}\n {isPostDetail ? (\n <h2 className=\"font-semibold text-foreground truncate\">\n {authorNameNode}\n </h2>\n ) : (\n <div className=\"font-semibold text-foreground truncate\">\n {authorNameNode}\n </div>\n )}\n\n {isFeatured && (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={14}\n height={14}\n className=\"text-highlight fill-highlight shrink-0\"\n aria-label=\"Featured post\"\n >\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\" />\n </svg>\n )}\n\n {postedAt && (\n <>\n <span className=\"text-muted-foreground font-bold shrink-0\">\n &middot;\n </span>\n <time\n title={postedAt}\n className=\"text-xs text-muted-foreground whitespace-nowrap shrink-0\"\n dateTime={postedAt}\n >\n {formatRelativeTime(postedAt, locale ?? 'en')}\n </time>\n </>\n )}\n </div>\n </section>\n\n {/* Bottom row: post type hint + optional group link + cross-post via */}\n <div className=\"text-xs text-muted-foreground truncate mt-0.5\">\n <span>{hintText}</span>\n {groupLinkNode && (\n <>\n <span className=\"mx-1\"></span>\n {groupLinkNode}\n </>\n )}\n {crossPostGroup && (\n <>\n <span className=\"mx-1\">via</span>\n {LinkComponent && crossPostGroup.href ? (\n <LinkComponent\n href={crossPostGroup.href}\n className=\"text-action-primary font-medium hover:underline no-underline\"\n >\n #{crossPostGroup.name}\n </LinkComponent>\n ) : crossPostGroup.href ? (\n <a\n href={crossPostGroup.href}\n onClick={(e) => e.stopPropagation()}\n className=\"text-action-primary font-medium hover:underline no-underline\"\n >\n #{crossPostGroup.name}\n </a>\n ) : (\n <span className=\"text-action-primary font-medium\">\n #{crossPostGroup.name}\n </span>\n )}\n </>\n )}\n </div>\n </section>\n </section>\n\n {/* Top-right slot: actions menu OR cancel button */}\n {isPostPreview ? (\n onCancelPost && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onCancelPost()\n }}\n aria-label={cancelLabel}\n data-testid=\"cancel-pending-post\"\n className=\"absolute right-4 top-4 leading-none rounded-full p-1.5 transition-colors hover:bg-feedback-danger/10 hover:text-feedback-danger\"\n >\n <AppIcon name=\"cancel\" width={16} height={16} strokeWidth={1.75} />\n </button>\n )\n ) : renderActionsMenu ? (\n <div className=\"absolute right-2 top-2\">{renderActionsMenu()}</div>\n ) : onErasePress ? (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onErasePress()\n }}\n aria-label=\"Delete post\"\n className=\"absolute right-4 top-4 leading-none rounded-full p-1.5 transition-colors hover:bg-feedback-danger/10 hover:text-feedback-danger\"\n >\n <AppIcon name=\"chatErase\" width={16} height={16} strokeWidth={1.75} />\n </button>\n ) : null}\n </section>\n )\n}\n\nexport default PostHeader\n","import {\n AlarmClock,\n Check,\n CheckCircle2,\n CirclePlay,\n ExternalLink,\n LoaderCircle,\n MessageCircleMore,\n Smile,\n ThumbsDown,\n ThumbsUp,\n Trash2,\n TriangleAlert,\n Video,\n X,\n} from 'lucide-react'\nimport type { LucideProps } from 'lucide-react'\n\n// AppIcon subset used by post-components\nconst ICON_MAP = {\n video: Video,\n circlePlay: CirclePlay,\n cancel: X,\n externalLink: ExternalLink,\n sendEmoji: Smile,\n alarmClock: AlarmClock,\n messageCircleMore: MessageCircleMore,\n chatErase: Trash2,\n checkCircle2: CheckCircle2,\n thumbUp: ThumbsUp,\n thumbDown: ThumbsDown,\n check: Check,\n loader: LoaderCircle,\n triangleAlert: TriangleAlert,\n}\n\nexport type AppIconName = keyof typeof ICON_MAP\n\ninterface AppIconProps extends LucideProps {\n name: AppIconName\n}\n\nexport default function AppIcon({ name, ...props }: AppIconProps) {\n const Icon = ICON_MAP[name]\n if (!Icon) return null\n return <Icon {...props} />\n}\n","// Framework-agnostic humanized post-type hint.\n//\n// Ported from the web client's `toPostTypeHint`\n// (src/utils/PostUtils.ts). Returns the SAME i18n keys + an optional\n// `params.count` for plural cases, so a consumer's `translate(key, params)`\n// resolves identically. No React, no i18n lib — pure logic + English defaults.\n//\n// Machine post-type strings (from the web client Constants):\n// new:post:image -> NEW_POST_IMAGE\n// new:post:media -> NEW_POST_MEDIA\n// new:post:link -> NEW_POST_LINK\n// new:post:poll -> NEW_POST_POLL\n// new:post:text -> NEW_POST_MESSAGE\n// new:post:thread -> NEW_POST_THREAD\n// mediaItemToUpload -> MEDIA_ITEM_TO_UPLOAD (treated as media)\n\nexport interface PostTypeHintContext {\n isInGroup?: boolean\n isOwner?: boolean\n isPrivate?: boolean\n membersCount?: number\n /** Mirrors the web client's `isMetaDesc` branch (SEO/meta-description copy). */\n isMetaDesc?: boolean\n}\n\nexport interface PostTypeHint {\n key: string\n params?: { count?: number }\n}\n\nconst MEDIA_TYPES = new Set([\n 'new:post:media',\n 'new:post:image',\n 'mediaItemToUpload',\n])\n\nexport function getPostTypeHint(\n postType: string,\n ctx: PostTypeHintContext = {}\n): PostTypeHint {\n const {\n isInGroup = false,\n isOwner = false,\n isPrivate = false,\n membersCount = 0,\n isMetaDesc = false,\n } = ctx\n\n const isMedia = MEDIA_TYPES.has(postType)\n\n if (isInGroup) {\n if (isMetaDesc) {\n // SEO / meta-description copy\n if (isMedia)\n return { key: 'post_detail_meta_description_type_image_post' }\n switch (postType) {\n case 'new:post:link':\n return { key: 'post_detail_meta_description_type_link_post' }\n case 'new:post:poll':\n return { key: 'post_detail_meta_description_type_poll_post' }\n case 'new:post:thread':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_thread_post',\n }\n case 'new:post:text':\n default:\n return { key: 'post_detail_meta_description_type_message_post' }\n }\n }\n // who sent to a group\n if (isMedia)\n return { key: 'post_detail_one_liner_receive_and_send_group_image_post' }\n switch (postType) {\n case 'new:post:link':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_link_post',\n }\n case 'new:post:poll':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_poll_post',\n }\n case 'new:post:thread':\n return {\n key: 'post_detail_one_liner_receive_and_send_group_thread_post',\n }\n case 'new:post:text':\n default:\n return {\n key: 'post_detail_one_liner_receive_and_send_group_message_post',\n }\n }\n }\n\n if (isOwner) {\n // me sent to others\n return membersCount > 1\n ? sentPlural(postType, membersCount)\n : sentSingular(postType)\n }\n\n if (isPrivate) {\n // who sent to me with 1:1\n if (isMedia)\n return { key: 'post_detail_one_liner_receive_private_image_post' }\n switch (postType) {\n case 'new:post:link':\n return { key: 'post_detail_one_liner_receive_private_link_post' }\n case 'new:post:poll':\n return { key: 'post_detail_one_liner_receive_private_poll_post' }\n case 'new:post:thread':\n case 'new:post:text':\n default:\n return { key: 'post_detail_one_liner_receive_message_post' }\n }\n }\n\n // who sent to me with 1:M\n return membersCount > 1\n ? sentPlural(postType, membersCount)\n : sentSingular(postType)\n}\n\nfunction sentPlural(postType: string, count: number): PostTypeHint {\n const params = { count }\n if (MEDIA_TYPES.has(postType))\n return { key: 'post_detail_one_liner_send_private_image_post_plural', params }\n switch (postType) {\n case 'new:post:link':\n return {\n key: 'post_detail_one_liner_send_private_link_post_plural',\n params,\n }\n case 'new:post:poll':\n return {\n key: 'post_detail_one_liner_send_private_link_poll_plural',\n params,\n }\n case 'new:post:thread':\n case 'new:post:text':\n default:\n return { key: 'post_detail_one_liner_send_message_post_plural', params }\n }\n}\n\nfunction sentSingular(postType: string): PostTypeHint {\n if (MEDIA_TYPES.has(postType))\n return { key: 'post_detail_one_liner_send_private_image_post_singular' }\n switch (postType) {\n case 'new:post:link':\n return { key: 'post_detail_one_liner_send_private_link_post_singular' }\n case 'new:post:poll':\n return { key: 'post_detail_one_liner_send_private_link_poll_singular' }\n case 'new:post:thread':\n case 'new:post:text':\n default:\n return { key: 'post_detail_one_liner_send_message_post_singular' }\n }\n}\n\n// English fallback strings — ONE per key getPostTypeHint can return.\n// Every branch above is covered here.\nexport const POST_TYPE_HINT_DEFAULTS: Record<\n string,\n (p?: { count?: number }) => string\n> = {\n // in-group (one-liner)\n post_detail_one_liner_receive_and_send_group_image_post: () =>\n 'shared a media post in group',\n post_detail_one_liner_receive_and_send_group_link_post: () =>\n 'shared a link post in group',\n post_detail_one_liner_receive_and_send_group_poll_post: () =>\n 'shared a poll in group',\n post_detail_one_liner_receive_and_send_group_thread_post: () =>\n 'shared a thread in group',\n post_detail_one_liner_receive_and_send_group_message_post: () =>\n 'shared a post in group',\n\n // in-group (meta description)\n post_detail_meta_description_type_image_post: () => 'A media post',\n post_detail_meta_description_type_link_post: () => 'A link post',\n post_detail_meta_description_type_poll_post: () => 'A poll',\n post_detail_meta_description_type_message_post: () => 'A post',\n\n // owner / 1:M sent — plural\n post_detail_one_liner_send_private_image_post_plural: (p) =>\n `sent a media post to ${p?.count ?? 0} people`,\n post_detail_one_liner_send_private_link_post_plural: (p) =>\n `sent a link post to ${p?.count ?? 0} people`,\n post_detail_one_liner_send_private_link_poll_plural: (p) =>\n `sent a poll to ${p?.count ?? 0} people`,\n post_detail_one_liner_send_message_post_plural: (p) =>\n `sent a post to ${p?.count ?? 0} people`,\n\n // owner / 1:M sent — singular\n post_detail_one_liner_send_private_image_post_singular: () =>\n 'sent a media post',\n post_detail_one_liner_send_private_link_post_singular: () =>\n 'sent a link post',\n post_detail_one_liner_send_private_link_poll_singular: () => 'sent a poll',\n post_detail_one_liner_send_message_post_singular: () => 'sent a post',\n\n // private 1:1 received\n post_detail_one_liner_receive_private_image_post: () =>\n 'sent you a media post',\n post_detail_one_liner_receive_private_link_post: () => 'sent you a link post',\n post_detail_one_liner_receive_private_poll_post: () => 'sent you a poll',\n post_detail_one_liner_receive_message_post: () => 'sent you a post',\n}\n","const UNITS: [Intl.RelativeTimeFormatUnit, number][] = [\n ['year', 31_536_000],\n ['month', 2_592_000],\n ['week', 604_800],\n ['day', 86_400],\n ['hour', 3_600],\n ['minute', 60],\n]\n\nexport function formatRelativeTime(iso: string, locale: string = 'en'): string {\n const diffMs = Date.now() - new Date(iso).getTime()\n const seconds = Math.round(diffMs / 1000)\n if (Math.abs(seconds) < 60) return 'just now'\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' })\n for (const [unit, secs] of UNITS) {\n if (Math.abs(seconds) >= secs) {\n const value = Math.round(seconds / secs)\n return rtf.format(-value, unit) // negative = past\n }\n }\n return 'just now'\n}\n","/*!\n * React Native Autolink\n *\n * Copyright 2016-2018 Josh Swan\n * Released under the MIT license\n * https://github.com/joshswan/react-native-autolink/blob/master/LICENSE\n *\n * Simplified and improved by Dean, to support mention list.\n * Ported to design-system post-components: routing and config dependencies removed.\n */\n\nimport React, { useCallback, useMemo } from 'react'\nimport Autolinker, { Match } from 'autolinker'\nimport { truncateSmart } from 'autolinker/dist/commonjs/truncate/truncate-smart'\nimport { truncateEnd } from 'autolinker/dist/commonjs/truncate/truncate-end'\nimport { truncateMiddle } from 'autolinker/dist/commonjs/truncate/truncate-middle'\nimport { MentionData, FormatMentionData } from '../types'\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst MENTION_TYPE = {\n MENTION: 'mention',\n HASHTAG: 'hashtag',\n} as const\n\n// ---------------------------------------------------------------------------\n// Utilities (ported from InputValidator.ts / helpers.tsx)\n// ---------------------------------------------------------------------------\n\nimport emojiRegex from 'emoji-regex'\n\nconst EMOJI_REGEX = emojiRegex()\n\nexport const getPureEmojiSize = (body: string): number => {\n let match: RegExpExecArray | null\n let emojiCount = 0\n let emojiSize = 0\n\n while ((match = EMOJI_REGEX.exec(body))) {\n const emoji = match[0]\n emojiSize += emoji.length\n emojiCount += 1\n }\n\n if (emojiSize === body.length) {\n return emojiCount\n }\n return 0\n}\n\nexport const checkMentionDataIndex = (\n mentionData: MentionData[] = [],\n copyMentionData: MentionData[] = [],\n body = ''\n): FormatMentionData[] => {\n let mentionBody = body\n const newMentionData = [...mentionData, ...copyMentionData]\n let lastMentionData: { index: number; endIndex: number } = { index: 0, endIndex: 0 }\n const formatNewMention: FormatMentionData[] = []\n\n for (let i = 0; i < newMentionData.length; i++) {\n const mention = { ...newMentionData[i] }\n\n if (mention.name && typeof mention.name === 'string') {\n mention.name = mention.name.trim()\n } else {\n continue\n }\n\n if (mentionBody.indexOf(mention.name) === -1) {\n continue\n }\n\n const type = mention.type\n const name = (type === MENTION_TYPE.MENTION ? '@' : '#') + mention.name\n const index = mentionBody.indexOf(name) + lastMentionData.endIndex\n const endIndex = index + name.length\n mentionBody = body.substr(endIndex, body.length)\n lastMentionData = { index, endIndex }\n\n formatNewMention.push({\n name,\n type,\n index,\n endIndex,\n data: mention,\n })\n }\n\n return formatNewMention\n}\n\nconst isLinkInternal = (\n url: string,\n supportDeepviewDomain: string | string[]\n): boolean => {\n if (!url) return false\n const domains = Array.isArray(supportDeepviewDomain)\n ? supportDeepviewDomain\n : supportDeepviewDomain\n ? [supportDeepviewDomain]\n : []\n return domains.some((d) => d.length > 0 && url.includes(d))\n}\n\n// ---------------------------------------------------------------------------\n// getUrl helper (exported for reuse by PostLinkItem etc.)\n// ---------------------------------------------------------------------------\n\nexport const getUrl = (match: any, phone?: any): [string] => {\n const type = match.getType()\n\n switch (type) {\n case 'email': {\n return [`mailto:${encodeURIComponent(match.getEmail())}`]\n }\n case 'phone': {\n const number = match.getNumber()\n switch (phone) {\n case 'sms':\n case 'text':\n return [`sms:${number}`]\n default:\n return [`tel:${number}`]\n }\n }\n case 'url': {\n return [match.getAnchorHref()]\n }\n default: {\n return [match.getMatchedText()]\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// truncate helper (attached to AutoLink below)\n// ---------------------------------------------------------------------------\n\ntype TruncateOptions = {\n truncate?: number\n truncateChars?: string\n truncateLocation?: 'smart' | 'end' | 'middle'\n}\n\nconst truncate = (\n text: string,\n { truncate: len = 32, truncateChars = '..', truncateLocation = 'smart' }: TruncateOptions = {}\n): string => {\n let fn: (text: string, length: number, ellipsisChars: string) => string\n\n switch (truncateLocation) {\n case 'end':\n fn = truncateEnd\n break\n case 'middle':\n fn = truncateMiddle\n break\n default:\n fn = truncateSmart\n }\n\n return fn(text, len, truncateChars)\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\ninterface AutoLinkProps {\n text: string\n mentionData?: MentionData[]\n onNavigate?: (href: string, isInternal: boolean) => void\n // When provided, internal mention links (@user / #group) render THROUGH this\n // component so the host app owns navigation: the web client passes its <Link>\n // (= router.push + a real href), the embed passes an <a> that absolutizes the\n // relative href to the Select app origin. Falls back to a raw <a> + onNavigate\n // when absent (backward-compatible for callers that haven't adopted it).\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n // pass-through display props\n phone?: any\n email?: any\n stripPrefix?: boolean\n style?: React.CSSProperties\n mentionClassName?: string\n className?: string\n}\n\nconst AutoLink = ({\n text: textProp,\n mentionData = [],\n onNavigate,\n linkComponent,\n supportDeepviewDomain = '',\n phone = true,\n email = true,\n stripPrefix = false,\n style = { fontSize: 12 },\n mentionClassName: mentionClassNameProp,\n className,\n}: AutoLinkProps) => {\n const mentionClassName = useMemo(\n () => mentionClassNameProp || 'font-bold text-action-primary',\n [mentionClassNameProp]\n )\n\n const handleNavigate = useCallback(\n (href: string, internal: boolean) => {\n if (onNavigate) {\n onNavigate(href, internal)\n } else if (internal) {\n window.location.href = href\n } else {\n window.open(href, '_blank')\n }\n },\n [onNavigate]\n )\n\n const renderDefaultLink = useCallback(\n (text: string, match: any, index: number) => {\n const [url] = getUrl(match, phone)\n const internal = isLinkInternal(url, supportDeepviewDomain)\n return (\n <a\n key={`${index}-autolink`}\n target=\"_blank\"\n rel={`noreferrer noopener${!internal ? ' nofollow' : ''}`}\n href={url}\n className=\"items-center text-link\"\n onClick={(e) => {\n e.stopPropagation()\n handleNavigate(url, internal)\n }}\n >\n {truncate(text, { truncate: 27, truncateLocation: 'end' })}\n </a>\n )\n },\n [phone, supportDeepviewDomain, handleNavigate]\n )\n\n const renderLink = useCallback(\n (text: string, match: Match, index: number) => {\n const [url] = getUrl(match, phone)\n if (isLinkInternal(url, supportDeepviewDomain)) {\n const internal = true\n return (\n <a\n key={`${index}-deeplink`}\n href={url}\n className=\"items-center text-link\"\n style={{ alignSelf: 'center' }}\n onClick={(e) => {\n e.stopPropagation()\n handleNavigate(url, internal)\n }}\n >\n {text}\n </a>\n )\n }\n return renderDefaultLink(text, match, index)\n },\n [phone, supportDeepviewDomain, renderDefaultLink, handleNavigate]\n )\n\n const renderMentionData = useCallback(\n (fmData: FormatMentionData, key: any) => {\n const href =\n fmData.type === MENTION_TYPE.HASHTAG\n ? `/groups/${fmData.data.selectId}`\n : `/users/${fmData.data.selectId || fmData.data.id}`\n\n const className = `no-underline hover:underline context-menu-ios-disable cursor-pointer ${mentionClassName}`\n\n // With a linkComponent, IT owns navigation (router.push / native nav) and\n // renders the href. The DS only stops the click from bubbling to the\n // card's press handler — calling handleNavigate too would double-navigate.\n // The linkComponent type doesn't accept an onClick, so wrap it in a span\n // (inline → no effect on text flow) that swallows the propagation.\n if (linkComponent) {\n const LinkComponent = linkComponent\n return (\n <span\n key={key + fmData.index}\n onClick={(e) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n }}\n >\n <LinkComponent href={href} className={className}>\n {fmData.name}\n </LinkComponent>\n </span>\n )\n }\n\n return (\n <a\n key={key + fmData.index}\n className={className}\n href={href}\n onClick={(e) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n handleNavigate(href, true)\n }}\n >\n {fmData.name}\n </a>\n )\n },\n [mentionClassName, handleNavigate, linkComponent]\n )\n\n const renderTextNodes = useCallback(() => {\n let text = textProp\n\n const uid = Math.floor(Math.random() * 0x10000000000).toString(16)\n const tokenRegexp = new RegExp(`(@__ELEMENT-${uid}-\\\\d+__@)`, 'g')\n\n const generateToken = (() => {\n let counter = 0\n return () => `@__ELEMENT-${uid}-${counter++}__@`\n })()\n\n const matches: Record<string, any> = {}\n\n try {\n text = Autolinker.link(text || '', {\n email,\n phone,\n urls: {\n schemeMatches: true,\n wwwMatches: true,\n tldMatches: true,\n } as any,\n stripPrefix,\n replaceFn: (match) => {\n const token = generateToken()\n matches[token] = match\n return token\n },\n })\n } catch {\n return null\n }\n\n const newNodes: React.ReactNode[] = []\n\n text\n .split(tokenRegexp)\n .filter((part) => !!part)\n .forEach((part, index) => {\n const match = matches[part]\n if (!match) {\n if (!mentionData || mentionData.length === 0) {\n newNodes.push(part)\n } else {\n const newMentionData = checkMentionDataIndex(mentionData, [], part)\n if (!newMentionData || newMentionData.length === 0) {\n newNodes.push(part)\n return\n }\n\n for (let j = 0; j < newMentionData.length; j++) {\n const curMentionData = newMentionData[j]\n\n if (j === 0) {\n const word = part.substring(0, curMentionData.index)\n newNodes.push(word)\n }\n\n newNodes.push(renderMentionData(curMentionData, part + index))\n\n const nextMentionData =\n j < newMentionData.length ? newMentionData[j + 1] : null\n if (nextMentionData) {\n const word = part.substring(curMentionData.endIndex, nextMentionData.index)\n newNodes.push(word)\n } else {\n const word = part.substring(curMentionData.endIndex, part.length)\n newNodes.push(word)\n }\n }\n }\n return\n }\n\n switch (match.getType()) {\n case 'email':\n case 'phone':\n case 'url':\n newNodes.push(renderLink(match.getAnchorText(), match, index))\n break\n default:\n newNodes.push(part)\n break\n }\n })\n\n let textStyle: React.CSSProperties | undefined = style\n const fontSize = style && (style as any).fontSize ? (style as any).fontSize : 12\n const pureEmojiCount = getPureEmojiSize(text.trim())\n if (pureEmojiCount === 1) {\n textStyle = { ...style, fontSize: fontSize * 2.5 }\n } else if (pureEmojiCount === 2) {\n textStyle = { ...style, fontSize: fontSize * 2 }\n } else if (pureEmojiCount === 3) {\n textStyle = { ...style, fontSize: fontSize * 1.5 }\n }\n\n return (\n <div style={textStyle} className={className}>\n {newNodes}\n </div>\n )\n }, [\n style,\n email,\n phone,\n stripPrefix,\n mentionData,\n textProp,\n className,\n renderLink,\n renderMentionData,\n ])\n\n return renderTextNodes()\n}\n\nAutoLink.truncate = truncate\n\nexport default AutoLink\n","import AutoLink from './AutoLink'\nimport { hasMeaningfulHtml } from '../resolver/postContentResolver'\nimport type { ResolvedTextContent } from '../resolver/postContentResolver'\nimport { cn } from '../utils/cn'\nimport DOMPurify from 'dompurify'\nimport React, { useMemo } from 'react'\nimport PostEmail from './PostEmail'\n\ninterface Props {\n textContent: ResolvedTextContent\n showFull?: boolean\n isPostDetail: boolean\n isRichContent?: boolean\n hideEmailDescription?: boolean\n isEmailPost?: boolean\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n}\n\nconst PURIFY_CONFIG = {\n ALLOWED_TAGS: [\n 'p',\n 'br',\n 'b',\n 'i',\n 'em',\n 'strong',\n 'a',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'blockquote',\n 'code',\n 'pre',\n 'span',\n 'div',\n 'img',\n 'video',\n 'figure',\n 'figcaption',\n 'table',\n 'thead',\n 'tbody',\n 'tr',\n 'th',\n 'td',\n 'hr',\n 'sub',\n 'sup',\n 's',\n 'u',\n ],\n ALLOWED_ATTR: [\n 'href',\n 'controls',\n 'target',\n 'rel',\n 'class',\n 'id',\n 'src',\n 'alt',\n 'title',\n 'width',\n 'height',\n 'data-*',\n ],\n ALLOW_DATA_ATTR: true,\n ADD_ATTR: ['target'],\n FORBID_TAGS: ['script', 'style', 'iframe', 'object', 'embed', 'form'],\n FORBID_ATTR: ['onerror', 'onload', 'onclick', 'onmouseover'],\n}\n\nconst VOID_TAGS = new Set([\n 'BR',\n 'HR',\n 'IMG',\n 'VIDEO',\n 'INPUT',\n 'AREA',\n 'BASE',\n 'COL',\n 'LINK',\n 'META',\n 'PARAM',\n 'SOURCE',\n 'TRACK',\n 'WBR',\n])\n\nconst removeEmpty = (el: Element): void => {\n Array.from(el.children).forEach(removeEmpty)\n if (VOID_TAGS.has(el.tagName)) return\n if (!el.textContent?.trim() && el.children.length === 0) el.remove()\n}\n\nconst PostBody: React.FC<Props> = ({\n textContent,\n showFull = true,\n isPostDetail,\n isRichContent = false,\n hideEmailDescription = false,\n isEmailPost = false,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n}) => {\n const { plain, html, truncatedPlain, mentionData } = textContent\n\n const { sanitizedHtml, feedSanitizedHtml } = useMemo(() => {\n if (!html) return { sanitizedHtml: null, feedSanitizedHtml: null }\n\n const sanitized = DOMPurify.sanitize(html, PURIFY_CONFIG)\n\n // Feed mode: keep only the first media element to avoid flooding the feed.\n if (typeof document === 'undefined') {\n return { sanitizedHtml: sanitized, feedSanitizedHtml: sanitized }\n }\n\n const feedContainer = document.createElement('div')\n feedContainer.innerHTML = sanitized\n let keptOne = false\n feedContainer.querySelectorAll('img, video').forEach((el) => {\n if (!keptOne) {\n keptOne = true\n } else {\n el.remove()\n }\n })\n removeEmpty(feedContainer)\n return {\n sanitizedHtml: sanitized,\n feedSanitizedHtml: feedContainer.innerHTML,\n }\n }, [html])\n\n const { subject } = textContent\n const displayText = showFull ? plain : truncatedPlain\n const hasHtml = !!sanitizedHtml\n const hasMeaningfulHtmlText = hasMeaningfulHtml(sanitizedHtml)\n\n // Memoise the dangerouslySetInnerHTML elements so React sees the same React\n // element reference across renders and skips reconciling the prose subtree.\n // Without this, a re-render of PostBody re-creates the inner <div>'s element\n // descriptor; React diffs it, re-applies innerHTML, and the inner <video>\n // node is replaced — losing readyState and triggering a fresh metadata load.\n const detailProseElement = useMemo(\n () =>\n sanitizedHtml ? (\n <div\n className=\"prose prose-p:my-2! prose-a:text-action-primary! prose-a:no-underline! prose-img:my-4! prose-video:my-4! px-5! pb-4! max-w-full leading-relaxed overflow-hidden\"\n dangerouslySetInnerHTML={{ __html: sanitizedHtml }}\n />\n ) : null,\n [sanitizedHtml]\n )\n\n const feedProseElement = useMemo(\n () =>\n feedSanitizedHtml ? (\n <div\n className=\"prose *:px-4! *:data-[media='true']:px-0! *:data-link-preview:mx-4! [&>[data-media='true']>img]:rounded-none! [&>[data-media='true']>video]:rounded-none! [&>[data-media='true']>video]:size-full! prose-video:size-full! *:data-[media='true']:my-2 [&>div]:last-of-type:mb-0! prose-img:my-0! prose-img:w-full prose-video:my-0! prose-p:my-2! prose-a:text-action-primary! prose-a:no-underline! pb-4 max-w-full leading-relaxed line-clamp-4 overflow-hidden\"\n dangerouslySetInnerHTML={{ __html: feedSanitizedHtml }}\n />\n ) : null,\n [feedSanitizedHtml]\n )\n\n // If there's no text at all (neither plain nor html), render nothing\n if ((!displayText || typeof displayText !== 'string') && !hasHtml) {\n return null\n }\n\n const renderAutoLink = () => {\n if (!displayText || typeof displayText !== 'string') return null\n return (\n <AutoLink\n text={displayText}\n mentionData={mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n />\n )\n }\n\n if (isPostDetail) {\n if (isEmailPost && html) {\n return (\n <div className=\"relative flex-1 max-h-screen w-full overflow-x-hidden overflow-y-auto xl:px-0 px-5\">\n <h1 className=\"text-2xl font-semibold text-gray-900 leading-snug mt-5 mb-3 px-5\">\n {subject}\n </h1>\n <PostEmail html={html} />\n </div>\n )\n }\n\n return (\n <div className=\"flex-1\">\n {/* Keep plain text visible when htmlBody has no meaningful text (e.g. media-only html). */}\n {!hasMeaningfulHtmlText && <div>{renderAutoLink()}</div>}\n {sanitizedHtml && hasMeaningfulHtmlText && (\n <div data-theme=\"select-post-builder\" className=\"w-full max-w-full\">\n {detailProseElement}\n </div>\n )}\n </div>\n )\n }\n\n if (isRichContent && feedSanitizedHtml && hasMeaningfulHtmlText) {\n return (\n <div className={cn('flex-1 pb-4')} data-theme=\"select-post-builder\">\n {feedProseElement}\n </div>\n )\n }\n\n // Email post feed preview: subject line title + teaser body.\n if (subject) {\n return (\n <div className=\"flex-1 px-4 pb-4\">\n <h1 className=\"text-2xl font-semibold text-gray-900 leading-snug mb-1\">\n {subject}\n </h1>\n {!hideEmailDescription &&\n displayText &&\n typeof displayText === 'string' && (\n <AutoLink\n text={displayText}\n mentionData={mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n className=\"whitespace-normal leading-relaxed text-gray-600 line-clamp-3\"\n style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}\n />\n )}\n </div>\n )\n }\n\n // Feed default: plain text preview.\n return (\n <div className=\"flex-1\">\n <div>{renderAutoLink()}</div>\n </div>\n )\n}\n\nexport default PostBody\n","import React, { useEffect, useMemo, useRef } from 'react'\nimport DOMPurify from 'dompurify'\n\nconst EMAIL_PURIFY_CONFIG = {\n ALLOWED_TAGS: [\n // Structure\n 'html',\n 'head',\n 'body',\n 'style',\n // Layout (email is table-based)\n 'table',\n 'thead',\n 'tbody',\n 'tr',\n 'th',\n 'td',\n // Text\n 'p',\n 'span',\n 'div',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'b',\n 'strong',\n 'i',\n 'em',\n 'u',\n 'sub',\n 'sup',\n 'br',\n 'ul',\n 'ol',\n 'li',\n // Media & links\n 'a',\n 'img',\n ],\n ALLOWED_ATTR: [\n // Styling — critical for email\n 'style',\n 'class',\n 'bgcolor',\n 'color',\n // Table layout attributes (email-specific)\n 'width',\n 'height',\n 'align',\n 'valign',\n 'cellpadding',\n 'cellspacing',\n 'border',\n 'colspan',\n 'rowspan',\n // Images\n 'src',\n 'alt',\n // Links\n 'href',\n 'target',\n 'rel',\n // Accessibility\n 'role',\n 'aria-label',\n 'aria-roledescription',\n // Email-specific\n 'data-open-tracking',\n 'data-read-online-tooltip',\n ],\n ALLOW_DATA_ATTR: false,\n FORCE_BODY: false,\n WHOLE_DOCUMENT: true, // preserves <head> with <style>\n}\n\nconst sanitizeEmailHtml = (rawHtml: string) => {\n const clean = DOMPurify.sanitize(rawHtml, EMAIL_PURIFY_CONFIG)\n const doc = new DOMParser().parseFromString(clean, 'text/html')\n\n if (!doc.head) {\n const head = doc.createElement('head')\n doc.documentElement.insertBefore(head, doc.body)\n }\n\n const base = doc.createElement('base')\n base.setAttribute('target', '_blank')\n doc.head.appendChild(base)\n\n const style = doc.createElement('style')\n style.textContent = `\n html, body {\n margin: 0;\n padding: 0;\n }\n\n @media only screen and (max-width: 640px) {\n table[style*=\"min-width\"] {\n min-width: 0 !important;\n width: 100% !important;\n max-width: 100% !important;\n }\n\n td[style*=\"min-width\"],\n th[style*=\"min-width\"],\n div[style*=\"min-width\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n box-sizing: border-box !important;\n }\n\n img {\n max-width: 100% !important;\n height: auto !important;\n }\n }`\n\n doc.head.appendChild(style)\n\n doc.querySelectorAll('a[href]').forEach((a) => {\n a.setAttribute('target', '_blank')\n a.setAttribute('rel', 'noopener noreferrer nofollow')\n })\n\n return '<!DOCTYPE html>\\n' + doc.documentElement.outerHTML\n}\n\nconst PostEmail: React.FC<{ html: string }> = ({ html }) => {\n const ref = useRef<HTMLIFrameElement>(null)\n const cleanHtml = useMemo(() => sanitizeEmailHtml(html), [html])\n\n useEffect(() => {\n const iframe = ref.current\n if (!iframe) return\n\n let resizeObserver: ResizeObserver | null = null\n let rafId: number | null = null\n let timeoutIds: number[] = []\n\n const resizeIframe = () => {\n try {\n const doc = iframe.contentDocument\n if (!doc) return\n\n const body = doc.body\n const height = Math.max(\n Math.ceil(body.scrollHeight),\n Math.ceil(body.offsetHeight),\n Math.ceil(body.getBoundingClientRect().height)\n )\n\n iframe.style.height = `${height + 2}px`\n } catch {\n // ignore\n }\n }\n\n const scheduleResize = () => {\n if (rafId) cancelAnimationFrame(rafId)\n rafId = requestAnimationFrame(resizeIframe)\n }\n\n const handleLoad = () => {\n scheduleResize()\n\n try {\n const doc = iframe.contentDocument\n if (!doc) return\n\n Array.from(doc.images).forEach((img) => {\n img.addEventListener('load', scheduleResize)\n img.addEventListener('error', scheduleResize)\n })\n\n resizeObserver = new ResizeObserver(() => {\n scheduleResize()\n })\n\n resizeObserver.observe(doc.body)\n\n timeoutIds = [\n window.setTimeout(scheduleResize, 50),\n window.setTimeout(scheduleResize, 150),\n window.setTimeout(scheduleResize, 300),\n window.setTimeout(scheduleResize, 600),\n ]\n } catch {\n // ignore\n }\n }\n\n const handleResize = () => {\n scheduleResize()\n }\n\n iframe.addEventListener('load', handleLoad)\n window.addEventListener('resize', handleResize)\n\n return () => {\n iframe.removeEventListener('load', handleLoad)\n window.removeEventListener('resize', handleResize)\n\n if (rafId) cancelAnimationFrame(rafId)\n timeoutIds.forEach(clearTimeout)\n resizeObserver?.disconnect()\n\n try {\n const doc = iframe.contentDocument\n if (!doc) return\n\n Array.from(doc.images).forEach((img) => {\n img.removeEventListener('load', scheduleResize)\n img.removeEventListener('error', scheduleResize)\n })\n } catch {\n // ignore\n }\n }\n }, [cleanHtml])\n\n return (\n <iframe\n ref={ref}\n srcDoc={cleanHtml}\n sandbox=\"allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation\"\n className=\"block w-full border-0\"\n />\n )\n}\n\nexport default PostEmail\n","import React, { useMemo, FC } from 'react'\nimport { ItemData, PollItemData } from '../types'\nimport AsyncImage from './AsyncImage'\nimport Loader from './Loader'\nimport { postItemType } from '../utils/postItemType'\n\ninterface MediaProps {\n item: ItemData | PollItemData\n className: string\n handleLightbox?: (e: React.MouseEvent) => void\n additionalImagesCount?: number\n ratio?: number\n data?: ItemData[]\n isPostDetail?: boolean\n onCardPress?: () => void\n}\n\nconst MediaView: FC<MediaProps> = ({\n item,\n className,\n handleLightbox,\n additionalImagesCount,\n ratio,\n data,\n isPostDetail,\n onCardPress,\n}) => {\n const mediaSrc = useMemo(() => {\n if (\n item.type === postItemType.IMAGE_ITEM_TO_UPLOAD ||\n item.type === postItemType.MEDIA_ITEM_TO_UPLOAD\n ) {\n return URL.createObjectURL(item.file)\n }\n return item.sources?.original?.url ?? ''\n }, [item.file, item.sources?.original?.url, item.type])\n\n if (item.type === postItemType.POLL_TEXT_ITEM) {\n const textViewClass = `${className} aspect-square`\n return (\n <div\n key={(item as PollItemData).key}\n onClick={onCardPress}\n className={textViewClass}\n style={{\n backgroundColor: (item as PollItemData).option_color,\n }}\n >\n <div className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2\">\n <p className=\"text-center text-lg font-bold text-background\">\n {(item as PollItemData).text}\n </p>\n </div>\n </div>\n )\n }\n\n if (\n item.type === postItemType.IMAGE_ITEM ||\n item.type === postItemType.POLL_IMAGE_ITEM ||\n item.type === postItemType.GIF_ITEM ||\n item.type === postItemType.IMAGE_ITEM_TO_UPLOAD ||\n item.type === postItemType.MEDIA_ITEM ||\n item.type === postItemType.MEDIA_ITEM_TO_UPLOAD ||\n item.type === postItemType.POLL_MEDIA_ITEM\n ) {\n return (\n <div key={item.key} onClick={handleLightbox} className={className}>\n {item.type.includes('ToUpload') && <Loader type=\"upload_loader\" />}\n <AsyncImage\n alt={mediaSrc}\n src={mediaSrc}\n className={className}\n ratio={ratio}\n item={item}\n data={data || []}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n />\n {additionalImagesCount && (\n <div className=\"absolute right-1 top-0\">\n <p className=\"text-4xl font-bold text-muted-foreground\">{`+${additionalImagesCount}`}</p>\n </div>\n )}\n </div>\n )\n }\n\n return null\n}\n\nexport default MediaView\n","/* eslint-disable @next/next/no-img-element */\nimport React, { useCallback, useMemo } from 'react'\nimport { Gallery, Item } from 'react-photoswipe-gallery'\nimport { postItemType } from '../utils/postItemType'\nimport 'photoswipe/dist/photoswipe.css'\nimport Loader from './Loader'\nimport AppIcon from './AppIcon'\nimport { ItemData, PollItemData } from '../types'\n\ninterface Props {\n data?: ItemData[]\n item: PollItemData | ItemData\n onCardPress?: () => void\n src?: string\n alt?: string\n className?: string\n ratio: number | undefined\n isPostDetail?: boolean\n}\n\ninterface Placeholder {\n isBase64: boolean\n url: string\n}\n\nconst isVideo = (url: string) => {\n return (\n url?.toLowerCase().endsWith('.mp4') ||\n url?.toLowerCase().endsWith('.webm') ||\n url?.toLowerCase().endsWith('.ogg')\n )\n}\n\nconst isImage = (url: string) => {\n return (\n url?.toLowerCase().endsWith('.jpeg') ||\n url?.toLowerCase().endsWith('.jpg') ||\n url?.toLowerCase().endsWith('.png') ||\n url?.toLowerCase().endsWith('.webp') ||\n url?.toLowerCase().endsWith('.gif') ||\n url?.toLowerCase().endsWith('.avif')\n )\n}\n\nconst calVideoRatio = (width: number, height: number) => {\n let ratio = 1\n if (width > 0 && height > 0) {\n ratio = width / height\n if (ratio < 0.7) {\n ratio = 0.7\n }\n }\n return `${ratio}`\n}\n\nconst AsyncImage: React.FC<Props> = ({\n data,\n ratio,\n className,\n isPostDetail,\n item,\n onCardPress,\n src = '',\n alt,\n}) => {\n const {\n placeholder = {\n isBase64: false,\n url: '',\n },\n }: { placeholder: Placeholder } = item.sources || {}\n\n const placeholderUrl = useMemo(() => {\n const url = placeholder.isBase64\n ? `data:${item.imageType};base64,${placeholder.url}`\n : placeholder.url\n return url\n }, [placeholder.isBase64, placeholder.url, item.imageType])\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (onCardPress) {\n onCardPress()\n }\n },\n [onCardPress]\n )\n\n const showUploadImg = (item: PollItemData | ItemData) => {\n return item.imageType === 'image/heic' ? (\n <img\n src={src}\n alt={alt ?? ''}\n className={className}\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n />\n ) : (\n <div\n className={className}\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n ></div>\n )\n }\n\n const uploadVideoPost = item.type.includes('ToUpload')\n const showUploadingMedia = () => (\n <div\n className=\"relative h-full w-full\"\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n >\n {uploadVideoPost && <Loader type=\"upload_loader\" />}\n <video\n title=\"Video Upload Preview\"\n width={'100%'}\n height={'100%'}\n className={className}\n style={{\n aspectRatio: `${ratio}` || 'auto',\n }}\n >\n {item.file instanceof Blob && (\n <source src={URL.createObjectURL(item.file as Blob)} type={(item.file as File).type} />\n )}\n </video>\n <AppIcon\n name=\"video\"\n className={`absolute bottom-2 left-2 text-background`}\n />\n </div>\n )\n\n const renderMediaItem = useCallback(\n (media: ItemData) => {\n const originalInfo = media?.sources?.original || {}\n let thumbnailInfo = media?.sources?.thumbnail\n if (\n originalInfo?.url?.endsWith('gif') ||\n !isImage(media?.sources?.thumbnail?.url)\n ) {\n thumbnailInfo = originalInfo\n }\n\n const aspectRatio =\n `${ratio}` ||\n calVideoRatio(originalInfo.width, originalInfo.height) ||\n 'auto'\n const hasStableKeys = Boolean(media.key && item.key)\n const isCurrentItem = hasStableKeys\n ? media.key === item.key\n : originalInfo.url === src\n const display = isCurrentItem ? 'block' : 'none'\n\n const isBlobVideo =\n originalInfo?.url?.startsWith('blob:') &&\n typeof media.imageType === 'string' &&\n media.imageType.startsWith('video/')\n\n if (isBlobVideo) {\n return (\n <div\n key={media.key}\n onClick={handleClick}\n className={className + ' media-item'}\n style={{ aspectRatio, display }}\n >\n <video\n src={originalInfo.url}\n muted\n playsInline\n preload=\"metadata\"\n className={className}\n style={{\n aspectRatio,\n display: 'block',\n width: '100%',\n height: '100%',\n }}\n />\n <AppIcon\n name=\"video\"\n className=\"absolute bottom-2 left-2 text-background\"\n />\n <AppIcon\n name=\"circlePlay\"\n className=\"size-10 bg-foreground/20 hover:bg-foreground/40 transition-colors duration-300 rounded-full absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-background\"\n />\n </div>\n )\n }\n\n if (isVideo(originalInfo.url)) {\n return (\n <Item\n key={media.key}\n content={\n <div\n className=\"flex h-full w-full items-center justify-center\"\n style={{\n aspectRatio,\n }}\n >\n <video\n height={'100%'}\n width={'100%'}\n className=\"aspect-video\"\n controls\n autoPlay\n >\n <source src={originalInfo.url} type={media.imageType} />\n </video>\n </div>\n }\n >\n {({ ref, open }) => (\n <div onClick={isPostDetail ? open : handleClick}>\n <img\n src={thumbnailInfo.url}\n ref={ref as React.Ref<HTMLImageElement>}\n alt={alt ?? ''}\n className={className + ' media-item '}\n style={{\n aspectRatio,\n display,\n }}\n onClick={isPostDetail ? open : handleClick}\n />\n <AppIcon\n name=\"video\"\n className={`absolute bottom-2 left-2 text-background`}\n onClick={isPostDetail ? open : handleClick}\n ref={ref as React.Ref<HTMLImageElement>}\n style={{\n aspectRatio,\n display,\n }}\n />\n <AppIcon\n name=\"circlePlay\"\n className={`size-10 bg-foreground/20 hover:bg-foreground/40 transition-colors duration-300 rounded-full absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-3xl text-background`}\n onClick={isPostDetail ? open : handleClick}\n ref={ref as React.Ref<HTMLImageElement>}\n style={{\n aspectRatio,\n display,\n }}\n />\n </div>\n )}\n </Item>\n )\n }\n\n return (\n <Item\n key={media.key}\n width={originalInfo.width}\n height={originalInfo.height}\n original={originalInfo.url}\n thumbnail={thumbnailInfo.url}\n >\n {({ open, ref }) => (\n <img\n onClick={isPostDetail ? open : handleClick}\n ref={ref as React.Ref<HTMLImageElement>}\n src={originalInfo.url || thumbnailInfo.url}\n alt={alt ?? ''}\n className={className}\n style={{\n aspectRatio,\n display,\n }}\n />\n )}\n </Item>\n )\n },\n [className, handleClick, isPostDetail, item.key, ratio, src]\n )\n\n const handleMediaItems = () => {\n return (\n <Gallery options={{ showHideAnimationType: 'fade' }}>\n {data?.map((media: ItemData) => renderMediaItem(media))}\n </Gallery>\n )\n }\n\n return (\n <div\n style={{\n backgroundImage: `url(${placeholderUrl})`,\n }}\n className=\"h-full w-full bg-cover bg-center bg-no-repeat\"\n >\n {item.type === postItemType.MEDIA_ITEM_TO_UPLOAD && showUploadingMedia()}\n {item.type === postItemType.IMAGE_ITEM_TO_UPLOAD && showUploadImg(item)}\n {item.type !== postItemType.IMAGE_ITEM_TO_UPLOAD &&\n item.type !== postItemType.MEDIA_ITEM_TO_UPLOAD &&\n handleMediaItems()}\n </div>\n )\n}\n\nexport default AsyncImage\n","import React from 'react'\n\ninterface LoaderProps {\n type?: string\n fullScreen?: boolean\n}\n\nconst Loader: React.FC<LoaderProps> = ({\n type = 'page_loader',\n fullScreen = false,\n}) => {\n const style: Record<string, string> = {\n page_loader: 'after:border-border after:border-t-action-primary',\n upload_loader:\n 'after:border-foreground after:border-t-background bg-foreground rounded-full',\n }\n const showLoader = () => {\n return (\n <div className=\"absolute left-1/2 top-1/2 z-20 -translate-x-1/2 -translate-y-1/2\">\n <div\n className={`after:contents-[''] flex h-full items-center justify-center after:h-10 after:w-10 after:animate-spin after:rounded-[50%] after:border-4 ${style[type]} `}\n ></div>\n </div>\n )\n }\n if (fullScreen) {\n return (\n <div className=\"h-screen-safe-14 lg:h-screen-safe-16\">{showLoader()}</div>\n )\n }\n return showLoader()\n}\n\nexport default Loader\n","import type { PollItemData, PollResult } from '../../types'\n\nexport const getOptionRateV2 = (\n item: PollItemData,\n voteResult: PollResult | null\n): string => {\n if (!voteResult) return '0%'\n const voteItem = voteResult.options.find(\n (option) => option.option_id === item.option_id\n )\n const totalCount = voteResult.options.reduce(\n (total, option) => total + option.count,\n 0\n )\n if (voteItem && totalCount > 0) {\n return ((voteItem.count / totalCount) * 100).toFixed(0) + '%'\n }\n return '0%'\n}\n\nexport const getVoteInfo = (\n item: PollItemData,\n voteResult: PollResult | null\n): { rate: string; isAppOwnerVoted: boolean; isVoteItem: boolean } => {\n const isAppOwnerVoted = !!voteResult?.user_vote_option_id\n const isVoteItem = !!voteResult?.options.find(\n (option) =>\n option.option_id === item.option_id &&\n option.option_id === voteResult.user_vote_option_id\n )\n return {\n rate: getOptionRateV2(item, voteResult),\n isAppOwnerVoted,\n isVoteItem,\n }\n}\n","import React from 'react'\nimport AppIcon from '../AppIcon'\nimport type { PollItemData, PollResult } from '../../types'\nimport { getVoteInfo } from './pollUtils'\n\ntype Props = {\n type: 'NORMAL' | 'SINGLE_LEFT' | 'SINGLE_RIGHT'\n index: number\n item: PollItemData\n voteResult: PollResult | null\n isPostOwner?: boolean\n}\n\nconst PostPollIResultView: React.FC<Props> = ({\n type,\n item,\n voteResult,\n isPostOwner,\n}) => {\n const voteInfo = getVoteInfo(item, voteResult)\n const textCss = voteInfo.isVoteItem ? '#FFFFFF' : item.option_color\n const backgroundCss = voteInfo.isVoteItem ? item.option_color : '#FFFFFF'\n const totalVotes =\n voteResult?.options.reduce((sum, o) => sum + o.count, 0) ?? 0\n\n if ((!voteInfo.isAppOwnerVoted && !isPostOwner) || totalVotes === 0) {\n return null\n }\n\n if (type === 'SINGLE_LEFT') {\n return (\n <div\n className=\"absolute top-0 m-6 flex flex-row items-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md\"\n style={{ backgroundColor: backgroundCss }}\n >\n <p className=\"text-sm font-bold\" style={{ color: textCss }}>\n {voteInfo.rate}\n </p>\n <AppIcon\n name=\"thumbUp\"\n size={16}\n className=\"ml-2\"\n style={{ color: textCss }}\n />\n </div>\n )\n }\n\n if (type === 'SINGLE_RIGHT') {\n return (\n <div\n className=\"absolute right-0 top-0 m-6 flex flex-row items-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md\"\n style={{ backgroundColor: backgroundCss }}\n >\n <p className=\"text-sm font-bold\" style={{ color: textCss }}>\n {voteInfo.rate}\n </p>\n <AppIcon\n name=\"thumbDown\"\n size={16}\n className=\"ml-2\"\n style={{ color: textCss }}\n />\n </div>\n )\n }\n\n return (\n <div\n className=\"absolute top-0 m-3 flex items-center justify-center rounded-full px-4 py-2 shadow-sm backdrop-blur-md\"\n style={{ backgroundColor: backgroundCss }}\n >\n <p className=\"text-sm font-bold\" style={{ color: textCss }}>\n {voteInfo.rate}\n </p>\n </div>\n )\n}\n\nexport default PostPollIResultView\n","import React from 'react'\nimport AppIcon from '../AppIcon'\nimport type { PollItemData, PollResult } from '../../types'\nimport { getVoteInfo } from './pollUtils'\n\ninterface Props {\n type: 'NORMAL' | 'SINGLE_LEFT' | 'SINGLE_RIGHT'\n onVotePress: (item: PollItemData) => void\n item: PollItemData\n voteResult: PollResult | null\n}\n\nconst PostPollIButtonView: React.FC<Props> = ({\n type,\n item,\n voteResult,\n onVotePress,\n}) => {\n const voteInfo = getVoteInfo(item, voteResult)\n\n const handleVoting = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n if (!voteInfo.isVoteItem) onVotePress(item)\n }\n\n const voteLabel = voteInfo.isVoteItem\n ? `Voted: ${item.text || 'this option'}`\n : `Vote for ${item.text || 'this option'}`\n\n if (type === 'SINGLE_LEFT') {\n const nonVoteClassName =\n 'absolute bottom-0 left-0 m-6 flex size-11 items-center justify-center rounded-full bg-black/30 backdrop-blur-sm border border-background/20 cursor-pointer transition-all duration-200 hover:bg-black/50'\n\n const voteClassName =\n 'absolute bottom-0 left-0 m-6 flex size-11 items-center justify-center rounded-full bg-background shadow-lg cursor-pointer transition-all duration-200'\n return (\n <button\n className={voteInfo.isVoteItem ? voteClassName : nonVoteClassName}\n onClick={handleVoting}\n aria-label={voteLabel}\n aria-pressed={voteInfo.isVoteItem}\n >\n <AppIcon\n name=\"thumbUp\"\n size={20}\n aria-hidden=\"true\"\n className={voteInfo.isVoteItem ? '' : 'text-white'}\n style={voteInfo.isVoteItem ? { color: item.option_color } : {}}\n />\n </button>\n )\n }\n\n if (type === 'SINGLE_RIGHT') {\n const nonVoteClassName =\n 'absolute bottom-0 right-0 m-6 flex size-11 items-center justify-center rounded-full bg-black/30 backdrop-blur-sm border border-background/20 cursor-pointer transition-all duration-200 hover:bg-black/50'\n\n const voteClassName =\n 'absolute bottom-0 right-0 m-6 flex size-11 items-center justify-center rounded-full bg-background shadow-lg cursor-pointer transition-all duration-200'\n return (\n <button\n className={voteInfo.isVoteItem ? voteClassName : nonVoteClassName}\n onClick={handleVoting}\n aria-label={voteLabel}\n aria-pressed={voteInfo.isVoteItem}\n >\n <AppIcon\n name=\"thumbDown\"\n size={20}\n aria-hidden=\"true\"\n className={voteInfo.isVoteItem ? '' : 'text-white'}\n style={voteInfo.isVoteItem ? { color: item.option_color } : {}}\n />\n </button>\n )\n }\n\n const nonVoteClassName =\n 'absolute bottom-3 right-3 rounded-full p-1 backdrop-blur-md border border-background/40 bg-background/20 hover:bg-background/30 scale-100 transition-all duration-300 z-20 cursor-pointer'\n\n const voteClassName =\n 'absolute bottom-3 right-3 rounded-full p-1 backdrop-blur-md border border-action-primary bg-action-primary scale-110 transition-all duration-300 z-20 cursor-pointer'\n\n return (\n <button\n className={voteInfo.isVoteItem ? voteClassName : nonVoteClassName}\n style={\n voteInfo.isVoteItem && item.option_color\n ? {\n backgroundColor: item.option_color,\n borderColor: item.option_color,\n }\n : undefined\n }\n onClick={handleVoting}\n aria-label={voteLabel}\n aria-pressed={voteInfo.isVoteItem}\n >\n <AppIcon\n name=\"checkCircle2\"\n aria-hidden=\"true\"\n className={`size-8 ${voteInfo.isVoteItem ? 'text-white' : 'text-white/90 drop-shadow-md'}`}\n />\n </button>\n )\n}\n\nexport default PostPollIButtonView\n","import React from 'react'\nimport type { PollItemData, PollResult } from '../../types'\nimport MediaView from '../MediaView'\nimport PostPollIResultView from './PostPollIResultView'\nimport PostPollIButtonView from './PostPollIButtonView'\n\ninterface Props {\n items: PollItemData[]\n voteResult: PollResult | null\n onVotePress: (item: PollItemData) => void\n onCardPress: () => void\n isPostDetail: boolean\n isInboxCard?: boolean\n isPostOwner?: boolean\n}\n\nconst PostPollLayoutOne: React.FC<Props> = ({\n items,\n voteResult,\n onVotePress,\n onCardPress,\n isPostDetail,\n isInboxCard,\n isPostOwner,\n}) => {\n const { sources } = items[0]\n let ratio = 1\n if (!isInboxCard && sources && sources.original) {\n const { width, height } = sources.original\n if (width > 0 && height > 0) {\n ratio = width / height\n if (ratio < 0.7) {\n // to avoid the layout too high\n ratio = 0.7\n }\n }\n }\n\n const className = 'object-cover w-full'\n return (\n <div className=\"not-prose relative w-full box-border\">\n <div className=\"relative w-full bg-gray-100\">\n <MediaView\n item={items[0]}\n className={className}\n data={[items[0]]}\n ratio={ratio}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n />\n <PostPollIResultView\n type=\"SINGLE_LEFT\"\n item={items[0]}\n index={0}\n voteResult={voteResult}\n isPostOwner={isPostOwner}\n />\n <PostPollIButtonView\n type=\"SINGLE_LEFT\"\n item={items[0]}\n voteResult={voteResult}\n onVotePress={onVotePress}\n />\n <PostPollIResultView\n type=\"SINGLE_RIGHT\"\n item={items[1]}\n index={1}\n voteResult={voteResult}\n isPostOwner={isPostOwner}\n />\n <PostPollIButtonView\n type=\"SINGLE_RIGHT\"\n item={items[1]}\n voteResult={voteResult}\n onVotePress={onVotePress}\n />\n </div>\n </div>\n )\n}\n\nexport default PostPollLayoutOne\n","import React from 'react'\nimport type { PollItemData, PollResult } from '../../types'\nimport MediaView from '../MediaView'\nimport PostPollIResultView from './PostPollIResultView'\nimport PostPollIButtonView from './PostPollIButtonView'\n\ninterface Props {\n items: PollItemData[]\n voteResult: PollResult | null\n onVotePress: (item: PollItemData) => void\n onCardPress: () => void\n isPostDetail: boolean\n isPostOwner?: boolean\n}\n\nconst GRID_CLASS: Record<number, string> = {\n 2: 'grid grid-flow-col grid-cols-2 grid-rows-1 gap-0.5 bg-gray-100',\n 3: 'grid grid-cols-2 grid-rows-1 gap-0.5 bg-gray-100',\n 4: 'grid grid-flow-row grid-cols-2 grid-rows-2 gap-0.5 bg-gray-100',\n}\n\nconst PostPollLayoutGrid: React.FC<Props> = ({\n items,\n voteResult,\n onVotePress,\n onCardPress,\n isPostDetail,\n isPostOwner,\n}) => {\n const gridClass = GRID_CLASS[items.length] ?? GRID_CLASS[4]\n\n return (\n <div className=\"not-prose w-full box-border\">\n <div className={gridClass}>\n {items.map((item, index) => (\n <div key={item.option_id || index} className=\"relative group\">\n <MediaView\n item={item}\n className=\"aspect-[1] col-span-1 object-cover w-full\"\n data={items}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n />\n <PostPollIResultView\n type=\"NORMAL\"\n item={item}\n index={index}\n voteResult={voteResult}\n isPostOwner={isPostOwner}\n />\n <PostPollIButtonView\n type=\"NORMAL\"\n item={item}\n voteResult={voteResult}\n onVotePress={onVotePress}\n />\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nexport default PostPollLayoutGrid\n","import React from 'react'\nimport { PollItemData } from '../types'\nimport PostPollLayoutOne from './PostPollLayout/PostPollLayoutOne'\nimport PostPollLayoutGrid from './PostPollLayout/PostPollLayoutGrid'\nimport { PollResult } from '../types'\n\ninterface Props {\n items: PollItemData[]\n voteResult: PollResult | null\n onVotePress: (item: PollItemData) => void\n onCardPress: () => void\n isPostDetail: boolean\n isInboxCard?: boolean\n isPostOwner?: boolean\n}\n\nconst PostPollView: React.FC<Props> = ({\n items,\n voteResult,\n onVotePress,\n onCardPress,\n isPostDetail,\n isInboxCard,\n isPostOwner,\n}) => {\n const isSingleChoicePoll = items.length === 2 && items[0].key === items[1].key\n\n if (isSingleChoicePoll) {\n return (\n <PostPollLayoutOne\n isInboxCard={isInboxCard}\n onVotePress={onVotePress}\n items={items}\n voteResult={voteResult}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n isPostOwner={isPostOwner}\n />\n )\n }\n\n if (items.length >= 2 && items.length <= 4) {\n return (\n <PostPollLayoutGrid\n onVotePress={onVotePress}\n items={items}\n voteResult={voteResult}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n isPostOwner={isPostOwner}\n />\n )\n }\n\n return null\n}\n\nexport default PostPollView\n","import React from 'react'\nimport TruncateText from '../resolver/TruncateText'\nimport AutoLink from './AutoLink'\nimport type { TextItemContent } from '../resolver/postContentResolver'\nimport type { MentionData } from '../types'\n\ninterface Props {\n textItems: TextItemContent['items']\n showFullText: boolean\n isPostDetail: boolean\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n}\n\nconst PostTextItem: React.FC<Props> = ({\n textItems,\n showFullText,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n}) => {\n return (\n <div className=\"flex-1\">\n <div>\n {textItems.map((item, index) => {\n const text = 'text' in item ? (item.text ?? '') : ''\n const key = 'key' in item ? item.key : index\n const mentionData =\n 'mentionData' in item\n ? (item.mentionData as MentionData[])\n : undefined\n return (\n <AutoLink\n key={key}\n text={showFullText ? text : TruncateText(text, 300)}\n mentionData={mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n />\n )\n })}\n </div>\n </div>\n )\n}\n\nexport default PostTextItem\n","import React, { useState } from 'react'\nimport { cn } from '../utils/cn'\nimport AppIcon from './AppIcon'\nimport { LinkItemMetaData } from '../types'\n\n// Helper to extract host from URL\nconst getHostFromUrl = (url?: string): string => {\n if (!url) return ''\n try {\n return new URL(url).host\n } catch {\n return url\n }\n}\n\n// Helper to determine link rel attribute\nconst getLinkRel = (\n host: string,\n supportDeepviewDomain: string | string[] = ''\n): string => {\n const domains = Array.isArray(supportDeepviewDomain)\n ? supportDeepviewDomain\n : supportDeepviewDomain\n ? [supportDeepviewDomain]\n : []\n const isInternal = domains.some((d) => d.length > 0 && host.includes(d))\n return isInternal ? 'noreferrer' : 'noreferrer nofollow'\n}\n\ninterface PostLinkItemProps {\n linkItems: LinkItemMetaData[]\n imageComponent?: React.ComponentType<{ src: string; alt: string; className?: string }>\n onCloseClick?: () => void\n type?: 'preview' | 'display'\n supportDeepviewDomain?: string | string[]\n}\n\nconst PostLinkItem: React.FC<PostLinkItemProps> = ({\n linkItems,\n imageComponent: ImageComponent,\n onCloseClick,\n type = 'display',\n supportDeepviewDomain = '',\n}) => {\n const [imageError, setImageError] = useState(false)\n\n if (linkItems.length === 0) {\n return null\n }\n\n const { linkUrl, linkTitle, linkDesc, linkImage } = linkItems[0] || {}\n const host = getHostFromUrl(linkUrl)\n const linkRel = getLinkRel(host, supportDeepviewDomain)\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n if (linkUrl) window.open(linkUrl, '_blank', 'noopener,noreferrer')\n }\n\n // Render image (with fallback to plain img if no imageComponent provided)\n const renderImage = (\n src: string,\n alt: string,\n aspectClassName: string,\n containerClassName: string\n ) => {\n if (imageError || !src) return null\n\n return (\n <div className={containerClassName}>\n <div className={aspectClassName}>\n {ImageComponent ? (\n <ImageComponent\n src={src}\n alt={alt}\n className=\"w-full h-full object-cover rounded-t-md\"\n />\n ) : (\n <img\n src={src}\n alt={alt}\n className=\"w-full h-full object-cover rounded-t-md\"\n onError={() => setImageError(true)}\n />\n )}\n </div>\n </div>\n )\n }\n\n // Legacy card style — used in comments\n if (type === 'preview') {\n const aspectRatio =\n linkImage &&\n linkImage.height > linkImage.width &&\n linkImage.height / linkImage.width > 0.7\n ? 'aspect-[0.7]'\n : 'aspect-video'\n\n return (\n <section\n className=\"not-prose min-w-96 relative cursor-pointer rounded-lg border border-border bg-background\"\n onClick={handleClick}\n role=\"link\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick(e as unknown as React.MouseEvent)\n }\n }}\n >\n {linkImage?.url && !imageError && (\n <div className=\"relative w-full\">\n {ImageComponent ? (\n <div className={`relative w-full ${aspectRatio}`}>\n <ImageComponent\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover rounded-t-md\"\n />\n </div>\n ) : (\n <div className={`relative w-full ${aspectRatio}`}>\n <img\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover rounded-t-md\"\n onError={() => setImageError(true)}\n />\n </div>\n )}\n </div>\n )}\n {typeof onCloseClick === 'function' && (\n <AppIcon\n name=\"cancel\"\n onClick={(e) => {\n e.stopPropagation()\n onCloseClick()\n }}\n className=\"absolute -right-2 -top-3 rounded-full bg-background size-4.5 hover:cursor-pointer hover:opacity-70\"\n />\n )}\n <section className=\"flex flex-col gap-1 p-3\">\n <a href={linkUrl} className=\"hidden\" rel={linkRel} tabIndex={-1} />\n <p\n className=\"wrap-break-word text-xs font-normal leading-4 text-muted-foreground\"\n data-test-id=\"post-link-host\"\n >\n {host}\n </p>\n <p\n className=\"text-clip-1 text-ellipsis wrap-break-word text-base leading-6\"\n data-test-id=\"post-link-title\"\n >\n {linkTitle}\n </p>\n <p\n className=\"text-clip-2 text-ellipsis wrap-break-word text-xs font-normal leading-5 tracking-tight text-muted-foreground\"\n data-test-id=\"post-link-desc\"\n >\n {linkDesc}\n </p>\n </section>\n </section>\n )\n }\n\n // New overlay style — used in posts and embed fallbacks\n return (\n <section\n className={cn('not-prose relative cursor-pointer group overflow-hidden')}\n onClick={handleClick}\n role=\"link\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick(e as unknown as React.MouseEvent)\n }\n }}\n >\n <div className=\"aspect-video relative\">\n <div className=\"max-w-200 max-h-100 size-full relative\">\n {linkImage?.url && !imageError && (\n <>\n {ImageComponent ? (\n <ImageComponent\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover transition-transform duration-700 group-hover:scale-105\"\n />\n ) : (\n <img\n src={linkImage.url}\n alt={linkTitle || 'Link preview image'}\n className=\"w-full h-full object-cover transition-transform duration-700 group-hover:scale-105\"\n onError={() => setImageError(true)}\n />\n )}\n </>\n )}\n </div>\n <div className=\"absolute inset-0 bg-linear-to-t from-black/90 via-black/40 to-transparent opacity-90 group-hover:opacity-100 transition-opacity\"></div>\n {typeof onCloseClick === 'function' && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onCloseClick()\n }}\n className=\"absolute top-2 right-2 bg-black/40 text-white rounded-full p-1 hover:bg-black/60 cursor-pointer border-none flex items-center justify-center transition-colors shadow-sm z-10\"\n aria-label=\"Remove link preview\"\n >\n <AppIcon name=\"cancel\" size={16} strokeWidth={2} />\n </button>\n )}\n <div className=\"absolute bottom-0 left-0 right-0 p-5 transform transition-transform duration-300 z-10 pointer-events-none\">\n <a\n href={linkUrl}\n className=\"hidden pointer-events-auto\"\n rel={linkRel}\n tabIndex={-1}\n />\n <div className=\"flex items-center gap-2 text-xs text-white/70 mb-2\">\n <AppIcon name=\"externalLink\" className=\"w-3.5 h-3.5\" />\n <span className=\"uppercase tracking-wider font-medium\">{host}</span>\n </div>\n <h3 className=\"font-semibold text-white text-xl leading-tight mb-1.5 group-hover:text-action-primary transition-colors line-clamp-2\">\n {linkTitle}\n </h3>\n {linkDesc && (\n <p className=\"text-white/70 text-sm line-clamp-2\">{linkDesc}</p>\n )}\n </div>\n </div>\n </section>\n )\n}\n\nexport default PostLinkItem\n","import React, { useMemo, useState } from 'react'\nimport PostLinkItem from './PostLinkItem'\nimport type { EmbedContent } from '../resolver/postContentResolver'\nimport { SPOTIFY_HEIGHT } from '../resolver/constants/embeds'\n\ninterface Props {\n embed: EmbedContent\n}\n\nconst TRUSTED_HOSTS: Record<string, string[]> = {\n youtube: ['www.youtube.com', 'youtube.com'],\n spotify: ['open.spotify.com'],\n}\n\nconst isTrustedEmbedUrl = (provider: string, url: string) => {\n try {\n const u = new URL(url)\n if (u.protocol !== 'https:') return false\n const allowed = TRUSTED_HOSTS[provider] ?? []\n return allowed.includes(u.hostname.toLowerCase())\n } catch {\n return false\n }\n}\n\nconst PostEmbedView: React.FC<Props> = ({ embed }) => {\n const [hasError, setHasError] = useState(false)\n\n const canRender = useMemo(() => {\n return (\n !hasError &&\n !!embed.embedUrl &&\n isTrustedEmbedUrl(embed.provider, embed.embedUrl)\n )\n }, [hasError, embed.embedUrl, embed.provider])\n\n const linkItem = {\n linkUrl: embed.originalUrl,\n linkTitle: embed.preview?.title || embed.originalUrl,\n linkDesc: embed.preview?.description || '',\n linkImage: embed.preview?.image ?? undefined,\n linkIcon: '',\n type: 'linkItem',\n } as const\n\n if (!canRender) return <PostLinkItem linkItems={[linkItem]} />\n\n const isYouTube = embed.provider === 'youtube'\n const isSpotify = embed.provider === 'spotify'\n\n return (\n <div className=\"w-full px-4 pb-4 not-first:pt-4\">\n <div\n className=\"relative w-full overflow-hidden rounded-xl\"\n style={{ height: embed.height || SPOTIFY_HEIGHT }}\n >\n <iframe\n src={embed.embedUrl}\n className=\"absolute inset-0 h-full w-full\"\n loading=\"lazy\"\n sandbox=\"allow-scripts allow-same-origin allow-presentation\"\n allow={\n isYouTube\n ? 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n : isSpotify\n ? 'autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture'\n : ''\n }\n allowFullScreen={isYouTube}\n referrerPolicy=\"no-referrer-when-downgrade\"\n title={embed.preview?.title || `${embed.provider} embed`}\n style={{ border: 0 }}\n onError={() => setHasError(true)}\n />\n </div>\n </div>\n )\n}\n\nexport default PostEmbedView\n","import React from 'react'\nimport type { MediaUploadStatus } from '../../types'\nimport AppIcon from '../AppIcon'\n\ninterface Props {\n status?: MediaUploadStatus\n /** Tile width in px. Status text is hidden when < 100. */\n tileWidth?: number\n}\n\nconst MediaUploadStatusOverlay: React.FC<Props> = ({ status, tileWidth }) => {\n if (!status) return null\n\n const showText = !tileWidth || tileWidth >= 100\n\n if (status === 'uploading' || status === 'processing') {\n return (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 bg-overlay-scrim\">\n <AppIcon name=\"loader\" className=\"size-6 animate-spin text-background\" />\n {showText && (\n <span className=\"text-xs font-medium text-background\">\n {status === 'uploading' ? 'Uploading' : 'Processing'}\n </span>\n )}\n </div>\n )\n }\n\n if (status === 'uploaded') {\n return (\n <div className=\"absolute inset-0 flex items-center justify-center bg-feedback-success/15\">\n <div className=\"flex size-8 items-center justify-center rounded-full bg-foreground/60\">\n <AppIcon name=\"check\" className=\"size-5 text-background\" />\n </div>\n </div>\n )\n }\n\n // status === 'error'\n return (\n <div className=\"absolute inset-0 flex items-center justify-center bg-feedback-danger/20\">\n <div className=\"flex size-8 items-center justify-center rounded-full bg-foreground/60\">\n <span className=\"text-base font-bold text-background\">!</span>\n </div>\n </div>\n )\n}\n\nexport default MediaUploadStatusOverlay\n","import React from 'react'\nimport type { ItemData, MediaUploadStatus } from '../../types'\nimport MediaView from '../MediaView'\nimport MediaUploadStatusOverlay from './MediaUploadStatusOverlay'\n\n// Types\ninterface PostMediaLayoutProps {\n items: ItemData[]\n parentId?: string\n isPostDetail?: boolean\n onCardPress?: () => void\n mediaItemStatuses?: Record<string, MediaUploadStatus>\n}\n\ninterface GridLayout {\n gridColsClass: string\n gridSpan: number[]\n colSpanClasses: string[]\n itemRatio: number[]\n}\n\nconst gridLayoutData: Record<number, GridLayout> = {\n 1: {\n gridColsClass: 'grid-cols-1',\n gridSpan: [1],\n colSpanClasses: ['col-span-1'],\n itemRatio: [1],\n },\n 2: {\n gridColsClass: 'grid-cols-2',\n gridSpan: [1, 1],\n colSpanClasses: ['col-span-1', 'col-span-1'],\n itemRatio: [1, 1],\n },\n 3: {\n gridColsClass: 'grid-cols-2',\n gridSpan: [2, 1, 1],\n colSpanClasses: ['col-span-2', 'col-span-1', 'col-span-1'],\n itemRatio: [1.5, 1.5, 1.5],\n },\n 4: {\n gridColsClass: 'grid-cols-2',\n gridSpan: [1, 1, 1, 1],\n colSpanClasses: ['col-span-1', 'col-span-1', 'col-span-1', 'col-span-1'],\n itemRatio: [1, 1, 1, 1],\n },\n 5: {\n gridColsClass: 'grid-cols-6',\n gridSpan: [3, 3, 2, 2, 2],\n colSpanClasses: [\n 'col-span-3',\n 'col-span-3',\n 'col-span-2',\n 'col-span-2',\n 'col-span-2',\n ],\n itemRatio: [1.5, 1.5, 1, 1, 1],\n },\n}\n\nexport const PostMediaLayoutCore: React.FC<PostMediaLayoutProps> = ({\n items,\n parentId: _parentId,\n isPostDetail,\n onCardPress,\n mediaItemStatuses,\n}) => {\n if (!items?.length) {\n return null\n }\n\n const slicedData = items.slice(0, 5)\n const { gridColsClass, colSpanClasses, itemRatio } =\n gridLayoutData[slicedData.length]\n\n return (\n <div className=\"not-prose w-full box-border\">\n <div\n className={`grid ${gridColsClass} cursor-pointer grid-rows-1 gap-0.5 bg-muted`}\n >\n {slicedData.map((slicedItem, index) => {\n let ratio = 1\n if (slicedData.length === 1) {\n const { width, height } = slicedItem.type.includes('ToUpload')\n ? (slicedItem.file as any)\n : (slicedItem.sources?.original ?? {})\n\n const safeWidth = width ?? 1\n const safeHeight = height ?? 1\n\n ratio = safeWidth / safeHeight\n if (ratio < 0.7) {\n ratio = 0.7\n }\n } else {\n ratio = itemRatio[index]\n }\n\n const className = `w-full h-full relative ${colSpanClasses[index]} object-cover`\n return (\n <div key={index} className={`relative ${colSpanClasses[index]}`}>\n <MediaView\n item={slicedItem}\n ratio={ratio}\n className={className}\n additionalImagesCount={\n index === slicedData.length - 1 && items.length > 5\n ? items.length - slicedData.length\n : undefined\n }\n data={items}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n />\n <MediaUploadStatusOverlay\n status={mediaItemStatuses?.[slicedItem.key]}\n />\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n\nexport default PostMediaLayoutCore\n","import React from 'react'\nimport type { PollItemData, MediaUploadStatus } from '../types'\nimport PostPollView from './PostPollView'\nimport PostTextItem from './PostTextItem'\nimport PostLinkItem from './PostLinkItem'\nimport PostEmbedView from './PostEmbedView'\nimport PostMediaLayout from './PostMediaLayout/PostMediaLayoutCore'\nimport type { PrimaryContent } from '../resolver/postContentResolver'\n\ninterface Props {\n primaryContent: PrimaryContent\n isPostDetail: boolean\n onCardPress: () => void\n onVotePress: (item: PollItemData) => void\n isPostOwner?: boolean\n parentId?: string\n isCommentScope?: boolean\n imageComponent?: React.ComponentType<{ src: string; alt: string; className?: string }>\n mediaItemStatuses?: Record<string, MediaUploadStatus>\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n}\n\nconst PostItemsView: React.FC<Props> = ({\n primaryContent,\n isPostDetail,\n onCardPress,\n onVotePress,\n isPostOwner,\n parentId,\n isCommentScope,\n imageComponent,\n mediaItemStatuses,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n}) => {\n if (!primaryContent) return null\n\n switch (primaryContent.type) {\n case 'embed':\n return <PostEmbedView embed={primaryContent} />\n\n case 'poll':\n return (\n <PostPollView\n items={primaryContent.items}\n voteResult={primaryContent.pollResult}\n onVotePress={onVotePress}\n onCardPress={onCardPress}\n isPostDetail={isPostDetail}\n isPostOwner={isPostOwner}\n />\n )\n\n case 'link':\n return (\n <PostLinkItem\n linkItems={[\n {\n linkUrl: primaryContent.linkUrl,\n linkTitle: primaryContent.title,\n linkDesc: primaryContent.description,\n linkImage: primaryContent.image ?? undefined,\n linkIcon: '',\n type: 'linkItem',\n },\n ]}\n imageComponent={imageComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )\n\n case 'media':\n return (\n <PostMediaLayout\n items={primaryContent.items}\n parentId={parentId}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n mediaItemStatuses={mediaItemStatuses}\n />\n )\n\n case 'textItem':\n return (\n <PostTextItem\n textItems={primaryContent.items}\n showFullText={isPostDetail}\n isPostDetail={isPostDetail}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )\n\n default:\n return null\n }\n}\n\nexport default PostItemsView\n","import React, { useCallback } from 'react'\nimport { contentTypeConstants } from '../utils/contentTypeConstants'\nimport AutoLink from './AutoLink'\nimport PostSectionSourceInfoView from './PostSectionSourceInfoView'\nimport PostMediaLayout from './PostMediaLayout/PostMediaLayoutCore'\nimport type { SectionItem } from '../resolver/postContentResolver'\n\ninterface Props {\n sections: SectionItem[]\n isPostDetail: boolean\n onCardPress: () => void\n onNavigate?: (href: string, isInternal: boolean) => void\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n supportDeepviewDomain?: string | string[]\n imageComponent?: React.ComponentType<{\n src: string\n alt: string\n fill?: boolean\n placeholder?: 'blur' | 'empty'\n blurDataURL?: string\n priority?: boolean\n className?: string\n }>\n}\n\nconst PostSectionsView: React.FC<Props> = ({\n sections,\n isPostDetail,\n onCardPress,\n onNavigate,\n linkComponent,\n supportDeepviewDomain,\n imageComponent,\n}) => {\n const renderSectionItem = useCallback(\n (section: SectionItem, index: number) => {\n const { type, data } = section\n if (type === contentTypeConstants.NEW_POST_MESSAGE) {\n return (\n <AutoLink\n key={`${index} - ${data.body}`}\n text={data.body || ''}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={data.mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )\n }\n if (type === contentTypeConstants.NEW_POST_MEDIA) {\n return (\n <div key={`${index} - ${data.body}`} className=\"my-3\">\n {data.sourceInfo && (\n <PostSectionSourceInfoView\n sourceInfo={data.sourceInfo}\n imageComponent={imageComponent}\n />\n )}\n {data.body && (\n <AutoLink\n key={`${index} - ${data.body}`}\n text={data.body || ''}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={data.mentionData}\n onNavigate={onNavigate}\n linkComponent={linkComponent}\n supportDeepviewDomain={supportDeepviewDomain}\n />\n )}\n {data.items && (\n <PostMediaLayout\n items={data.items}\n isPostDetail={isPostDetail}\n onCardPress={onCardPress}\n />\n )}\n </div>\n )\n }\n return null\n },\n [isPostDetail, onCardPress, onNavigate, supportDeepviewDomain, imageComponent]\n )\n\n if (!sections || sections.length === 0) {\n return null\n }\n\n return (\n <div className=\"space-y-2\">\n {sections.map((section, index) => {\n return renderSectionItem(section, index)\n })}\n </div>\n )\n}\n\nexport default PostSectionsView\n","// Verbatim port of contentTypeConstants (and its dependency contentTypeRules)\n// from web client src/Constants.ts\n// These values must match the backend exactly — do not rename or change values.\n\nconst contentTypeRules = {\n NEW_MESSAGE: 'new:message',\n NEW_POST: 'new:post',\n NEW_COMMENT: 'new:comment',\n EVENT: 'event',\n} as const\n\nexport const contentTypeConstants = {\n TO_BE_DELETE: 'tobedelete',\n NEW_GROUP: 'new:group',\n LOAD_MORE_CONTENT: 'loadMoreContent',\n NEW_MESSAGE: `${contentTypeRules.NEW_MESSAGE}:text`,\n NEW_MESSAGE_GUGGY: `${contentTypeRules.NEW_MESSAGE}:gif`,\n NEW_MESSAGE_VOICE: `${contentTypeRules.NEW_MESSAGE}:voice`,\n NEW_POST_IMAGE: `${contentTypeRules.NEW_POST}:image`,\n NEW_POST_MEDIA: `${contentTypeRules.NEW_POST}:media`,\n NEW_POST_POLL: `${contentTypeRules.NEW_POST}:poll`,\n NEW_POST_LINK: `${contentTypeRules.NEW_POST}:link`,\n NEW_POST_MESSAGE: `${contentTypeRules.NEW_POST}:text`,\n NEW_POST_THREAD: `${contentTypeRules.NEW_POST}:thread`,\n NEW_COMMENT: `${contentTypeRules.NEW_COMMENT}`,\n NEW_COMMENT_GUGGY: `${contentTypeRules.NEW_COMMENT}:gif`,\n NEW_COMMENT_VOICE: `${contentTypeRules.NEW_COMMENT}:voice`,\n NEW_COMMENT_IMAGE: `${contentTypeRules.NEW_COMMENT}:image`,\n NEW_COMMENT_MEDIA: `${contentTypeRules.NEW_COMMENT}:media`,\n ERASE_MESSAGE: 'erase:message',\n EVENT_POLL_VOTE: 'event:poll:vote',\n EVENT_NEW_GREETING_POST: 'event:greeting:post',\n EVENT_UPDATE_GROUP: 'event:update:group',\n EVENT_ERASE_GROUP_CONTENT: 'event:erase:group:content',\n EVENT_ERASE_GROUP_COMMENT: 'event:erase:group:comment',\n EVENT_NOT_A_CONTACT: 'event:not:contact',\n EVENT_SCREENSHOT: 'event:screenshot',\n EVENT_COMMENT_SCREENSHOT: 'event:comment:screenshot',\n EVENT_TOAST_CONVERSATION: 'event:toast:conversation',\n EVENT_TOAST_POST: 'event:toast:post',\n UPDATE_GROUP_NAME: 'group:update:name',\n UPDATE_GROUP_DESCRIPTION: 'group:update:description',\n UPDATE_GROUP_BACKGROUND: 'group:update:background',\n UPDATE_GROUP_DEFAULT_DEEPLINK: 'group:update:default_deeplink',\n UPDATE_GROUP_AVATAR: 'group:update:avatar',\n UPDATE_GROUP_NEW_USERS: 'group:new:users',\n UPDATE_GROUP_REMOVE_USERS: 'group:remove:users',\n UPDATE_GROUP_USER_LEAVE: 'group:remove:users:leave',\n UPDATE_GROUP_NEW_OWNER: 'group:new:owner',\n UPDATE_GROUP_SELECT_ID: 'group:update:select_id',\n UPDATE_GROUP_SHOW_HISTORY: 'group:update:show_history',\n UPDATE_GROUP_SHARE_TO_PUBLIC: 'group:update:share_to_public',\n UPDATE_GROUP_PERMISSION: 'group:update:permission',\n UPDATE_GROUP_NEW_FEATURED: 'group:new:featured',\n UPDATE_GROUP_FEATURED_IN_GROUP: 'group:featured:in:group',\n UPDATE_GROUP_FEATURED_BY_USER: 'group:featured:by:user',\n UPDATE_RELATIONSHIP: 'update:relationship',\n NEW_GROUP_REQUEST: 'group:request:new',\n NEW_GROUP_REQUEST_ACCEPTED: 'group:request:accepted',\n REMOVE_GROUP_ADMIN: 'group:remove:admin',\n ADD_GROUP_ADMIN: 'group:new:admin',\n UPDATE_CONTENT: 'update:content',\n NEW_GROUP_REQUEST_REMOVE: 'group:request:removed',\n AGGREGATED_MESSAGE_TIME: 'aggregated:message:time',\n REQUEST_IMAGE_DOWNLOAD: 'request:image:download',\n} as const\n","import React from 'react'\nimport { Avatar, AvatarImage, AvatarFallback } from '@select-org/ui'\n\ninterface Props {\n sourceInfo?: {\n avatar: string\n username: string\n url: string\n }\n imageComponent?: React.ComponentType<{\n src: string\n alt: string\n fill?: boolean\n placeholder?: 'blur' | 'empty'\n blurDataURL?: string\n priority?: boolean\n className?: string\n }>\n}\n\nconst PostSectionSourceInfoView: React.FC<Props> = ({\n sourceInfo,\n imageComponent,\n}) => {\n if (!sourceInfo) {\n return null\n }\n\n return (\n <div className=\"mx-4 mb-3 mt-3 border-b border-gray-100 pb-3\">\n <div className=\"flex flex-row items-center\">\n {/* Use the DS Avatar (same as PostHeader) so the source avatar gets the\n shared circular shape, the imageComponent seam, and the initials-based\n fallback (initials lib + deterministic colour) — matching the original\n web AvatarCard with initials. */}\n <Avatar size=\"sm\" className=\"shrink-0 ring-1 ring-border-subtle\">\n <AvatarImage\n src={sourceInfo.avatar}\n alt={sourceInfo.username}\n imageComponent={imageComponent}\n />\n <AvatarFallback name={sourceInfo.username} className=\"text-xs\" />\n </Avatar>\n <div className=\"ml-2 flex-col justify-center flex\">\n <div className=\"text-sm font-semibold text-foreground leading-none\">\n {sourceInfo.username}\n </div>\n <div className=\"text-xs text-muted-foreground mt-1 leading-none\">\n {sourceInfo.url}\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default PostSectionSourceInfoView\n","import React, { useState } from 'react'\nimport { NotificationBadge } from '@select-org/ui'\nimport { cn } from '../utils/cn'\nimport AppIcon from './AppIcon'\n\ninterface PostFooterProps {\n postHref?: string\n commentCount?: number\n unreadCommentCount?: number\n showFooterLink?: boolean\n footerLinkLabel?: string\n footerLinkHref?: string\n isSnoozed?: boolean\n onSnoozeToggle?: () => void\n /**\n * Custom link renderer (e.g. Next.js `<Link>`) for the comment and footer\n * links. Falls back to a native `<a>`. Passing this is important inside SPAs:\n * a native `<a>` triggers a full-page reload, whereas the consumer's router\n * link performs a soft client-side navigation.\n */\n linkComponent?: React.ComponentType<{\n href: string\n children: React.ReactNode\n className?: string\n }>\n renderReactionTrigger?: (props: { onOpen: () => void }) => React.ReactNode\n renderReactionModal?: (props: {\n isOpen: boolean\n onClose: () => void\n onSend: (emoji: string) => void\n }) => React.ReactNode\n}\n\nconst PostFooter: React.FC<PostFooterProps> = ({\n postHref,\n commentCount = 0,\n unreadCommentCount = 0,\n showFooterLink = false,\n footerLinkLabel = 'Open in app',\n footerLinkHref = '/',\n isSnoozed = false,\n onSnoozeToggle,\n linkComponent: LinkComponent,\n renderReactionTrigger,\n renderReactionModal,\n}) => {\n const [isReactionOpen, setIsReactionOpen] = useState(false)\n\n const handleOpen = () => setIsReactionOpen(true)\n const handleClose = () => setIsReactionOpen(false)\n\n const commentButtonClass =\n 'relative text-muted-foreground hover:text-foreground hover:bg-muted p-2 rounded-full transition-all flex items-center justify-center cursor-pointer bg-transparent border-none select-none'\n\n const commentAriaLabel = `View comments${commentCount > 0 ? `, ${commentCount} comment${commentCount !== 1 ? 's' : ''}` : ''}`\n\n const commentBadge =\n commentCount > 0 ? (\n <span className=\"absolute top-0 right-0 -mt-0.5 -mr-0.5\">\n <NotificationBadge\n count={unreadCommentCount > 0 ? unreadCommentCount : commentCount}\n variant={unreadCommentCount > 0 ? 'solid' : 'neutral'}\n size=\"sm\"\n className=\"ring-2 ring-background\"\n />\n </span>\n ) : null\n\n return (\n <section className=\"flex items-center justify-between p-2 px-4 border-t border-border/50\">\n <div className=\"relative flex items-center gap-1\">\n {renderReactionTrigger ? (\n renderReactionTrigger({ onOpen: handleOpen })\n ) : (\n <button\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n handleOpen()\n }}\n className=\"text-muted-foreground hover:text-foreground hover:bg-muted p-2 rounded-full transition-all cursor-pointer bg-transparent border-none select-none\"\n aria-label=\"Add reaction\"\n aria-expanded={isReactionOpen}\n aria-haspopup=\"true\"\n >\n <AppIcon name=\"sendEmoji\" aria-hidden=\"true\" />\n </button>\n )}\n\n {onSnoozeToggle && (\n <button\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n onSnoozeToggle()\n }}\n className={cn(\n 'p-2 rounded-full hover:bg-muted transition-all cursor-pointer bg-transparent border-none select-none',\n isSnoozed\n ? 'text-feedback-warning'\n : 'text-muted-foreground hover:text-foreground'\n )}\n aria-label={isSnoozed ? 'Unsnooze post' : 'Snooze post'}\n title={isSnoozed ? 'Unsnooze post' : 'Snooze post (30 min)'}\n >\n <AppIcon name=\"alarmClock\" />\n </button>\n )}\n\n {renderReactionModal && (\n <div className=\"z-50 absolute bottom-full left-0 mb-2\">\n {renderReactionModal({\n isOpen: isReactionOpen,\n onClose: handleClose,\n onSend: (emoji: string) => {\n handleClose()\n },\n })}\n </div>\n )}\n </div>\n\n {/* The comment icon is purely a \"view comments\" navigation affordance.\n Without a postHref there's nowhere to go (e.g. the post-detail page,\n which is the destination), so render nothing rather than a dead,\n non-interactive icon button. */}\n {postHref && (\n <div className=\"relative flex items-center ml-auto\">\n {LinkComponent ? (\n <LinkComponent\n href={postHref}\n className={cn(commentButtonClass, 'no-underline')}\n >\n <AppIcon name=\"messageCircleMore\" aria-hidden=\"true\" />\n {/* The LinkComponent contract takes no aria-label, and this link\n is icon-only — provide an accessible name via sr-only text. */}\n <span className=\"sr-only\">{commentAriaLabel}</span>\n {commentBadge}\n </LinkComponent>\n ) : (\n <a\n href={postHref}\n className={cn(commentButtonClass, 'no-underline')}\n onClick={(e) => {\n e.stopPropagation()\n }}\n aria-label={commentAriaLabel}\n >\n <AppIcon name=\"messageCircleMore\" aria-hidden=\"true\" />\n {commentBadge}\n </a>\n )}\n </div>\n )}\n\n {showFooterLink &&\n (() => {\n const footerLinkClass =\n 'bg-action-primary/5 hover:bg-action-primary/10 transition-colors w-full text-center py-3 text-sm font-medium text-action-primary no-underline rounded-b-xl border-t border-action-primary/10'\n return (\n <section className=\"flex justify-center -mx-5 -mb-2.5 mt-2.5\">\n {LinkComponent ? (\n <LinkComponent href={footerLinkHref} className={footerLinkClass}>\n {footerLinkLabel}\n </LinkComponent>\n ) : (\n <a href={footerLinkHref} className={footerLinkClass}>\n {footerLinkLabel}\n </a>\n )}\n </section>\n )\n })()}\n </section>\n )\n}\n\nexport default PostFooter\n","import type { MediaUploadStatus } from '../../types'\n\nexport interface UploadStats {\n inFlight: number\n done: number\n failed: number\n total: number\n}\n\n/**\n * Count per-item upload statuses into an aggregate for the upload strip.\n * `uploading` and `processing` both count as in-flight; `total` is the sum\n * of the three buckets (entries with no recognized status are ignored).\n */\nexport function deriveUploadStats(\n statuses: Record<string, MediaUploadStatus> | undefined\n): UploadStats {\n let inFlight = 0\n let done = 0\n let failed = 0\n for (const s of Object.values(statuses ?? {})) {\n if (s === 'uploading' || s === 'processing') inFlight++\n else if (s === 'uploaded') done++\n else if (s === 'error') failed++\n }\n return { inFlight, done, failed, total: inFlight + done + failed }\n}\n","import React from 'react'\nimport { cn } from '../utils/cn'\nimport AppIcon from './AppIcon'\nimport type { MediaUploadStatus } from '../types'\nimport { deriveUploadStats } from './PostMediaLayout/uploadStats'\n\ninterface Props {\n statuses?: Record<string, MediaUploadStatus>\n labels?: {\n /** Template with `{count}` replaced by the remaining in-flight number. */\n uploadingRemaining?: string\n /** Shown when nothing is in flight but failures remain. */\n uploadingDone?: string\n }\n}\n\nconst PostUploadStrip: React.FC<Props> = ({ statuses, labels }) => {\n const stats = deriveUploadStats(statuses)\n\n // Meaningful only while uploads are in flight or have failed.\n if (stats.total === 0) return null\n if (stats.inFlight === 0 && stats.failed === 0) return null\n\n const hasError = stats.failed > 0\n const remaining = stats.inFlight\n\n const remainingTemplate = labels?.uploadingRemaining ?? 'Uploading {count} more'\n const doneLabel = labels?.uploadingDone ?? 'All uploaded'\n const progressLabel =\n remaining > 0\n ? remainingTemplate.replace('{count}', String(remaining))\n : doneLabel\n\n return (\n <div\n className={cn(\n 'not-prose flex items-center gap-2.5 border-t border-border px-5 py-2.5',\n hasError ? 'bg-feedback-danger/8' : 'bg-feedback-info/8'\n )}\n >\n {remaining > 0 ? (\n <AppIcon\n name=\"loader\"\n className={cn(\n 'size-4 shrink-0 animate-spin',\n hasError ? 'text-feedback-danger' : 'text-feedback-info'\n )}\n />\n ) : (\n <AppIcon\n name=\"triangleAlert\"\n className=\"size-4 shrink-0 text-feedback-danger\"\n />\n )}\n <span\n className={cn(\n 'truncate text-xs font-medium',\n hasError ? 'text-feedback-danger' : 'text-feedback-info'\n )}\n >\n {progressLabel}\n </span>\n <span\n className={cn(\n 'ml-auto shrink-0 text-[11px]',\n hasError ? 'text-feedback-danger/80' : 'text-feedback-info/80'\n )}\n >\n {stats.done} / {stats.total}\n {hasError && ` · ${stats.failed} failed`}\n </span>\n </div>\n )\n}\n\nexport default PostUploadStrip\n","import React, { useEffect, useState } from 'react'\nimport AppIcon from './AppIcon'\n\ninterface Props {\n backgroundColor?: string\n onYesPress: (e?: React.MouseEvent) => void\n onNoPress: (e?: React.MouseEvent) => void\n fontColor?: string\n itemType?: string\n isOpen: boolean\n handleClose: () => void\n}\n\nconst EraseConfirmModal: React.FC<Props> = ({\n onYesPress,\n onNoPress,\n itemType = 'comment',\n isOpen,\n handleClose,\n}) => {\n const [first, setFirst] = useState(true)\n const [second, setSecond] = useState(false)\n\n // Lock scroll and handle Escape key when open\n useEffect(() => {\n if (!isOpen) return\n const closeOnEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') handleClose()\n }\n document.body.addEventListener('keydown', closeOnEscape)\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n document.body.style.overflow = 'hidden'\n document.body.style.paddingRight = `${scrollbarWidth}px`\n return () => {\n document.body.removeEventListener('keydown', closeOnEscape)\n document.body.style.overflow = ''\n document.body.style.paddingRight = ''\n }\n }, [isOpen, handleClose])\n\n if (!isOpen) return null\n\n const handleFirst = (e: React.MouseEvent) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n setFirst(false)\n setSecond(true)\n }\n\n const handleNoPress = (e: React.MouseEvent) => {\n onNoPress(e)\n setFirst(true)\n setSecond(false)\n }\n\n const eraseLabel = itemType === 'Post' ? 'Erase post' : 'Erase comment'\n const confirmTitle =\n itemType === 'Post'\n ? 'Are you sure you want to erase this post?'\n : 'Are you sure you want to erase this comment?'\n const confirmBody =\n itemType === 'Post'\n ? 'This action cannot be undone.'\n : 'This action cannot be undone.'\n\n return (\n <div>\n {/* Backdrop */}\n <div className=\"fixed left-0 top-0 z-50 h-screen w-full bg-black/50\" />\n {/* Modal container */}\n <div\n className=\"fixed left-0 top-0 z-50 flex h-screen w-full items-center justify-center p-4\"\n onClick={(e) => {\n e.stopPropagation()\n e.nativeEvent.stopImmediatePropagation()\n }}\n >\n <div className=\"rounded-3xl bg-background px-8 py-6 text-center shadow-3\">\n {first && (\n <div\n className=\"flex w-[256px] flex-col justify-around\"\n onClick={(e) => e.stopPropagation()}\n >\n <div\n className=\"mb-4 flex flex-row items-center hover:cursor-pointer hover:opacity-50\"\n data-testid=\"modal-erase-post\"\n onClick={(e) => handleFirst(e)}\n >\n <div>\n <AppIcon name=\"chatErase\" className=\"size-7.5 cursor-pointer\" />\n </div>\n <p className=\"ml-3 text-lg\">{eraseLabel}</p>\n </div>\n <div\n className=\"flex flex-row items-center hover:cursor-pointer hover:opacity-50\"\n onClick={handleNoPress}\n >\n <div>\n <AppIcon name=\"cancel\" className=\"cursor-pointer size-6\" />\n </div>\n <p className=\"ml-3 text-lg\">Cancel</p>\n </div>\n </div>\n )}\n {second && (\n <div\n onClick={(e) => e.stopPropagation()}\n className=\"flex w-[296px] flex-col items-center justify-around\"\n >\n <div className=\"mb-4\">\n <h4 className=\"mb-2 text-lg font-bold\">{confirmTitle}</h4>\n <p className=\"text-muted-foreground\">{confirmBody}</p>\n </div>\n <div className=\"flex items-center justify-around\">\n <button\n className=\"mr-6 py-2 text-muted-foreground\"\n onClick={handleNoPress}\n >\n Cancel\n </button>\n <button\n className=\"rounded-3xl bg-action-primary px-6 py-2 font-semibold text-white\"\n onClick={onYesPress}\n data-testid=\"confirm-modal-erase\"\n >\n Erase\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n\nexport default EraseConfirmModal\n","import React, { useCallback, useMemo } from 'react'\nimport { contentTypeConstants } from '../utils/contentTypeConstants'\nimport AutoLink from './AutoLink'\nimport PostMediaLayout from './PostMediaLayout/PostMediaLayoutCore'\nimport type { ItemData } from '../types'\nimport type { SectionItem } from '../resolver/postContentResolver'\n\ninterface Props {\n fontColor?: string\n sections: SectionItem[]\n onCardPress?: () => void\n}\n\nconst BODY_SIZE = 80\n\nconst PostSectionsSummaryView: React.FC<Props> = ({\n sections,\n fontColor,\n onCardPress,\n}) => {\n const imageItems: ItemData[] = useMemo(() => {\n if (!sections || sections.length === 0) return []\n return sections.reduce((items: ItemData[], section: SectionItem) => {\n if (section.type === contentTypeConstants.NEW_POST_MEDIA) {\n return items.concat((section.data.items as ItemData[]) || [])\n }\n return items\n }, [])\n }, [sections])\n\n const textBody = useMemo(() => {\n if (!sections || sections.length === 0) return ''\n const allBody = sections.reduce((body: string, section: SectionItem) => {\n if (\n section.type === contentTypeConstants.NEW_POST_MEDIA &&\n section.data.body\n ) {\n return body + (body ? '\\n' : '') + section.data.body\n }\n return body\n }, '')\n return allBody ? `${allBody.slice(0, BODY_SIZE)}...` : ''\n }, [sections])\n\n const renderSectionItem = useCallback(\n (section: SectionItem, index: number) => {\n const { type, data } = section\n if (type === contentTypeConstants.NEW_POST_MESSAGE) {\n return (\n <AutoLink\n key={`${index} - ${data.body}`}\n text={data.body || ''}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n color: fontColor || 'var(--color-foreground)',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={data.mentionData}\n />\n )\n }\n return null\n },\n [fontColor]\n )\n\n if (!sections || sections.length === 0) {\n return null\n }\n\n return (\n <div className=\"flex-col\">\n {sections.map((section, index) => {\n return renderSectionItem(section, index)\n })}\n {textBody && (\n <AutoLink\n key=\"body\"\n text={textBody}\n className=\"whitespace-normal px-4 pb-4 leading-relaxed text-gray-800\"\n style={{\n color: fontColor || 'var(--color-foreground)',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n mentionData={[]}\n />\n )}\n <PostMediaLayout\n items={imageItems}\n />\n </div>\n )\n}\n\nexport default PostSectionsSummaryView\n","import React, { useRef, useEffect } from 'react'\n\ninterface ReactionModalProps {\n isOpen: boolean\n close: () => void\n sendReaction: (emoji: string) => void\n onAnalyticsEvent?: (event: string, data?: Record<string, unknown>) => void\n}\n\nconst reactionList = ['👍', '😍', '😂', '😱', '😭', '😎']\n\nconst ReactionModal = ({ isOpen, close, sendReaction, onAnalyticsEvent }: ReactionModalProps) => {\n const ref = useRef<HTMLDivElement>(null)\n\n // Combined effect for analytics and outside click - only active when modal is open\n useEffect(() => {\n if (!isOpen) return\n\n onAnalyticsEvent?.('reaction')\n\n const handleOutsideClick = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n close()\n }\n }\n document.addEventListener('click', handleOutsideClick)\n return () => {\n document.removeEventListener('click', handleOutsideClick)\n }\n }, [isOpen, close, onAnalyticsEvent])\n\n if (!isOpen) return null\n\n return (\n <div className=\"z-500 flex items-center justify-center\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Reaction picker\">\n <div ref={ref} className=\"rounded-3xl bg-muted p-2\">\n <div className=\"flex justify-around\">\n {reactionList.map((reaction, index) => {\n return (\n <button\n type=\"button\"\n key={reaction + index}\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n onAnalyticsEvent?.('reaction_send')\n sendReaction(reaction)\n close()\n }}\n className=\"cursor-pointer px-2 text-3xl hover:scale-125 transition-transform\"\n >\n {reaction}\n </button>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n\nexport { ReactionModal }\n"],"mappings":"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","names":["React","useMemo","useState","jsx","jsx","className","DOMPurify","useMemo","useMemo","jsx","jsx","jsxs","useMemo","DOMPurify","useMemo","useCallback","useMemo","jsx","jsx","jsxs","useMemo","useCallback","item","jsx","jsxs","useMemo","jsx","jsxs","jsx","nonVoteClassName","voteClassName","jsx","jsxs","jsx","jsxs","jsx","jsx","Fragment","jsx","jsxs","useMemo","useState","jsx","useState","useMemo","jsx","jsxs","jsx","jsxs","jsx","useCallback","Avatar","AvatarImage","AvatarFallback","jsx","jsxs","jsx","jsxs","useCallback","useState","jsx","jsxs","useState","jsx","jsxs","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","useState","useMemo","React","useCallback","useMemo","jsx","jsxs","useMemo","useCallback","useRef","useEffect","jsx"]}