From 6eb563935e0787a94552fc29242fa5487bfebd15 Mon Sep 17 00:00:00 2001 From: BFlat Date: Mon, 27 Nov 2023 22:09:45 +0700 Subject: [PATCH] skeleton cards and infinite scroll --- packages/fakeyou.com/package.json | 2 + .../src/components/common/Card/Card.scss | 13 ++ .../common/Card/SkeletonCard/SkeletonCard.tsx | 37 ++++ .../common/Card/SkeletonCard/index.ts | 1 + .../common/Card/VideoCard/VideoCard.tsx | 2 +- .../common/MasonryGrid/MasonryGrid.tsx | 27 ++- .../profile/profile_view/tabs/MediaTab.tsx | 103 +++++++--- .../profile/profile_view/tabs/mockData.ts | 190 ++++++++++++++++++ yarn.lock | 51 ++++- 9 files changed, 384 insertions(+), 42 deletions(-) create mode 100644 packages/fakeyou.com/src/components/common/Card/SkeletonCard/SkeletonCard.tsx create mode 100644 packages/fakeyou.com/src/components/common/Card/SkeletonCard/index.ts diff --git a/packages/fakeyou.com/package.json b/packages/fakeyou.com/package.json index 7ee06fcf3c..d90a3807e1 100644 --- a/packages/fakeyou.com/package.json +++ b/packages/fakeyou.com/package.json @@ -28,6 +28,7 @@ "@types/gtag.js": "^0.0.12", "@types/howler": "^2.1.2", "@types/imagesloaded": "^4.1.6", + "@types/infinite-scroll": "^4.0.3", "@types/jest": "^24.9.1", "@types/js-cookie": "^3.0.1", "@types/masonry-layout": "^4.2.7", @@ -46,6 +47,7 @@ "i18next-browser-languagedetector": "^7.1.0", "i18next-http-backend": "^2.2.1", "imagesloaded": "^5.0.0", + "infinite-scroll": "^4.0.1", "js-cookie": "^3.0.1", "masonry-layout": "^4.2.2", "posthog-js": "^1.73.1", diff --git a/packages/fakeyou.com/src/components/common/Card/Card.scss b/packages/fakeyou.com/src/components/common/Card/Card.scss index 6c2334b738..d5c08790b7 100644 --- a/packages/fakeyou.com/src/components/common/Card/Card.scss +++ b/packages/fakeyou.com/src/components/common/Card/Card.scss @@ -17,6 +17,15 @@ max-height: 500px; } + .card-video { + width: 100%; + transition: 0.4s ease; + object-fit: cover; + object-position: center; + min-height: 240px; + max-height: 240px; + } + .card-img-overlay { position: absolute; bottom: 0; @@ -65,6 +74,10 @@ transform: scale(1.05); } + &:hover > .card-video { + transform: scale(1.05); + } + &:hover .card-video-play { color: rgba($white, 0.8); } diff --git a/packages/fakeyou.com/src/components/common/Card/SkeletonCard/SkeletonCard.tsx b/packages/fakeyou.com/src/components/common/Card/SkeletonCard/SkeletonCard.tsx new file mode 100644 index 0000000000..e622773985 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Card/SkeletonCard/SkeletonCard.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import Card from "../Card"; +import Skeleton from "components/common/Skeleton"; + +interface SkeletonCardProps {} + +export default function SkeletonCard(props: SkeletonCardProps) { + return ( +
+ +
+
+
+ +
+
+ +
+
+ +
+ +
+

+ +

+
+ +
+

+ +

+
+
+
+ ); +} diff --git a/packages/fakeyou.com/src/components/common/Card/SkeletonCard/index.ts b/packages/fakeyou.com/src/components/common/Card/SkeletonCard/index.ts new file mode 100644 index 0000000000..7a1d781a94 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Card/SkeletonCard/index.ts @@ -0,0 +1 @@ +export { default } from "./SkeletonCard"; 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 c784c0374c..47a9c133a4 100644 --- a/packages/fakeyou.com/src/components/common/Card/VideoCard/VideoCard.tsx +++ b/packages/fakeyou.com/src/components/common/Card/VideoCard/VideoCard.tsx @@ -33,7 +33,7 @@ export default function VideoCard({ data }: VideoCardProps) { {data.weight_name}
diff --git a/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx b/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx index d7ef5f8564..df2b4e27a7 100644 --- a/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx +++ b/packages/fakeyou.com/src/components/common/MasonryGrid/MasonryGrid.tsx @@ -1,17 +1,28 @@ 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, useRef } from "react"; +import React, { useEffect } from "react"; interface MasonryGridProps { children: React.ReactNode; + onLayoutComplete?: () => void; + gridRef: React.RefObject; } -export default function MasonryGrid({ children }: MasonryGridProps) { - const gridRef = useRef(null); - +export default function MasonryGrid({ + children, + onLayoutComplete, + gridRef, +}: MasonryGridProps) { 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, { itemSelector: ".grid-item", @@ -20,10 +31,8 @@ export default function MasonryGrid({ children }: MasonryGridProps) { //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 () { - //Needs this type guard to check that it is not undefined. - if (masonryInstance && typeof masonryInstance.layout === "function") { - masonryInstance.layout(); - } + updateLayout(); + onLayoutComplete?.(); }); } @@ -33,7 +42,7 @@ export default function MasonryGrid({ children }: MasonryGridProps) { masonryInstance.destroy(); } }; - }, []); + }, [gridRef, onLayoutComplete]); return (
(null); + + const fetchMoreData = () => { + if (data.length >= mockData.length) { + setHasMore(false); + return; + } + + // Simulate an API fetch + setTimeout(() => { + const startIndex = page * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + const nextItems = mockData.slice(startIndex, endIndex); + setData(data.concat(nextItems)); + setPage(page + 1); + }, 1500); + }; const options = [ { value: "all", label: "All Media" }, @@ -32,32 +55,52 @@ export default function MediaTab() { />
- - {data.map((data, index) => { - let card; - switch (data.media_type) { - case "audio": - card = ; - break; - case "image": - card = ; - break; - case "video": - card = ; - break; - default: - card =
Unsupported media type
; - } - return ( -
- {card} -
- ); - })} -
+ {isLoading ? ( +
+ {Array.from({ length: 6 }).map((_, index) => ( + + ))} +
+ ) : ( + Loading...} + endMessage={

No more media

} + className="overflow-hidden" + > + console.log("Layout complete!")} + > + {data.map((data, index) => { + let card; + switch (data.media_type) { + case "audio": + card = ; + break; + case "image": + card = ; + break; + case "video": + card = ; + break; + default: + card =
Unsupported media type
; + } + return ( +
+ {card} +
+ ); + })} +
+
+ )}
); diff --git a/packages/fakeyou.com/src/v2/view/pages/profile/profile_view/tabs/mockData.ts b/packages/fakeyou.com/src/v2/view/pages/profile/profile_view/tabs/mockData.ts index 0c4d879356..f6ab8532f3 100644 --- a/packages/fakeyou.com/src/v2/view/pages/profile/profile_view/tabs/mockData.ts +++ b/packages/fakeyou.com/src/v2/view/pages/profile/profile_view/tabs/mockData.ts @@ -94,6 +94,101 @@ let mockData = [ isLiked: true, created_at: "2023-08-10T09:00:00.000Z", }, + { + token: "token11", + weight_name: "Queen Elizabeth", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token12", + weight_name: "Monster House", + media_type: "image", + public_bucket_path: "/images/dummy-image.jpg", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token13", + weight_name: "Ronaldo", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token14", + weight_name: "Desert", + media_type: "video", + public_bucket_path: "/images/dummy-video.jpg", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token15", + weight_name: "3D Cat", + media_type: "image", + public_bucket_path: "/images/dummy-image-2.jpg", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token16", + weight_name: "Superman", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token17", + weight_name: "Son Goku", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token18", + weight_name: "Astronaut in Space", + media_type: "image", + public_bucket_path: "/images/dummy-image-3.jpg", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token19", + weight_name: "Monokuma", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token20", + weight_name: "Watery Landscape", + media_type: "image", + public_bucket_path: "/images/dummy-image-4.jpg", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, { token: "token1", weight_name: "Queen Elizabeth", @@ -189,6 +284,101 @@ let mockData = [ isLiked: true, created_at: "2023-08-10T09:00:00.000Z", }, + { + token: "token11", + weight_name: "Queen Elizabeth", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token12", + weight_name: "Monster House", + media_type: "image", + public_bucket_path: "/images/dummy-image.jpg", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token13", + weight_name: "Ronaldo", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token14", + weight_name: "Desert", + media_type: "video", + public_bucket_path: "/images/dummy-video.jpg", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token15", + weight_name: "3D Cat", + media_type: "image", + public_bucket_path: "/images/dummy-image-2.jpg", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token16", + weight_name: "Superman", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 200, + isLiked: false, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token17", + weight_name: "Son Goku", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token18", + weight_name: "Astronaut in Space", + media_type: "image", + public_bucket_path: "/images/dummy-image-3.jpg", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token19", + weight_name: "Monokuma", + media_type: "audio", + public_bucket_path: + "/media/s/p/x/d/2/spxd2xr7nt7zdezyhp61h00kxatr18pf/fakeyou_rvc_spxd2xr7nt7zdezyhp61h00kxatr18pf.wav", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, + { + token: "token20", + weight_name: "Watery Landscape", + media_type: "image", + public_bucket_path: "/images/dummy-image-4.jpg", + likes: 150, + isLiked: true, + created_at: "2023-08-10T09:00:00.000Z", + }, ]; export default mockData; diff --git a/yarn.lock b/yarn.lock index 588607d2bb..2543aea034 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4433,6 +4433,7 @@ __metadata: "@types/gtag.js": ^0.0.12 "@types/howler": ^2.1.2 "@types/imagesloaded": ^4.1.6 + "@types/infinite-scroll": ^4.0.3 "@types/jest": ^24.9.1 "@types/js-cookie": ^3.0.1 "@types/masonry-layout": ^4.2.7 @@ -4455,6 +4456,7 @@ __metadata: i18next-browser-languagedetector: ^7.1.0 i18next-http-backend: ^2.2.1 imagesloaded: ^5.0.0 + infinite-scroll: ^4.0.1 js-cookie: ^3.0.1 masonry-layout: ^4.2.2 posthog-js: ^1.73.1 @@ -5261,6 +5263,25 @@ __metadata: languageName: node linkType: hard +"@types/infinite-scroll@npm:^4.0.3": + version: 4.0.3 + resolution: "@types/infinite-scroll@npm:4.0.3" + dependencies: + "@types/isotope-layout": "*" + "@types/jquery": "*" + "@types/masonry-layout": "*" + "@types/packery": "*" + checksum: c7c9a2db7eb6a26c646a63c36fb1b04b381b9bcbae1b5fbc97d36f05eea36d6b17749b52cb906be578087aa203bfce72541b175fd0529df7c71961a7e7608668 + languageName: node + linkType: hard + +"@types/isotope-layout@npm:*": + version: 3.0.12 + resolution: "@types/isotope-layout@npm:3.0.12" + checksum: 7ae477fad4017a2e7ebbd0b5202e26d6febc58bc0604688d99d2ff822157d48eab77c8a89d942afc21ad1b0d51967491d07c9619d2e5722b626964c2c03e71b9 + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.4 resolution: "@types/istanbul-lib-coverage@npm:2.0.4" @@ -5345,7 +5366,7 @@ __metadata: languageName: node linkType: hard -"@types/masonry-layout@npm:^4.2.7": +"@types/masonry-layout@npm:*, @types/masonry-layout@npm:^4.2.7": version: 4.2.7 resolution: "@types/masonry-layout@npm:4.2.7" dependencies: @@ -5403,6 +5424,15 @@ __metadata: languageName: node linkType: hard +"@types/packery@npm:*": + version: 1.4.37 + resolution: "@types/packery@npm:1.4.37" + dependencies: + "@types/jquery": "*" + checksum: 8350af4392e89988f4d8ec57827b47503be54365f5486c34ef36af3c0f48f1dc18332805eec7d04b06a6c22c2ef7db6cae03bc840058a9972d08fca21b0bc957 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.0 resolution: "@types/parse-json@npm:4.0.0" @@ -10438,7 +10468,7 @@ __metadata: languageName: node linkType: hard -"ev-emitter@npm:^2.1.2": +"ev-emitter@npm:^2.1.0, ev-emitter@npm:^2.1.2": version: 2.1.2 resolution: "ev-emitter@npm:2.1.2" checksum: 1102823ef040684869256100e19a6c6aeeecd422d09a267d7c74e77023136eede2ee86ee475ad1019d30d1f7917557d74542d5665e9f91c398bd5814260af6b3 @@ -10917,6 +10947,13 @@ __metadata: languageName: node linkType: hard +"fizzy-ui-utils@npm:^3.0.0": + version: 3.0.0 + resolution: "fizzy-ui-utils@npm:3.0.0" + checksum: 73b53e5dc89e033bad3eb9cf111d220502afae083c84fbc842d9453202673284de270f7bbe6cc77a806678e62cf8068da1b4280f0d3a1bf1310110248dfa96cd + languageName: node + linkType: hard + "flat-cache@npm:^3.0.4": version: 3.0.4 resolution: "flat-cache@npm:3.0.4" @@ -12275,6 +12312,16 @@ __metadata: languageName: node linkType: hard +"infinite-scroll@npm:^4.0.1": + version: 4.0.1 + resolution: "infinite-scroll@npm:4.0.1" + dependencies: + ev-emitter: ^2.1.0 + fizzy-ui-utils: ^3.0.0 + checksum: e6000c0b82eace9df15ffb007447ecd12b806df60a41c6a06cdc0f931ae419e360be1e713f02e1047e088c75e0060198b25d19de6c3f88bd5fe0f987e326050a + languageName: node + linkType: hard + "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6"