feat: share post to other apps
This commit is contained in:
@@ -23,6 +23,8 @@ import {
|
||||
ogForLetter,
|
||||
ogForMagazine,
|
||||
ogForOtherDocument,
|
||||
ogForPost,
|
||||
ogForProfile,
|
||||
ogForTranscription,
|
||||
ogForVerse,
|
||||
} from "@/lib/og";
|
||||
@@ -115,6 +117,10 @@ export async function buildShareOgMeta(fullPath: string): Promise<Metadata> {
|
||||
return parts.length >= 3
|
||||
? await ogForOtherDocPath(parts[1], parts[2], sp)
|
||||
: ogDefault();
|
||||
case "u":
|
||||
// /u/<handle> → profile share
|
||||
// /u/<handle>/posts#post-<id> → post share (post id in u.hash)
|
||||
return await ogForProfilePath(parts, u.hash);
|
||||
default:
|
||||
return ogWithFallbackQuote("Prabhupāda Says", sp);
|
||||
}
|
||||
@@ -365,6 +371,74 @@ async function ogForOtherDocPath(
|
||||
// Fallback
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Profile + post share dispatch
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type PublicProfileForOg = {
|
||||
handle: string;
|
||||
name: string;
|
||||
post_count?: number;
|
||||
};
|
||||
|
||||
type PostForOg = {
|
||||
id: string;
|
||||
caption: string;
|
||||
source_title?: string | null;
|
||||
author_name?: string | null;
|
||||
author_handle?: string | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve `/u/<handle>` and `/u/<handle>/posts#post-<id>` share targets
|
||||
* to the correct OG card. The hash carries the post id when the share
|
||||
* is a single-post link (built by SharePostSheet); without a hash we
|
||||
* fall back to a profile card for the handle.
|
||||
*/
|
||||
async function ogForProfilePath(
|
||||
parts: string[],
|
||||
hash: string,
|
||||
): Promise<Metadata> {
|
||||
if (parts.length < 2) return ogDefault();
|
||||
const handle = parts[1];
|
||||
|
||||
// Post share: /u/<handle>/posts with `#post-<id>` fragment.
|
||||
if (parts.length >= 3 && parts[2] === "posts") {
|
||||
const m = hash.match(/^#post-(.+)$/);
|
||||
if (m) {
|
||||
const postID = m[1];
|
||||
try {
|
||||
const post = await bff<PostForOg>(
|
||||
`/posts/${encodeURIComponent(postID)}`,
|
||||
{ revalidate: 60 },
|
||||
);
|
||||
if (post) return ogForPost(post);
|
||||
} catch {
|
||||
// fall through to profile-level card
|
||||
}
|
||||
}
|
||||
// No post id → treat as a feed share for the profile.
|
||||
}
|
||||
|
||||
// Profile share: /u/<handle>
|
||||
try {
|
||||
const profile = await bff<PublicProfileForOg>(
|
||||
`/u/${encodeURIComponent(handle)}`,
|
||||
{ revalidate: 60 },
|
||||
);
|
||||
if (profile) {
|
||||
return ogForProfile({
|
||||
handle: profile.handle,
|
||||
name: profile.name,
|
||||
postCount: profile.post_count,
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// fall through
|
||||
}
|
||||
return ogDefault();
|
||||
}
|
||||
|
||||
function ogWithFallbackQuote(
|
||||
title: string,
|
||||
sp: URLSearchParams,
|
||||
|
||||
Reference in New Issue
Block a user