-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add new mux onboarding video for assistant #807
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f230f7b
5872dff
02f7802
506406a
b332641
99f610b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,8 @@ import { PlayIcon } from "lucide-react"; | |
| type Video = { | ||
| title: string; | ||
| description: React.ReactNode; | ||
| videoId: string; | ||
| youtubeVideoId?: string; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both youtubeVideoId and muxPlaybackId are optional, allowing a video entry with neither ID; the dialog then renders nothing, resulting in a blank modal. Enforce at least one ID (union/discriminated type) or gate rendering of WatchVideo when no ID is present. Prompt for AI agents✅ Addressed in |
||
| muxPlaybackId?: string; | ||
| }; | ||
|
|
||
| export function PageHeader({ | ||
|
|
@@ -24,7 +25,9 @@ export function PageHeader({ | |
| <PageHeading>{title}</PageHeading> | ||
| <div className="flex items-center mt-1"> | ||
| <PageSubHeading>{description}</PageSubHeading> | ||
| {video && <WatchVideo video={video} />} | ||
| {video && (video.youtubeVideoId || video.muxPlaybackId) && ( | ||
| <WatchVideo video={video} /> | ||
| )} | ||
| </div> | ||
| </div> | ||
| ); | ||
|
|
@@ -42,7 +45,8 @@ function WatchVideo({ video }: { video: Video }) { | |
| <OnboardingDialogContent | ||
| title={video.title} | ||
| description={video.description} | ||
| videoId={video.videoId} | ||
| youtubeVideoId={video.youtubeVideoId} | ||
| muxPlaybackId={video.muxPlaybackId} | ||
| /> | ||
| </Dialog> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| import React, { useState, useEffect } from "react"; | ||
| import type { ComponentProps } from "react"; | ||
| import Image from "next/image"; | ||
| import MuxPlayer from "@mux/mux-player-react"; | ||
| import { PlayIcon, X } from "lucide-react"; | ||
| import { CardGreen } from "@/components/ui/card"; | ||
| import { | ||
|
|
@@ -12,6 +13,7 @@ import { | |
| DialogTitle, | ||
| } from "@/components/ui/dialog"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import { ClientOnly } from "@/components/ClientOnly"; | ||
|
|
||
| type VideoCardProps = ComponentProps<typeof VideoCard> & { | ||
| storageKey: string; | ||
|
|
@@ -45,8 +47,9 @@ const VideoCard = React.forwardRef< | |
| icon?: React.ReactNode; | ||
| title: string; | ||
| description: string; | ||
| videoSrc: string; | ||
| thumbnailSrc: string; | ||
| videoSrc?: string; | ||
| thumbnailSrc?: string; | ||
| muxPlaybackId?: string; | ||
| onClose?: () => void; | ||
| } | ||
| >( | ||
|
|
@@ -58,6 +61,7 @@ const VideoCard = React.forwardRef< | |
| description, | ||
| videoSrc, | ||
| thumbnailSrc, | ||
| muxPlaybackId, | ||
| onClose, | ||
| ...props | ||
| }, | ||
|
|
@@ -112,7 +116,11 @@ const VideoCard = React.forwardRef< | |
| > | ||
| <div className="relative w-32 h-20 rounded-lg overflow-hidden bg-gray-100 dark:bg-gray-800"> | ||
| <Image | ||
| src={thumbnailSrc} | ||
| src={ | ||
| muxPlaybackId | ||
| ? `https://image.mux.com/${muxPlaybackId}/thumbnail.jpg` | ||
| : thumbnailSrc || "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=" | ||
| } | ||
| alt={title} | ||
| fill | ||
| className="object-cover transition-all duration-200 group-hover:scale-105" | ||
|
|
@@ -126,16 +134,29 @@ const VideoCard = React.forwardRef< | |
| </div> | ||
| </button> | ||
| </DialogTrigger> | ||
| <DialogContent className="max-w-4xl border-0 bg-transparent p-0"> | ||
| <DialogContent className="max-w-6xl border-0 bg-transparent p-0 overflow-hidden"> | ||
| <DialogTitle className="sr-only">Video: {title}</DialogTitle> | ||
| <div className="relative aspect-video w-full"> | ||
| <iframe | ||
| src={`${videoSrc}${videoSrc.includes("?") ? "&" : "?"}autoplay=1&rel=0`} | ||
| className="size-full rounded-lg" | ||
| title={`Video: ${title}`} | ||
| allowFullScreen | ||
| allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" | ||
| /> | ||
| <div className="relative aspect-video w-full overflow-hidden rounded-lg"> | ||
| {muxPlaybackId ? ( | ||
| <ClientOnly> | ||
| <MuxPlayer | ||
| playbackId={muxPlaybackId} | ||
| metadata={{ video_title: title }} | ||
| accentColor="#3b82f6" | ||
| className="size-full rounded-lg" | ||
| style={{ overflow: "hidden" }} | ||
| autoPlay | ||
| /> | ||
| </ClientOnly> | ||
| ) : ( | ||
| <iframe | ||
| src={`${videoSrc}${videoSrc?.includes("?") ? "&" : "?"}autoplay=1&rel=0`} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If videoSrc is undefined, iframe src becomes an invalid URL (e.g., "undefined?autoplay=1..."), breaking playback. Prompt for AI agents |
||
| className="size-full rounded-lg" | ||
| title={`Video: ${title}`} | ||
| allowFullScreen | ||
| allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" | ||
| /> | ||
| )} | ||
| </div> | ||
| </DialogContent> | ||
| </Dialog> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.