1import type { AssetResource, ChatFileAttachment, EnvironmentId } from "@t3tools/contracts";
2import { videoMimeType } from "@t3tools/shared/video";
3
4import type { DraftComposerFileAttachment } from "./composerImages";
5import type { MediaActionsSource } from "./mediaActionsSource";
6
7export type MediaVideoPreviewSource = {
8 readonly type: "media";
9 readonly name: string;
10 readonly mimeType: string;
11 readonly sourceIdentifier?: string;
12 readonly srcFragment?: string;
13 readonly actionsSource?: MediaActionsSource;
14} & (
15 | { readonly uri: string }
16 | {
17 readonly environmentId: EnvironmentId;
18 readonly resource: Extract<
19 AssetResource,
20 { readonly _tag: "attachment" | "media-file" | "draft-workspace-file" | "github-media" }
21 >;
22 }
23);
24
25/** Resolves the current capability without making it the identity of the video. */
26export function mediaVideoPreviewUri(
27 source: MediaVideoPreviewSource,
28 assetUrl: string | null,
29): string | null {
30 if ("uri" in source) return source.uri;
31 return assetUrl === null ? null : assetUrl + (source.srcFragment ?? "");
32}
33
34/** Keeps thumbnails independent of refreshed asset signatures and scoped to their environment. */
35export function mediaVideoThumbnailKey(source: MediaVideoPreviewSource): string {
36 return JSON.stringify(
37 "uri" in source
38 ? ["media-video", source.uri]
39 : source.resource._tag === "attachment"
40 ? ["media-video", source.environmentId, "attachment", source.resource.attachmentId]
41 : source.resource._tag === "media-file"
42 ? [
43 "media-video",
44 "media-file",
45 source.environmentId,
46 source.resource.threadId,
47 source.resource.path,
48 source.srcFragment ?? "",
49 ]
50 : source.resource._tag === "github-media"
51 ? [
52 "media-video",
53 "github-media",
54 source.environmentId,
55 source.resource.cwd,
56 source.resource.url,
57 ]
58 : [
59 "media-video",
60 "draft-workspace-file",
61 source.environmentId,
62 source.resource.cwd,
63 source.resource.path,
64 source.srcFragment ?? "",
65 ],
66 );
67}
68
69export interface LocalVideoPreviewSource {
70 readonly type: "local";
71 readonly attachment: DraftComposerFileAttachment;
72 readonly sourceIdentifier?: string;
73}
74
75export type VideoPreviewSource = LocalVideoPreviewSource | MediaVideoPreviewSource;
76
77export function attachmentVideoPreviewSource(
78 environmentId: EnvironmentId,
79 attachment: ChatFileAttachment,
80 sourceIdentifier?: string,
81): MediaVideoPreviewSource {
82 const mimeType = videoMimeType(attachment) ?? attachment.mimeType;
83 const resource = {
84 _tag: "attachment" as const,
85 attachmentId: attachment.id,
86 fileName: attachment.name,
87 mimeType,
88 };
89 return {
90 type: "media",
91 name: attachment.name,
92 mimeType,
93 ...(sourceIdentifier ? { sourceIdentifier } : {}),
94 environmentId,
95 resource,
96 actionsSource: {
97 name: attachment.name,
98 mimeType,
99 ...(sourceIdentifier ? { sourceIdentifier } : {}),
100 environmentId,
101 resource,
102 },
103 };
104}