newOS for Developers
MediaComponent
output155 linesA universal media renderer that automatically selects the appropriate component based on content type (image, video, text, or fallback).
apps/web/Components/MediaComponents/MediaComponent.tsx@newos/web
Content Type Registry
const contentTypeElements: Record<string, ContentElement> = {
default: UniversalComponent, // Fallback for unknown types
"image/jpeg": ImageComponent,
"image/png": ImageComponent,
"image/gif": ImageComponent,
"video/mp4": VideoComponent,
"text/plain": TextMediaComponent,
"text/html": TextMediaComponent,
};Props (ContentImageProps)
MediaComponent: ContentElement = (props: ContentImageProps) => {
contentType?: string; // MIME type for component selection
thumbnail?: boolean; // Thumbnail mode (default: true)
content?: string; // Text content for TextMediaComponent
contentUrl?: string; // URL for media content
agents?: UserReadPublicResponse[];
mode?: "chat" | undefined; // Affects border-radius styling
height?: string | number; // Container height
width?: string | number; // Container width
eagerDisplay?: boolean; // Skip visibility check
mediaContentMode?: string; // If includes "none", skip text overlay
// ...additional props passed to sub-components
}Component Selection Logic
contentType in registry, fallback to "default"default OR text/plain with no content → use UniversalComponentcontent prop → render TextMediaComponent as overlayeagerDisplay)Key Features
Lazy Loading
Uses useVisibilityOnce hook with 150ms threshold to only render content when visible in viewport. Override with eagerDisplay=true.
Text Overlay
For non-text content types, automatically renders TextMediaComponentas an extra overlay if content prop exists. Skip with mediaContentMode="none".
Mode-Based Styling
mode="chat" removes border-radius (0px) for seamless chat bubble integration. Default mode uses 18px border-radius.
Error Handling
Catches errors via onError callback and stores in state. Error state triggers error display (currently minimal implementation).
Responsive Width
For text/plain content without mode, sets minWidth: 300pxand centers on mobile using useIsWideScreen hook.
Edge Cases & Gotchas
thumbnail prop defaults to truevia thumbnail ?? true. Pass explicit false for full-size rendering.thumbnail=false, the component renders without the visibility observer wrapper, potentially affecting performance.UniversalComponent, which attempts generic rendering.ant-image-size class from Ant Design for consistent image sizing.Sub-Components
ImageComponent
Handles JPEG, PNG, GIF images with lazy loading and thumbnail generation.
VideoComponent
MP4 video player with custom controls.
TextMediaComponent
Rich text renderer for plain text and HTML content with typewriter effects.
UniversalComponent
Fallback component for unknown content types, attempts best-effort rendering.