feat(posts): support short titles for resource cards

Add optional post-level and localized title fields, and use a new
postTitleText helper for Resource.title so card/list surfaces prefer short
backend-provided titles instead of full body text. When title is missing,
fallback to the first non-empty body line, then filename, then post id.

Document the backend handoff in docs/posts-title-api.md alongside the other
backend task docs.
This commit is contained in:
TerryM
2026-05-30 03:11:03 +08:00
parent 2b9ab9eb2c
commit 6798e90708
4 changed files with 82 additions and 2 deletions

View File

@@ -11,3 +11,19 @@ export function postDisplayText(post: Post, lang: string): string {
""
);
}
export function postTitleText(post: Post, lang: string): string {
const key = localizationKey(lang);
const localized =
post.localizations?.[key as keyof typeof post.localizations];
const explicitTitle = localized?.title?.trim() || post.title?.trim();
if (explicitTitle) return explicitTitle;
const text = postDisplayText(post, lang);
return (
text
.split(/\n{1,}/)
.map((line) => line.trim())
.find(Boolean) || ""
);
}

View File

@@ -14,6 +14,9 @@ export type PostTypeFilter = PostType | "all";
export type AttachmentKind = "image" | "video" | "document";
export type PostLocaleTexts = {
/** Short display title for list/card surfaces. */
title?: string;
/** Full post body text. */
text: string;
};
@@ -59,6 +62,8 @@ export type Post = {
categorySlug: string;
language: string;
sourceLanguage?: string;
/** Short display title for list/card surfaces. */
title?: string;
text?: string;
localizations?: Partial<PostLocalizations>;
attachments: Attachment[];

View File

@@ -1,6 +1,9 @@
import type { Category, Resource } from "../api";
import type { Attachment, Post } from "../types/post";
import { postDisplayText } from "../components/messageStream/utils/postText";
import {
postDisplayText,
postTitleText,
} from "../components/messageStream/utils/postText";
export type PostBackedResource = Resource & {
downloadPostId?: string;
@@ -35,7 +38,7 @@ export function postToResource(
categories: Category[] = [],
): PostBackedResource {
const first = post.attachments[0];
const title = postDisplayText(post, lang) || first?.filename || post.id;
const title = postTitleText(post, lang) || first?.filename || post.id;
const category = categories.find((c) => c.id === post.categoryId);
return {
id: post.id,