diff --git a/packages/components/src/api/_common/enums/WeightType.ts b/packages/components/src/api/_common/enums/WeightType.ts index f4e51c6846..3866895148 100644 --- a/packages/components/src/api/_common/enums/WeightType.ts +++ b/packages/components/src/api/_common/enums/WeightType.ts @@ -8,3 +8,17 @@ export enum WeightType { LORA = "loRA", VALL_E = "vall_e", } + +export const weightTypeInfo = { + [WeightType.TT2]: { label: "TT2", color: "teal" }, + [WeightType.HIFIGAN_TT2]: { + label: "HifiGAN TT2", + color: "blue", + }, + [WeightType.RVCv2]: { label: "RVCv2", color: "orange" }, + [WeightType.SD_15]: { label: "SD 1.5", color: "green" }, + [WeightType.SDXL]: { label: "SDXL", color: "purple" }, + [WeightType.SVC]: { label: "SVC", color: "cyan" }, + [WeightType.LORA]: { label: "LoRA", color: "pink" }, + [WeightType.VALL_E]: { label: "VALL-E", color: "ultramarine" }, +}; diff --git a/packages/components/src/api/media_files/ListMediaFiles.ts b/packages/components/src/api/media_files/ListMediaFiles.ts index c19d011c4c..c13f626c4e 100644 --- a/packages/components/src/api/media_files/ListMediaFiles.ts +++ b/packages/components/src/api/media_files/ListMediaFiles.ts @@ -1,6 +1,5 @@ import MakeRequest from "../MakeRequest"; import { MediaFile } from "./GetMedia"; -// import { MediaFileType } from "../_common/enums/MediaFileType"; import { LazyPagination } from "../_common/SharedFetchTypes"; export interface ListMediaFilesRequest {} diff --git a/packages/components/src/api/weights/GetWeight.ts b/packages/components/src/api/weights/GetWeight.ts index 2a69f6b291..f517aab6bb 100644 --- a/packages/components/src/api/weights/GetWeight.ts +++ b/packages/components/src/api/weights/GetWeight.ts @@ -1,28 +1,42 @@ -// import MakeRequest from "../MakeRequest"; +import MakeRequest from "../MakeRequest"; import { UserDetailsLight } from "../_common/UserDetailsLight"; import { WeightCategory } from "../_common/enums/WeightCategory"; import { WeightType } from "../_common/enums/WeightType"; export interface Weight { weight_token: string; - weight_type: WeightType; - weight_category: WeightCategory; - maybe_creator_user: UserDetailsLight | null; + weights_type: WeightType; + weights_category: WeightCategory; + title: string; + public_bucket_path: string; creator_set_visibility: string; created_at: Date; updated_at: Date; - title: string; + creator: UserDetailsLight; description_markdown: string; + description_rendered_html: string; + file_checksum_sha2: string; + file_size_bytes: number; + maybe_cached_user_ratings_ratio: number | null; + maybe_cover_image_public_bucket_path: string | null; + version: number; } -// export interface GetMediaRequest {} +export interface GetWeightRequest { + weight_token: "string"; +} -// export interface GetMediaResponse { -// success: boolean, -// media_file?: MediaFile, -// } +export interface GetWeightResponse { + success: boolean; + media_file?: Weight; +} -// export const GetMedia = MakeRequest({ -// method: "GET", -// routingFunction: (mediaFileToken: string) => `/v1/media_files/file/${mediaFileToken}`, -// }); +export const GetWeight = MakeRequest< + string, + GetWeightRequest, + GetWeightResponse, + {} +>({ + method: "GET", + routingFunction: (weightToken: string) => `/v1/weights/weight/${weightToken}`, +}); diff --git a/packages/components/src/api/weights/ListWeights.ts b/packages/components/src/api/weights/ListWeights.ts new file mode 100644 index 0000000000..3c3fca9d9e --- /dev/null +++ b/packages/components/src/api/weights/ListWeights.ts @@ -0,0 +1,25 @@ +import MakeRequest from "../MakeRequest"; +import { Weight } from "./GetWeight"; +import { LazyPagination } from "../_common/SharedFetchTypes"; + +export interface ListWeightsRequest {} + +export interface ListWeightsResponse { + pagination: LazyPagination; + success: boolean; + results: Weight[]; +} + +export interface ListWeightsParams { + page_index: number; +} + +export const ListWeights = MakeRequest< + string, + ListWeightsRequest, + ListWeightsResponse, + ListWeightsParams +>({ + method: "GET", + routingFunction: () => `/v1/weights/list`, +}); diff --git a/packages/fakeyou.com/src/components/common/Card/AudioCard/AudioCard.tsx b/packages/fakeyou.com/src/components/common/Card/AudioCard/AudioCard.tsx index 7de27ff126..9fed75569a 100644 --- a/packages/fakeyou.com/src/components/common/Card/AudioCard/AudioCard.tsx +++ b/packages/fakeyou.com/src/components/common/Card/AudioCard/AudioCard.tsx @@ -25,13 +25,11 @@ export default function AudioCard({ }: AudioCardProps) { const history = useHistory(); - // console.log("🐙",data, data.public_bucket_path); - const handleCardClick = () => { if (type === "media") { history.push(`/media/${data.token}`); } else if (type === "weights") { - history.push(`/weight/${data.token}`); + history.push(`/weight/${data.weight_token}`); } }; @@ -81,13 +79,15 @@ export default function AudioCard({ {showCreator && (
)} @@ -126,9 +126,7 @@ export default function AudioCard({
-
- {data.weight_name} -
+
{data.title}

{timeAgo}

@@ -144,15 +142,13 @@ export default function AudioCard({ {showCreator && (
)} diff --git a/packages/fakeyou.com/src/components/common/Card/ImageCard/ImageCard.tsx b/packages/fakeyou.com/src/components/common/Card/ImageCard/ImageCard.tsx index b943b86407..ac3dcb3bff 100644 --- a/packages/fakeyou.com/src/components/common/Card/ImageCard/ImageCard.tsx +++ b/packages/fakeyou.com/src/components/common/Card/ImageCard/ImageCard.tsx @@ -8,6 +8,7 @@ import FavoriteButton from "components/common/FavoriteButton"; import CreatorName from "../CreatorName"; import Button from "components/common/Button"; import { faArrowRight } from "@fortawesome/pro-solid-svg-icons"; +import useWeightTypeInfo from "hooks/useWeightTypeInfo/useWeightTypeInfo"; interface ImageCardProps { data: any; @@ -22,7 +23,7 @@ export default function ImageCard({ data, type, showCreator }: ImageCardProps) { if (type === "media") { history.push(`/media/${data.token}`); } else if (type === "weights") { - history.push(`/weight/${data.token}`); + history.push(`/weight/${data.weight_token}`); } }; @@ -36,6 +37,9 @@ export default function ImageCard({ data, type, showCreator }: ImageCardProps) { console.log(`The item is now ${data.isLiked ? "liked" : "not liked"}.`); }; + const { label: weightBadgeLabel, color: weightBadgeColor } = + useWeightTypeInfo(data.weights_type); + return ( {type === "media" && ( @@ -68,11 +72,17 @@ export default function ImageCard({ data, type, showCreator }: ImageCardProps) { {showCreator && (
)} @@ -89,15 +99,22 @@ export default function ImageCard({ data, type, showCreator }: ImageCardProps) { {type === "weights" && ( <> {data.weight_name}
- +
diff --git a/packages/fakeyou.com/src/components/common/Card/VideoCard/VideoCard.tsx b/packages/fakeyou.com/src/components/common/Card/VideoCard/VideoCard.tsx index 6eb592c25d..46600a2032 100644 --- a/packages/fakeyou.com/src/components/common/Card/VideoCard/VideoCard.tsx +++ b/packages/fakeyou.com/src/components/common/Card/VideoCard/VideoCard.tsx @@ -64,11 +64,17 @@ export default function VideoCard({ data, type, showCreator }: VideoCardProps) { {showCreator && (
)} diff --git a/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx b/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx index 0e2fb19312..cd8d137f3a 100644 --- a/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx +++ b/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx @@ -1,6 +1,6 @@ -import Masonry from "masonry-layout"; //Refer to: https://github.com/desandro/masonry -import imagesLoaded from "imagesloaded"; //Refer to: https://github.com/desandro/imagesloaded -import React, { useEffect } from "react"; +import React, { useEffect, useRef } from "react"; +import Masonry from "masonry-layout"; +import imagesLoaded from "imagesloaded"; interface MasonryGridProps { children: React.ReactNode; @@ -13,38 +13,77 @@ export default function MasonryGrid({ onLayoutComplete, gridRef, }: MasonryGridProps) { + const masonryInstance = useRef(null); + useEffect(() => { - let masonryInstance: Masonry | null = null; - - const updateLayout = () => { - //Needs this type guard to check that it is not undefined. - if (masonryInstance && typeof masonryInstance.layout === "function") { - masonryInstance.layout(); - } - }; - if (gridRef.current) { - masonryInstance = new Masonry(gridRef.current, { + masonryInstance.current = new Masonry(gridRef.current, { itemSelector: ".grid-item", percentPosition: true, transitionDuration: 0, }); - - //Needs this or images will overflow masonry card. It checks if image is loaded then after it is loaded, it resizes the card. - imagesLoaded(gridRef.current, function () { - updateLayout(); - onLayoutComplete?.(); - }); } - //Clean up return () => { - if (masonryInstance && typeof masonryInstance.destroy === "function") { - masonryInstance.destroy(); + if ( + masonryInstance.current && + typeof masonryInstance.current.destroy === "function" + ) { + masonryInstance.current.destroy(); } }; + }, [gridRef]); + + useEffect(() => { + const currentGrid = gridRef.current; + const currentMasonryInstance = masonryInstance.current; + + if (currentGrid && currentMasonryInstance) { + imagesLoaded(currentGrid, function () { + if (typeof currentMasonryInstance.layout === "function") { + currentMasonryInstance.layout(); + onLayoutComplete?.(); + } + }); + } }, [gridRef, onLayoutComplete]); + useEffect(() => { + const currentGrid = gridRef.current; + const currentMasonryInstance = masonryInstance.current; + + if (currentGrid && currentMasonryInstance) { + // Observer to detect when new grid items are added + const observer = new MutationObserver(mutations => { + mutations.forEach(mutation => { + if (mutation.addedNodes.length) { + // Append new items to the Masonry layout + const newItems = Array.from(mutation.addedNodes).filter( + node => + node instanceof HTMLElement && + node.classList.contains("grid-item") + ); + if (newItems.length) { + if (typeof currentMasonryInstance.appended === "function") { + currentMasonryInstance.appended(newItems); + } + } + } + }); + }); + + // Observe the grid for new items + observer.observe(currentGrid, { + childList: true, + }); + + // Clean up observer on unmount + return () => { + observer.disconnect(); + }; + } + }, [gridRef]); + return (
- {tabs.map(tab => ( - - {tab.content} - - ))} + + {activeTabProps?.content} + ); diff --git a/packages/fakeyou.com/src/hooks/useWeightTypeInfo/useWeightTypeInfo.tsx b/packages/fakeyou.com/src/hooks/useWeightTypeInfo/useWeightTypeInfo.tsx new file mode 100644 index 0000000000..ca3dac7c12 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useWeightTypeInfo/useWeightTypeInfo.tsx @@ -0,0 +1,25 @@ +import { WeightType } from "@storyteller/components/src/api/_common/enums/WeightType"; + +type WeightTypeInfo = { + [key in WeightType]: { label: string; color: string }; +}; + +const weightTypeInfo: WeightTypeInfo = { + [WeightType.TT2]: { label: "TT2", color: "teal" }, + [WeightType.HIFIGAN_TT2]: { label: "HifiGAN TT2", color: "blue" }, + [WeightType.RVCv2]: { label: "RVCv2", color: "orange" }, + [WeightType.SD_15]: { label: "SD 1.5", color: "green" }, + [WeightType.SDXL]: { label: "SDXL", color: "purple" }, + [WeightType.SVC]: { label: "SVC", color: "cyan" }, + [WeightType.LORA]: { label: "LoRA", color: "pink" }, + [WeightType.VALL_E]: { label: "VALL-E", color: "ultramarine" }, +}; + +export default function useWeightTypeInfo(weightsType: WeightType) { + return ( + weightTypeInfo[weightsType] || { + label: "Unknown", + color: "gray", + } + ); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/explore/tabs/FeaturedTab.tsx b/packages/fakeyou.com/src/v2/view/pages/explore/tabs/FeaturedTab.tsx index 8fd3efb6e7..91a27c9764 100644 --- a/packages/fakeyou.com/src/v2/view/pages/explore/tabs/FeaturedTab.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/explore/tabs/FeaturedTab.tsx @@ -6,7 +6,6 @@ import SkeletonCard from "components/common/Card/SkeletonCard"; import { Link } from "react-router-dom"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChevronRight } from "@fortawesome/pro-solid-svg-icons"; -import ImageCard from "components/common/Card/ImageCard"; export default function FeaturedTab() { const gridContainerRef = useRef(null); @@ -59,7 +58,7 @@ export default function FeaturedTab() { )}
-
+ {/*

Featured Image Weights @@ -98,7 +97,7 @@ export default function FeaturedTab() { })} )} -

+
*/}
); } diff --git a/packages/fakeyou.com/src/v2/view/pages/explore/tabs/WeightsTab.tsx b/packages/fakeyou.com/src/v2/view/pages/explore/tabs/WeightsTab.tsx index 914d3bba73..91b3de6daa 100644 --- a/packages/fakeyou.com/src/v2/view/pages/explore/tabs/WeightsTab.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/explore/tabs/WeightsTab.tsx @@ -1,149 +1,157 @@ import React, { useRef, useState } from "react"; import MasonryGrid from "components/common/MasonryGrid/MasonryGrid"; -import mockWeightsData from "./mockWeightsData"; import AudioCard from "components/common/Card/AudioCard"; import ImageCard from "components/common/Card/ImageCard"; -import VideoCard from "components/common/Card/VideoCard"; -import Select from "components/common/Select"; +// import VideoCard from "components/common/Card/VideoCard"; +import { TempSelect } from "components/common"; import { faArrowDownWideShort, faFilter, } from "@fortawesome/pro-solid-svg-icons"; +import AudioPlayerProvider from "components/common/AudioPlayer/AudioPlayerContext"; import SkeletonCard from "components/common/Card/SkeletonCard"; +import { ListWeights } from "@storyteller/components/src/api/weights/ListWeights"; +import { Weight } from "@storyteller/components/src/api/weights/GetWeight"; +import { useLazyLists } from "hooks"; +import InfiniteScroll from "react-infinite-scroll-component"; +import { WeightCategory } from "@storyteller/components/src/api/_common/enums/WeightCategory"; -export default function WeightsTab() { +export default function MediaTab() { const gridContainerRef = useRef(null); - const [data] = useState(mockWeightsData); const [isLoading] = useState(false); - const [selectedFilter, setSelectedFilter] = useState("all"); + + const [list, listSet] = useState([]); + const weights = useLazyLists({ + fetcher: ListWeights, + list, + listSet, + requestList: true, + }); const filterOptions = [ { value: "all", label: "All Weights" }, - { value: "tts", label: "Text to Speech" }, - { value: "vc", label: "Voice to Voice" }, - { value: "sd", label: "Image Generation" }, + { value: "images", label: "Image Generation" }, + { value: "audio", label: "Audio" }, + { value: "video", label: "Video" }, ]; const sortOptions = [ { value: "newest", label: "Newest" }, { value: "oldest", label: "Oldest" }, - { value: "mostliked", label: "Most Bookmarked" }, + { value: "mostliked", label: "Most Liked" }, ]; - const modelTtsOptions = [ - { value: "all", label: "All Types" }, - { value: "tt2", label: "Tacotron 2" }, - ]; - - const modelVcOptions = [ - { value: "all", label: "All Types" }, - { value: "rvc", label: "RVCv2" }, - { value: "svc", label: "SoVitsSvc" }, - ]; - - const modelSdOptions = [ - { value: "all", label: "All Types" }, - { value: "lora", label: "LoRA" }, - { value: "SD15", label: "SD 1.5" }, - { value: "SDXL", label: "SD XL" }, - ]; - - const handleFilterChange = (option: any) => { - const selectedOption = option as { value: string; label: string }; - setSelectedFilter(selectedOption.value); - }; - return ( <>
- - - {selectedFilter === "tts" && ( - - )} - {selectedFilter === "vc" && ( -