Skip to content
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

feat(pipeline-builder): support video/multiple-video in pipeline builder #943

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions packages/design-system/src/new-ui/Icons/MultipleVideo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from "react";
import { IconBase, IconBaseProps } from "./IconBase";

export const MultipleVideo = React.forwardRef<
SVGSVGElement,
Omit<IconBaseProps, "viewBox" | "children">
>((props, ref) => {
const { className, ...passThrough } = props;
return (
<IconBase
{...passThrough}
ref={ref}
viewBox="0 0 25 24"
className={className}
>
<g clip-path="url(#clip0_1497_93)">
<path
d="M16.943 4.80003L12.943 8.00003L8.94304 4.80003M20.943 12.5093V11.84C20.943 10.4959 20.943 9.82384 20.6815 9.31045C20.4514 8.85886 20.0842 8.49171 19.6326 8.26161C19.1192 8.00003 18.4472 8.00003 17.103 8.00003H8.78304C7.43891 8.00003 6.76685 8.00003 6.25346 8.26161C5.80187 8.49171 5.43472 8.85886 5.20462 9.31045C4.94304 9.82384 4.94304 10.4959 4.94304 11.84V15.36C4.94304 16.7042 4.94304 17.3762 5.20462 17.8896C5.43472 18.3412 5.80187 18.7083 6.25346 18.9384C6.76685 19.2 7.43891 19.2 8.78304 19.2H14.1772M20.943 22.2001V19.2001M20.943 19.2001V16.2001M20.943 19.2001H17.943M20.943 19.2001H23.943"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_1497_93">
<rect
width="24"
height="24"
fill="white"
transform="translate(0.943039)"
/>
</clipPath>
</defs>
</IconBase>
);
});
MultipleVideo.displayName = "IconMultipleVideo";
25 changes: 25 additions & 0 deletions packages/design-system/src/new-ui/Icons/Video.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from "react";
import { IconBase, IconBaseProps } from "./IconBase";

export const Video = React.forwardRef<
SVGSVGElement,
Omit<IconBaseProps, "viewBox" | "children">
>((props, ref) => {
const { className, ...passThrough } = props;
return (
<IconBase
{...passThrough}
ref={ref}
viewBox="0 0 24 24"
className={className}
>
<path
d="M16 4.8L12 8L8 4.8M7.84 19.2H16.16C17.5041 19.2 18.1762 19.2 18.6896 18.9384C19.1412 18.7083 19.5083 18.3412 19.7384 17.8896C20 17.3762 20 16.7041 20 15.36V11.84C20 10.4959 20 9.82381 19.7384 9.31043C19.5083 8.85884 19.1412 8.49168 18.6896 8.26159C18.1762 8 17.5041 8 16.16 8H7.84C6.49587 8 5.82381 8 5.31042 8.26159C4.85883 8.49168 4.49168 8.85884 4.26158 9.31043C4 9.82381 4 10.4959 4 11.84V15.36C4 16.7041 4 17.3762 4.26158 17.8896C4.49168 18.3412 4.85883 18.7083 5.31042 18.9384C5.82381 19.2 6.49587 19.2 7.84 19.2Z"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</IconBase>
);
});
Video.displayName = "IconVideo";
4 changes: 4 additions & 0 deletions packages/design-system/src/new-ui/Icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { ImagePlus } from "./ImagePlus";
import { Logout01 } from "./Logout01";
import { LayersTwo01 } from "./LayersTwo01";
import { Lightning01 } from "./Lightning01";
import { MultipleVideo } from "./MultipleVideo";
import { Model } from "./Model";
import { PauseCircle } from "./PauseCircle";
import { MasterCard } from "./MasterCard";
Expand Down Expand Up @@ -95,6 +96,7 @@ import { Upload01 } from "./Upload01";
import { User01 } from "./User01";
import { User02 } from "./User02";
import { UserPlus01 } from "./UserPlus01";
import { Video } from "./Video";
import { VideoRecorder } from "./VideoRecorder";
import { Visa } from "./Visa";
import { VisualQuestionAnswering } from "./VisualQuestionAnswering";
Expand Down Expand Up @@ -163,6 +165,7 @@ export const Icons = {
LayersTwo01,
Lightning01,
Model,
MultipleVideo,
PauseCircle,
MasterCard,
Menu01,
Expand Down Expand Up @@ -198,6 +201,7 @@ export const Icons = {
User01,
User02,
UserPlus01,
Video,
VideoRecorder,
Visa,
VisualQuestionAnswering,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import cn from "clsx";
import * as React from "react";
import { FieldMode } from "../../types";
import { Icons } from "@instill-ai/design-system";

export const VideoPreview = ({
src,
className,
}: {
src: string;
className?: string;
}) => {
const [isPlaying, setIsPlaying] = React.useState(false);
const videoRef = React.useRef<HTMLVideoElement>(null);

return (
<div
onClick={() => {
if (videoRef.current?.paused) {
videoRef.current?.play();
setIsPlaying(true);
} else {
videoRef.current?.pause();
setIsPlaying(false);
}
}}
className="relative"
>
<video
ref={videoRef}
src={src}
className={cn("w-full object-contain", className)}
/>
{isPlaying ? (
<div className="absolute bottom-0 left-0 right-0 top-0 z-10 flex items-center justify-center">
<CustomizePauseIcon className="h-1/3 w-1/3 stroke-white stroke-1" />
</div>
) : (
<div className="absolute bottom-0 left-0 right-0 top-0 z-10 flex items-center justify-center">
<CustomizePlayIcon className="h-1/3 w-1/3 stroke-white" />
</div>
)}
</div>
);
};

const CustomizePlayIcon = ({ className }: { className?: string }) => {
return (
<svg
viewBox="0 0 80 80"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<rect
x="1.5"
y="1.5"
width="77"
height="77"
rx="38.5"
stroke="white"
strokeWidth="3"
/>
<path
d="M56.25 37.904C57.9167 38.8355 57.9167 41.1645 56.25 42.096L33.75 54.6721C32.0833 55.6037 30 54.4392 30 52.5761L30 27.4239C30 25.5608 32.0833 24.3963 33.75 25.3279L56.25 37.904Z"
fill="white"
/>
</svg>
);
};

const CustomizePauseIcon = ({ className }: { className?: string }) => {
return (
<svg
viewBox="0 0 80 80"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<g filter="url(#filter0_b_857_30751)">
<path
d="M31.4998 28H28.4998V52H31.4998V28ZM51.4998 28H48.4998V52H51.4998V28ZM78.4998 40C78.4998 61.2629 61.2628 78.5 39.9998 78.5C18.7369 78.5 1.49985 61.2629 1.49985 40C1.49985 18.737 18.7369 1.49996 39.9998 1.49996C61.2628 1.49996 78.4998 18.737 78.4998 40Z"
stroke="white"
stroke-width="3"
/>
</g>
<defs>
<filter
id="filter0_b_857_30751"
x="-19.2002"
y="-19.2"
width="118.4"
height="118.4"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"
>
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feGaussianBlur in="BackgroundImageFix" stdDeviation="9.6" />
<feComposite
in2="SourceAlpha"
operator="in"
result="effect1_backgroundBlur_857_30751"
/>
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_backgroundBlur_857_30751"
result="shape"
/>
</filter>
</defs>
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./FieldDescriptionTooltip";
export * from "./VideoPreview";
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export const ImagesField = (props: ImagesFieldProps) => {
return (
<FieldRoot title={title} fieldKey={`${title}-field`}>
{images && !hideField ? (
<div className="flex w-full flex-wrap">
{images?.slice(0, 5)?.map((image) => {
<div className="flex w-full flex-wrap gap-2">
{images?.map((image) => {
if (!image) return null;

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Nullable } from "../../../type";
import { ComponentOutputFieldBaseProps } from "../../types";
import { VideoPreview } from "../common";
import { FieldRoot } from "./FieldRoot";

export type VideoFieldProps = {
video: Nullable<string>;
} & ComponentOutputFieldBaseProps;

export const VideoField = (props: VideoFieldProps) => {
const { title, video, hideField } = props;

return (
<FieldRoot title={title} fieldKey={`${title}-field`}>
{!hideField && video ? (
<VideoPreview src={video} className="w-full" />
) : null}
</FieldRoot>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Nullable } from "../../../type";
import { ComponentOutputFieldBaseProps } from "../../types";
import { VideoPreview } from "../common";
import { FieldRoot } from "./FieldRoot";

export type VideosFieldProps = {
videos: Nullable<string>[];
} & ComponentOutputFieldBaseProps;

export const VideosField = (props: VideosFieldProps) => {
const { title, videos, hideField } = props;

return (
<FieldRoot title={title} fieldKey={`${title}-field`}>
{videos && !hideField ? (
<div className="flex w-full flex-wrap gap-2">
{videos.map((video) => {
if (!video) return null;

return (
<VideoPreview
key={`${title}-${video}-field`}
src={video}
className="object-contain"
/>
);
})}
</div>
) : null}
</FieldRoot>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { ObjectField } from "./ObjectField";
import { ObjectsField } from "./ObjectsField";
import { TextField } from "./TextField";
import { TextsField } from "./TextsField";
import { VideoField } from "./VideoField";
import { VideosField } from "./VideosField";

export const ComponentOutputFields = {
AudioField,
Expand All @@ -20,4 +22,6 @@ export const ComponentOutputFields = {
ObjectsField,
TextField,
TextsField,
VideoField,
VideosField,
};
Loading
Loading