Improve backend media readiness for mobile clients
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled

هذا الالتزام موجود في:
boutmoun123
2026-05-25 23:18:00 +03:00
الأصل efd87659b2
التزام acd8d0d8cf
8 ملفات معدلة مع 238 إضافات و2 حذوفات

عرض الملف

@@ -0,0 +1,6 @@
export enum ProcessingStatus {
PENDING = 'pending',
PROCESSING = 'processing',
READY = 'ready',
FAILED = 'failed',
}

عرض الملف

@@ -0,0 +1,105 @@
import { PostType } from '../enums/post-type.enum';
type VariantSet = {
originalUrl?: string;
lowUrl?: string;
mediumUrl?: string;
highUrl?: string;
} | null;
type PostMediaInput = {
postType?: PostType | string;
imageUrls?: string[];
imageItems?: Array<{ url?: string; caption?: string; altText?: string; order?: number }>;
imageVariants?: VariantSet[];
videoUrl?: string;
hlsUrl?: string;
audioUrl?: string;
thumbnailUrl?: string;
thumbnailVariants?: VariantSet;
waveformPeaks?: number[];
durationSeconds?: number | null;
};
const firstNonEmpty = (...values: Array<string | undefined | null>): string =>
values.find((value): value is string => typeof value === 'string' && value.trim().length > 0) ?? '';
const normalizeVariantSet = (variants: VariantSet) => {
if (!variants) {
return null;
}
return {
originalUrl: variants.originalUrl ?? '',
lowUrl: variants.lowUrl ?? variants.mediumUrl ?? variants.highUrl ?? variants.originalUrl ?? '',
mediumUrl: variants.mediumUrl ?? variants.highUrl ?? variants.lowUrl ?? variants.originalUrl ?? '',
highUrl: variants.highUrl ?? variants.mediumUrl ?? variants.originalUrl ?? variants.lowUrl ?? '',
};
};
const preferredImageUrl = (variants: ReturnType<typeof normalizeVariantSet>, fallback = ''): string =>
firstNonEmpty(variants?.mediumUrl, variants?.highUrl, variants?.lowUrl, variants?.originalUrl, fallback);
export const buildPostMediaResponse = (post: PostMediaInput) => {
const imageUrls = Array.isArray(post.imageUrls) ? post.imageUrls : [];
const imageItems = Array.isArray(post.imageItems) ? post.imageItems : [];
const imageVariants = Array.isArray(post.imageVariants) ? post.imageVariants : [];
const thumbnailVariants = normalizeVariantSet(post.thumbnailVariants ?? null);
const fallbackImageItems: NonNullable<PostMediaInput['imageItems']> = imageUrls.map((url, index) => ({
url,
caption: '',
altText: '',
order: index,
}));
const images = (imageItems.length ? imageItems : fallbackImageItems).map(
(item, index) => {
const variants = normalizeVariantSet(imageVariants[index] ?? null);
const url = item.url || imageUrls[index] || '';
return {
url: preferredImageUrl(variants, url),
originalUrl: firstNonEmpty(variants?.originalUrl, url),
variants,
caption: item.caption ?? '',
altText: item.altText ?? '',
order: typeof item.order === 'number' ? item.order : index,
};
},
);
const mediaType =
post.postType === PostType.IMAGE && images.length
? PostType.IMAGE
: post.postType === PostType.VIDEO || post.videoUrl || post.hlsUrl
? PostType.VIDEO
: post.postType === PostType.AUDIO || post.audioUrl
? PostType.AUDIO
: PostType.TEXT;
const thumbnailUrl = preferredImageUrl(thumbnailVariants, post.thumbnailUrl ?? '');
const preferredPlaybackUrl =
mediaType === PostType.VIDEO
? firstNonEmpty(post.hlsUrl, post.videoUrl)
: mediaType === PostType.AUDIO
? post.audioUrl ?? ''
: '';
const displayUrl =
mediaType === PostType.IMAGE
? images[0]?.url ?? ''
: mediaType === PostType.VIDEO || mediaType === PostType.AUDIO
? thumbnailUrl
: '';
return {
mediaType,
displayUrl,
thumbnailUrl,
thumbnailVariants,
preferredPlaybackUrl,
hlsUrl: post.hlsUrl ?? '',
videoUrl: post.videoUrl ?? '',
audioUrl: post.audioUrl ?? '',
images,
durationSeconds: post.durationSeconds ?? null,
waveformPeaks: Array.isArray(post.waveformPeaks) ? post.waveformPeaks : [],
isPlayable: mediaType === PostType.VIDEO ? !!preferredPlaybackUrl : mediaType === PostType.AUDIO ? !!post.audioUrl : false,
};
};