Files
spsays-training/lib/post-share-text.ts
T
2026-08-29 11:58:33 +05:30

54 lines
1.8 KiB
TypeScript

/**
* Builds the shareable text for a post — the caption, its source reference,
* and a link.
*
* Extracted so the native share sheet and "send to a chat" quote a post
* identically. They differ only in where the text ends up, and two copies of
* this would drift the moment either format changed.
*/
import { createShortLink } from "@/lib/share";
import { structuredReferenceForPost } from "@/lib/source-reference";
import type { Post } from "@/lib/social";
export type PostShareText = {
/** Short link when the shortener answered, canonical URL otherwise. */
url: string;
/** Source reference on one line, for a native share sheet's title slot. */
title: string;
/** Caption, source reference and link — the body of the share. */
text: string;
};
/**
* `viewerHandle` covers the case where the BFF's create response omits
* author_handle: the poster IS the signed-in user right after posting.
* Returns null when neither yields a handle, since there is no post URL
* without one.
*/
export async function buildPostShareText(
post: Post,
viewerHandle: string | undefined,
): Promise<PostShareText | null> {
const handle = post.author_handle ?? viewerHandle ?? "";
if (!handle) return null;
const longPath = `/u/${encodeURIComponent(handle)}/posts#post-${post.id}`;
const code = await createShortLink(longPath);
const origin = window.location.origin;
const url = code
? new URL(`/share/${code}`, origin).toString()
: new URL(longPath, origin).toString();
const ref = structuredReferenceForPost(post.source_url, post.source_title);
const lines = [`“${post.caption}”`, "", "Source:", ref.title];
if (ref.detail) lines.push(ref.detail);
lines.push(url);
return {
url,
title: ref.detail ? `${ref.title} — ${ref.detail}` : ref.title,
text: lines.join("\n"),
};
}