authorgravatar for maria@kuuro.netmaria <maria@kuuro.net> 2026-09-07 20:52:21-03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-07 20:52:21-03:00
log569a8cd2c3303f55fd869687eb31359b5658cc78
treeede16a5a9a0877f7591ebaa72889e1e5b2f2e054
parentd67157a09c28883d7856d03d2b1d3aecdbf1b890
signature Signed by PGP key B5690EEEBB952194

fix(web): play pull request videos inline (#10617)


1 files changed, 17 insertions(+), 14 deletions(-)

apps/web/src/components/pullRequest/PullRequestMarkdown.tsx+17-14
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1import { ExternalLinkIcon, PaperclipIcon, PlayIcon } from "lucide-react";1import { ExternalLinkIcon, PaperclipIcon } from "lucide-react";
2import type { EnvironmentId, ScopedThreadRef } from "@t3tools/contracts";2import type { EnvironmentId, ScopedThreadRef } from "@t3tools/contracts";
3import { createContext, useContext, useMemo } from "react";3import { createContext, useContext, useMemo } from "react";
4import type { Options as ReactMarkdownOptions } from "react-markdown";4import type { Options as ReactMarkdownOptions } from "react-markdown";
...@@ -6,17 +6,12 @@ import type { Options as ReactMarkdownOptions } from "react-markdown";...@@ -6,17 +6,12 @@ import type { Options as ReactMarkdownOptions } from "react-markdown";
6import { cn } from "~/lib/utils";6import { cn } from "~/lib/utils";
77
8import ChatMarkdown from "../ChatMarkdown";8import ChatMarkdown from "../ChatMarkdown";
9import { MediaVideoPlayer } from "../media/MediaVideoPlayer";
9import { remarkPullRequestAutolinks, splitPullRequestBody } from "./pullRequestMarkdown.logic";10import { remarkPullRequestAutolinks, splitPullRequestBody } from "./pullRequestMarkdown.logic";
1011
11export const PullRequestMarkdownContext = createContext<string | null>(null);12export const PullRequestMarkdownContext = createContext<string | null>(null);
1213
13/**14/** Renders PR uploads inline, with retry and an original link when video playback fails. */
14 * A pull request body, rendered with the app's markdown renderer plus a card for each upload
15 * embedded in it, which that renderer drops on the floor.
16 *
17 * These upload URLs do not identify the media format. The card links to GitHub, where the
18 * original upload can be opened or downloaded even when its codec cannot play in the client.
19 */
20export function PullRequestMarkdown({15export function PullRequestMarkdown({
21 text,16 text,
22 cwd,17 cwd,
...@@ -52,8 +47,18 @@ export function PullRequestMarkdown({...@@ -52,8 +47,18 @@ export function PullRequestMarkdown({
52 />47 />
53 );48 );
54 }49 }
55 const isVideo = segment.media === "video";50 if (segment.media === "video") {
56 const Icon = isVideo ? PlayIcon : PaperclipIcon;51 return (
52 <MediaVideoPlayer
53 key={`${segment.id}:${segment.url}`}
54 src={segment.url}
55 originalUrl={segment.url}
56 label="Pull request video"
57 className="w-full"
58 videoClassName="rounded-lg border border-border/60"
59 />
60 );
61 }
57 return (62 return (
58 // A plain anchor rather than the page's openExternal button: the desktop window63 // A plain anchor rather than the page's openExternal button: the desktop window
59 // turns a blocked _blank into openExternal itself, and in a browser tab — where64 // turns a blocked _blank into openExternal itself, and in a browser tab — where
...@@ -65,10 +70,8 @@ export function PullRequestMarkdown({...@@ -65,10 +70,8 @@ export function PullRequestMarkdown({
65 target="_blank"70 target="_blank"
66 className="flex items-center gap-2 rounded-lg border border-border/60 bg-muted/30 px-3 py-2 text-sm hover:bg-muted/60"71 className="flex items-center gap-2 rounded-lg border border-border/60 bg-muted/30 px-3 py-2 text-sm hover:bg-muted/60"
67 >72 >
68 <Icon aria-hidden className="size-3.5 shrink-0 text-muted-foreground" />73 <PaperclipIcon aria-hidden className="size-3.5 shrink-0 text-muted-foreground" />
69 <span className="min-w-0 flex-1 truncate">74 <span className="min-w-0 flex-1 truncate">Open attachment on GitHub</span>
70 {isVideo ? "Play video on GitHub" : "Open attachment on GitHub"}
71 </span>
72 <ExternalLinkIcon aria-hidden className="size-3 shrink-0 text-muted-foreground" />75 <ExternalLinkIcon aria-hidden className="size-3 shrink-0 text-muted-foreground" />
73 </a>76 </a>
74 );77 );