diff --git a/src/website/packages/components/src/api/index.tsx b/src/website/packages/components/src/api/index.tsx index 888a89a970..bf162cb57c 100644 --- a/src/website/packages/components/src/api/index.tsx +++ b/src/website/packages/components/src/api/index.tsx @@ -2,12 +2,16 @@ import { FetchStatus } from "./_common/SharedFetchTypes"; import { MediaFileType, GetMediaByUser } from "./media_files"; import { Weight, ListWeights, ListFeaturedWeights } from "./weights"; import { GetBookmarksByUser } from "./bookmarks/GetBookmarksByUser"; +import { MediaFileClass } from "./enums/MediaFileClass"; +import { BucketConfig } from "./BucketConfig"; export type { MediaFileType, Weight }; export { + BucketConfig, FetchStatus, GetBookmarksByUser, GetMediaByUser, ListWeights, ListFeaturedWeights, + MediaFileClass, }; diff --git a/src/website/packages/fakeyou.com/src/components/common/Button/Button.tsx b/src/website/packages/fakeyou.com/src/components/common/Button/Button.tsx index 478232e783..336a941b17 100644 --- a/src/website/packages/fakeyou.com/src/components/common/Button/Button.tsx +++ b/src/website/packages/fakeyou.com/src/components/common/Button/Button.tsx @@ -10,6 +10,7 @@ export default function Button({ buttonRef, label, icon, + onClick, small, variant: variantProps = "primary", to, @@ -74,6 +75,7 @@ export default function Button({ square ? (small ? "button-square-small" : "button-square") : "" } button-${variant} ${full ? "w-100" : ""}`, disabled: disabled || isLoading, + onClick, }; delete rest.className; @@ -95,18 +97,14 @@ export default function Button({ ); const WrappedButton = to ? ( - - {ButtonContent} - + {ButtonContent} ) : href ? ( {ButtonContent} diff --git a/src/website/packages/fakeyou.com/src/components/common/Button/ButtonProps.tsx b/src/website/packages/fakeyou.com/src/components/common/Button/ButtonProps.tsx index f58aa238d3..f904397a8b 100644 --- a/src/website/packages/fakeyou.com/src/components/common/Button/ButtonProps.tsx +++ b/src/website/packages/fakeyou.com/src/components/common/Button/ButtonProps.tsx @@ -5,6 +5,7 @@ export default interface ButtonProps extends ButtonHTMLAttributes { buttonRef?: any; label?: string | null; + onClick?: (e: any) => any; icon?: IconDefinition; small?: boolean; variant?: string; diff --git a/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.scss b/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.scss index a858c3ba58..a6153b3246 100644 --- a/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.scss +++ b/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/InferenceJobsList.scss @@ -55,10 +55,11 @@ $primary-transparent: rgba($primary, 0.75); .fy-inference-jobs-list-grid { display: grid; - grid-template-columns: 2.25rem fit-content(100px) minmax(0, 1fr) minmax( + grid-template-columns: min-content fit-content(100px) minmax(0, 1fr) minmax( min-content, 1fr ); + // grid-template-rows: 4rem; gap: 1rem 0; .work-indicator { @@ -75,7 +76,7 @@ $primary-transparent: rgba($primary, 0.75); .fy-inference-job-hover-on, .fy-inference-job-hover-off { - padding: 0.5rem; + padding: 0.75rem; // &:first-of-type { } } @@ -83,6 +84,12 @@ $primary-transparent: rgba($primary, 0.75); .fy-inference-job-success { cursor: pointer; + button { + height: 2.25rem; + width: 2.25rem; + margin: auto 0 auto 1rem; + } + &.fy-inference-job-hover-on { background-color: $panel-inner; } @@ -90,8 +97,8 @@ $primary-transparent: rgba($primary, 0.75); .fy-inference-job-indicator { border-radius: 0.5rem 0 0 0.5rem; - margin-left: -0.5rem; - padding-right: 0; + // margin-left: -0.5rem; + // padding-right: 0; .fy-inference-job-indicator-container { // background-color: red; @@ -162,7 +169,7 @@ $primary-transparent: rgba($primary, 0.75); } .fy-inference-job-action-frame { - margin-right: -0.5rem; + // margin-right: -0.5rem; position: relative; padding: 0; // width: fit-content; @@ -175,12 +182,8 @@ $primary-transparent: rgba($primary, 0.75); cursor: pointer; margin: auto; white-space: nowrap; - // padding-left: .75rem; - // display: flex; - // align-items: center; border-radius: 0.5rem; - // line-height: 1em; - margin: auto 0 auto auto; + margin: auto 0 auto 1rem; } .job-status-complete-success { @@ -222,6 +225,33 @@ $primary-transparent: rgba($primary, 0.75); // height: 2.25rem; } } + + .fy-inference-job-preview { + // background-color: red; + // grid-column-start: 1; + // grid-column-end: five; + + .fy-inference-job-preview-thumb { + // background-color: blue; + // margin: 3rem 0; + height: 3.25rem; + width: fit-content; + overflow: hidden; + aspect-ratio: 4/3; + position: relative; + + .fy-inference-job-preview-static, + .fy-inference-job-preview-gif { + position: absolute; + border-radius: 0.5rem; + width: auto; + height: 100%; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + } } .fy-job-queue-ticker { diff --git a/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/JobItem.tsx b/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/JobItem.tsx index 1c94a612f3..22c54fe212 100644 --- a/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/JobItem.tsx +++ b/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/JobItem.tsx @@ -5,17 +5,21 @@ import { FrontendInferenceJobType, InferenceJob, } from "@storyteller/components/src/jobs/InferenceJob"; +import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia"; import { CancelJob, CancelJobResponse, } from "@storyteller/components/src/api/jobs/CancelJob"; -import { useHover, useSlides } from "hooks"; +import { MediaURLs, useHover, useMedia, useSlides } from "hooks"; import { JobState, jobStateCanChange, } from "@storyteller/components/src/jobs/JobStates"; +import { Button } from "components/common"; import { useHistory } from "react-router-dom"; import { STYLES_BY_KEY } from "common/StyleOptions"; +import JobResultPreview from "./JobResultPreview"; +import { faArrowDownToLine } from "@fortawesome/pro-solid-svg-icons"; interface JobListItem extends InferenceJob { failures: (fail: string) => string; @@ -28,18 +32,56 @@ interface JobListItem extends InferenceJob { const BaseAction = ({ canStop = false, + hover = false, + mediaFile, + maybeResultToken = "", success = false, toggleSlide = () => {}, + urls, +}: { + canStop: boolean; + hover: boolean; + mediaFile: MediaFile; + maybeResultToken: string; + success: boolean; + toggleSlide: () => void; + urls: MediaURLs; }) => canStop || success ? ( - - - + <> + + {success && ( + { + e.stopPropagation(); + }, + square: true, + small: true, + target: "_blank", + variant: "secondary", + }} + /> + )} + + + + > ) : ( <>> ); @@ -164,12 +206,22 @@ export default function JobItem({ } }; + const { mediaFile, urls } = useMedia({ mediaToken: maybeResultToken || "" }); + const slides = useSlides({ index, slides: [ { component: BaseAction, - props: { success, toggleSlide, canStop: canStop() }, + props: { + canStop: canStop(), + hover, + maybeResultToken, + mediaFile, + success, + toggleSlide, + urls, + }, }, { component: StopConfirm, props: { stopClick, toggleSlide } }, ], @@ -229,11 +281,6 @@ export default function JobItem({ {slides} - { - // - // { } - // - } > ); } diff --git a/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/JobResultPreview.tsx b/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/JobResultPreview.tsx new file mode 100644 index 0000000000..c1d68d98be --- /dev/null +++ b/src/website/packages/fakeyou.com/src/components/layout/InferenceJobsList/JobResultPreview.tsx @@ -0,0 +1,66 @@ +import React from "react"; +import { MediaURLs } from "hooks"; +// import { MediaFileClass } from "../enums/MediaFileClass"; +import { MediaFileClass } from "@storyteller/components/src/api"; + +import { a, TransitionFn, useTransition } from "@react-spring/web"; +import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia"; + +interface JobResultPreviewProps { + hover: boolean; + mediaFile: MediaFile; + show?: boolean; + urls: MediaURLs; +} + +export default function JobResultPreview({ + hover, + mediaFile, + show, + urls, +}: JobResultPreviewProps) { + const transitions: TransitionFn = useTransition( + hover, + { + config: { mass: 1, tension: 80, friction: 10 }, + from: { opacity: 0 }, + enter: { opacity: 1 }, + leave: { opacity: 0 }, + } + ); + + const previewSwitch = () => { + switch (mediaFile?.media_class) { + case MediaFileClass.Image: + return Image; + case MediaFileClass.Video: + return ( + + + {transitions((style, isHovering) => + isHovering ? ( + + ) : null + )} + + ); + default: + return null; + } + }; + + return show ? ( + {previewSwitch()} + ) : null; +} diff --git a/src/website/packages/fakeyou.com/src/hooks/index.tsx b/src/website/packages/fakeyou.com/src/hooks/index.tsx index f613985d06..4ce4a276df 100644 --- a/src/website/packages/fakeyou.com/src/hooks/index.tsx +++ b/src/website/packages/fakeyou.com/src/hooks/index.tsx @@ -12,7 +12,7 @@ import useChanger from "./useChanger"; import useCoverImgUpload from "./useCoverImgUpload"; import useDebounce from "./useDebounce"; import useFile from "./useFile"; -import useHover from "./useHover"; +import useHover, { HoverValues } from "./useHover"; import useId from "./useId"; import useIdempotency from "./useIdempotency"; import useInferenceJobs from "./useInferenceJobs"; @@ -22,7 +22,7 @@ import useJobStatus from "./useJobStatus"; import useLazyLists from "./useLazyLists"; import useListContent from "./useListContent"; import useLocalize from "./useLocalize"; -import useMedia from "./useMedia"; +import useMedia, { MediaURLs } from "./useMedia"; import useMediaUploader from "./useMediaUploader"; import useModal from "./useModal"; import useModalState, { ModalConfig, ModalWidth } from "./useModalState"; @@ -83,9 +83,11 @@ export type { AnimationEvents, BatchInputProps, CameraState, + HoverValues, MakeBookmarksProps, MakeBatchPropsParams, MakeRatingsProps, + MediaURLs, ModalConfig, ModalWidth, }; diff --git a/src/website/packages/fakeyou.com/src/hooks/useHover/useHover.tsx b/src/website/packages/fakeyou.com/src/hooks/useHover.tsx similarity index 61% rename from src/website/packages/fakeyou.com/src/hooks/useHover/useHover.tsx rename to src/website/packages/fakeyou.com/src/hooks/useHover.tsx index 8f0b07a28c..41e406141f 100644 --- a/src/website/packages/fakeyou.com/src/hooks/useHover/useHover.tsx +++ b/src/website/packages/fakeyou.com/src/hooks/useHover.tsx @@ -1,14 +1,24 @@ import { useState } from "react"; +type hoverEventFn = (e?: any) => void; + interface UseHoverParams { - onMouseEnter?: (e?: any) => void; - onMouseLeave?: (e?: any) => void; + onMouseEnter?: hoverEventFn; + onMouseLeave?: hoverEventFn; } +export type HoverValues = [ + boolean, + { + onMouseEnter: hoverEventFn; + onMouseLeave: hoverEventFn; + }, +]; + export default function useHover({ onMouseEnter = () => {}, onMouseLeave = () => {}, -}: UseHoverParams) { +}: UseHoverParams): HoverValues { const [hover, hoverSet] = useState(false); const onHover = (x: boolean) => (e: any) => { hoverSet(x); diff --git a/src/website/packages/fakeyou.com/src/hooks/useHover/index.tsx b/src/website/packages/fakeyou.com/src/hooks/useHover/index.tsx deleted file mode 100644 index fe4049453f..0000000000 --- a/src/website/packages/fakeyou.com/src/hooks/useHover/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from './useHover'; diff --git a/src/website/packages/fakeyou.com/src/hooks/useMedia/useMedia.tsx b/src/website/packages/fakeyou.com/src/hooks/useMedia.tsx similarity index 80% rename from src/website/packages/fakeyou.com/src/hooks/useMedia/useMedia.tsx rename to src/website/packages/fakeyou.com/src/hooks/useMedia.tsx index e327601dd8..5974024f47 100644 --- a/src/website/packages/fakeyou.com/src/hooks/useMedia/useMedia.tsx +++ b/src/website/packages/fakeyou.com/src/hooks/useMedia.tsx @@ -11,6 +11,14 @@ import { DeleteMedia } from "@storyteller/components/src/api/media_files/DeleteM import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes"; import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; +type ThumbFn = (width?: number, quality?: number) => string; + +export interface MediaURLs { + file: string; + gif: ThumbFn; + thumb: ThumbFn; +} + export default function useMedia({ debug = "", mediaToken = "", @@ -42,11 +50,19 @@ export default function useMedia({ status === FetchStatus.in_progress || writeStatus === FetchStatus.in_progress; - // const bucketConfig = new BucketConfig(); + const bucketConfig = new BucketConfig(); - const bucketUrl = media?.public_bucket_path - ? new BucketConfig().getGcsUrl(media.public_bucket_path) - : ""; + const publicBucketPath = media?.public_bucket_path || ""; + + const bucketUrl = bucketConfig.getGcsUrl(publicBucketPath); + + const urls = { + file: bucketConfig.getGcsUrl(publicBucketPath), + gif: (width = 360, quality = 20) => + bucketConfig.getCdnUrl(publicBucketPath + "-thumb.gif", width, quality), + thumb: (width = 600, quality = 100) => + bucketConfig.getCdnUrl(publicBucketPath + "-thumb.jpg", width, quality), + }; useEffect(() => { // this condidition handles all media file fetches @@ -96,6 +112,7 @@ export default function useMedia({ reload, status, statusSet, + urls, writeStatus, }; } diff --git a/src/website/packages/fakeyou.com/src/hooks/useMedia/index.ts b/src/website/packages/fakeyou.com/src/hooks/useMedia/index.ts deleted file mode 100644 index 35c7ce6054..0000000000 --- a/src/website/packages/fakeyou.com/src/hooks/useMedia/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './useMedia'; \ No newline at end of file