diff --git a/packages/components/src/api/media_files/ListMediaFiles.ts b/packages/components/src/api/media_files/ListMediaFiles.ts new file mode 100644 index 0000000000..4b9e262a7b --- /dev/null +++ b/packages/components/src/api/media_files/ListMediaFiles.ts @@ -0,0 +1,26 @@ +import MakeRequest from "../MakeRequest"; +import { MediaFile } from "./GetMedia"; +// import { MediaFileType } from "../_common/enums/MediaFileType"; +import { Pagination } from "../_common/SharedFetchTypes"; + +export interface ListMediaFilesRequest {} + +export interface ListMediaFilesResponse { + pagination: Pagination; + success: boolean; + results: MediaFile[]; +} + +export interface ListMediaFilesParams { + page_index: number; +} + +export const ListMediaFiles = MakeRequest< + string, + ListMediaFilesRequest, + ListMediaFilesResponse, + ListMediaFilesParams +>({ + method: "GET", + routingFunction: () => `/v1/media_files/list`, +}); diff --git a/packages/fakeyou.com/src/hooks/useListContent/useListContent.tsx b/packages/fakeyou.com/src/hooks/useListContent/useListContent.tsx index f7d0bfeee6..59ce127c1e 100644 --- a/packages/fakeyou.com/src/hooks/useListContent/useListContent.tsx +++ b/packages/fakeyou.com/src/hooks/useListContent/useListContent.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState } from "react"; import { useSession } from "hooks"; interface Props { @@ -8,9 +8,18 @@ interface Props { listSet: any; pagePreset?: number; requestList?: boolean; + isInfiniteScroll?: boolean; } -export default function useListContent({ addQueries, fetcher, list, listSet, pagePreset = 0, requestList = false }: Props) { +export default function useListContent({ + addQueries, + fetcher, + list, + listSet, + pagePreset = 0, + requestList = false, + isInfiniteScroll = false, +}: Props) { const { user } = useSession(); const [filter, filterSet] = useState("all"); const [page, pageSet] = useState(pagePreset); @@ -20,12 +29,17 @@ export default function useListContent({ addQueries, fetcher, list, listSet, pag const pageChange = (page: number) => { pageSet(page); + if (!isInfiniteScroll || page === 1) { + listSet([]); // Reset list if not in infinite scroll mode or starting from first page + } statusSet(1); }; - const onChange = ({ target }: { target: { name: string, value: any} }) => { - const todo: { [ key: string]: (x: any) => void } = { filterSet, sortSet }; + const onChange = ({ target }: { target: { name: string; value: any } }) => { + const todo: { [key: string]: (x: any) => void } = { filterSet, sortSet }; todo[target.name + "Set"](target.value); + pageSet(1); // Reset to first page on filter/sort change + listSet([]); // Reset list on filter/sort change statusSet(1); }; @@ -33,22 +47,40 @@ export default function useListContent({ addQueries, fetcher, list, listSet, pag if (user && user.username) { if (status === 1) { statusSet(2); - fetcher(user.username, {}, { - page_index: page, - ...addQueries, // eventually we should provide a way to type this ... or not. It works - ...filter !== "all" ? { filter_media_type: filter } : {}, - ...sort !== "newest" ? { sort_ascending: true } : {}, - }).then((res: any) => { + fetcher( + user.username, + {}, + { + page_index: page, + ...addQueries, // eventually we should provide a way to type this ... or not. It works + ...(filter !== "all" ? { filter_media_type: filter } : {}), + ...(sort !== "newest" ? { sort_ascending: true } : {}), + } + ).then((res: any) => { statusSet(3); - console.log("🧶",res); + console.log("🧶", res); if (res.results && res.pagination) { - pageCountSet(res.pagination.total_page_count) - listSet(res.results); + pageCountSet(res.pagination.total_page_count); + if (isInfiniteScroll && page !== 1) { + listSet((prevList: any) => [...prevList, ...res.results]); // Append to list for infinite scroll + } else { + listSet(res.results); // Replace list for regular pagination + } } }); } } - }, [addQueries, fetcher, filter, listSet, page, user, sort, status]); + }, [ + addQueries, + fetcher, + filter, + listSet, + page, + user, + sort, + status, + isInfiniteScroll, + ]); return { filter, @@ -63,6 +95,6 @@ export default function useListContent({ addQueries, fetcher, list, listSet, pag sort, sortSet, status, - statusSet + statusSet, }; -}; \ No newline at end of file +} diff --git a/packages/fakeyou.com/src/v2/view/pages/explore/tabs/MediaTab.tsx b/packages/fakeyou.com/src/v2/view/pages/explore/tabs/MediaTab.tsx index 6d3e87000a..7bcb9bdb30 100644 --- a/packages/fakeyou.com/src/v2/view/pages/explore/tabs/MediaTab.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/explore/tabs/MediaTab.tsx @@ -1,39 +1,40 @@ -import React, { useRef, useState } from "react"; +import React, { useCallback, useRef, useState } from "react"; import MasonryGrid from "components/common/MasonryGrid/MasonryGrid"; -import mockMediaData from "./mockMediaData"; 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 { 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 { ListMediaFiles } from "@storyteller/components/src/api/media_files/ListMediaFiles"; +import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia"; +import { useListContent } from "hooks"; import InfiniteScroll from "react-infinite-scroll-component"; export default function MediaTab() { const gridContainerRef = useRef(null); - const [data, setData] = useState(mockMediaData); const [isLoading] = useState(false); - const [hasMore, setHasMore] = useState(true); - const fetchMoreData = () => { - // Simulate a delay (like fetching API) - setTimeout(() => { - const moreData = data.concat( - // Here, create more dummy data - mockMediaData.map(item => ({ ...item, id: item.token + data.length })) - ); + const [list, listSet] = useState([]); + const media = useListContent({ + fetcher: ListMediaFiles, + list, + listSet, + pagePreset: 1, + requestList: true, + isInfiniteScroll: true, + }); - setData(moreData); - - if (moreData.length >= mockMediaData.length * 2) { - setHasMore(false); - } - }, 1500); - }; + // Fetch more data for infinite scroll + const fetchMoreData = useCallback(() => { + if (media.page < media.pageCount) { + media.pageChange(media.page + 1); + } + }, [media]); const filterOptions = [ { value: "all", label: "All Media" }, @@ -52,17 +53,23 @@ export default function MediaTab() { <>
-
@@ -75,8 +82,9 @@ export default function MediaTab() { ) : (
@@ -84,41 +92,29 @@ export default function MediaTab() {
} - dataLength={data.length} + endMessage={ +

No more results.

+ } className="overflow-hidden" > console.log("Layout complete!")} > - {data.map((data, index) => { + {media.list.map((data: MediaFile, index: number) => { let card; switch (data.media_type) { case "audio": - card = ( - - ); + card = ; break; case "image": - card = ( - - ); + card = ; break; case "video": - card = ; + card = ; break; default: - card =
Unsupported media type
; + card =
Unsupported media type
; } return (