From 19d8322dfc103971d964257ca49a5e14cc7a4f33 Mon Sep 17 00:00:00 2001 From: Francisco Pessano Date: Mon, 14 Oct 2024 00:07:31 -0300 Subject: [PATCH] Added second album image --- src/app/_components/album-image.tsx | 71 ++++++++++-- src/app/_components/album-showcase.tsx | 145 +++++++++++++------------ src/app/_components/sad-face-icon.tsx | 38 +++++++ src/app/_components/showcase.tsx | 22 ++-- src/app/utils/contants.ts | 4 +- src/server/api/routers/entry.ts | 4 +- src/server/utils/index.ts | 15 ++- 7 files changed, 204 insertions(+), 95 deletions(-) create mode 100644 src/app/_components/sad-face-icon.tsx diff --git a/src/app/_components/album-image.tsx b/src/app/_components/album-image.tsx index 514a6c7..fb8368c 100644 --- a/src/app/_components/album-image.tsx +++ b/src/app/_components/album-image.tsx @@ -1,7 +1,11 @@ -import React from "react"; +import { api } from "@/trpc/react"; +import React, { useEffect, useState } from "react"; import Tilt from "react-parallax-tilt"; +import SadFaceIcon from "./sad-face-icon"; interface AlbumImageProps { + number?: number; + entry: { data: any; isLoading: boolean }; showSpookyImage: boolean; imageSource: string; spookyImageSource: string | null; @@ -9,13 +13,27 @@ interface AlbumImageProps { generateSpookyImageData: string | null; lastSpookyImageLoaded: number; place: number; - spookyImageLoaded: boolean; - onImageLoad: () => void; loadGeneratedImage: boolean; onQueue: boolean; + saveImage: { + mutate: (arg0: { + entry: { + type: "album" | "artist"; + image: string; + name: string; + number?: number; + }; + }) => void; + }; + setLastSpookyImageLoaded: ( + arg0: number | ((state: number) => number), + ) => void; + error: boolean; } export function AlbumImage({ + number, + entry, showSpookyImage, imageSource, spookyImageSource, @@ -23,11 +41,42 @@ export function AlbumImage({ generateSpookyImageData, lastSpookyImageLoaded, place, - spookyImageLoaded, - onImageLoad, loadGeneratedImage, onQueue, + saveImage, + setLastSpookyImageLoaded, + error, }: AlbumImageProps) { + const [spookyImageLoaded, setSpookyImageLoaded] = useState(false); + + const handleSaveImage = async () => { + if (!entry.data && !entry.isLoading) { + saveImage.mutate({ + entry: { + type: "album", + image: imageSource, + name: album.name, + number, + }, + }); + } + }; + + useEffect(() => { + if (spookyImageLoaded) { + handleSaveImage(); + } + }, [spookyImageLoaded]); + + const onImageLoad = () => { + if (!spookyImageLoaded) { + setSpookyImageLoaded(true); + setLastSpookyImageLoaded((state: number) => + state > place ? state : place, + ); + } + }; + return ( {album.name} - {loadGeneratedImage && spookyImageSource && ( + {loadGeneratedImage && spookyImageSource && !error && ( )} - {showSpookyImage && !spookyImageLoaded && ( + {showSpookyImage && !spookyImageLoaded && !error && (
{(() => { @@ -91,6 +140,14 @@ export function AlbumImage({
)} + {error && ( +
+
+ +

Error

+
+
+ )}
); } diff --git a/src/app/_components/album-showcase.tsx b/src/app/_components/album-showcase.tsx index dc37e87..1638b58 100644 --- a/src/app/_components/album-showcase.tsx +++ b/src/app/_components/album-showcase.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { TrackByAlbum } from "./spotify-data"; import { api } from "@/trpc/react"; import { quantum } from "ldrs"; @@ -19,12 +19,12 @@ export default function AlbumShowcase({ album, position, tracks, - place, + places, lastSpookyImageLoaded, setLastSpookyImageLoaded, }: TrackByAlbum & { spookify: boolean; - place: number; + places: number[]; lastSpookyImageLoaded: number; setLastSpookyImageLoaded: any; }) { @@ -33,26 +33,34 @@ export default function AlbumShowcase({ : "https://via.placeholder.com/150"; const [showSpookyImage, setShowSpookyImage] = useState(spookify); - const [spookyImageLoaded, setSpookyImageLoaded] = useState(false); useEffect(() => { setShowSpookyImage(spookify); }, [spookify]); - const entry = api.entry.get.useQuery({ - type: "album", - name: album.name, - image: imageSource, - }); + const entry = api.entry.get.useQuery( + { + type: "album", + name: album.name, + image: imageSource, + }, + { + refetchInterval: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, + }, + ); const generateSpookyImage = api.entry.generate.useMutation(); const generateSecondSpookyImage = api.entry.generate.useMutation(); - const spookyImageMatch = ( - (entry.data?.value || generateSpookyImage.data) as null | string - )?.match(/https:\/\/res.cloudinary.com\/[^"]+/); + const spookyImageSource = useMemo(() => { + const spookyImageMatch = ( + (entry.data?.value || generateSpookyImage.data) as null | string + )?.match(/]*>/); - const spookyImageSource = spookyImageMatch ? spookyImageMatch[0] : ""; + return spookyImageMatch && spookyImageMatch[1] ? spookyImageMatch[1] : ""; + }, [entry.data, generateSpookyImage.data]); const secondEntry = api.entry.get.useQuery( { @@ -62,13 +70,12 @@ export default function AlbumShowcase({ number: 2, }, { - enabled: !!spookyImageSource, + refetchInterval: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, }, ); - const saveImage = api.entry.save.useMutation(); - const saveSecondImage = api.entry.save.useMutation(); - const handleGenerateSpookyImage = async () => { if (!entry.data && !entry.isLoading) { generateSpookyImage.mutate({ @@ -82,61 +89,44 @@ export default function AlbumShowcase({ }; const handleSecondGenerateSpookyImage = async () => { - if (!secondEntry.data && !secondEntry.isLoading) { + if (!secondEntry.data && !secondEntry.isLoading && spookyImageSource) { generateSecondSpookyImage.mutate({ entry: { type: "album", name: album.name, - image: spookyImageSource as string, + image: spookyImageSource, + number: 2, }, }); } }; - const handleSaveImage = async () => { - if (!entry.data && !entry.isLoading) { - saveImage.mutate({ - entry: { - type: "album", - image: imageSource, - name: album.name, - }, - }); - } - }; - - const handleSecondSaveImage = async () => { - if (!secondEntry.data && !secondEntry.isLoading) { - saveSecondImage.mutate({ - entry: { - type: "album", - image: spookyImageSource as string, - name: album.name, - }, - }); - } - }; + const saveImage = api.entry.save.useMutation(); + const saveSecondImage = api.entry.save.useMutation(); useEffect(() => { handleGenerateSpookyImage(); }, [entry.data]); useEffect(() => { - if (spookyImageLoaded) { - handleSaveImage(); - } - }, [spookyImageLoaded]); + handleSecondGenerateSpookyImage(); + }, [secondEntry.data, entry.data]); - //TODO ERROR HANDLING + const secondSpookyImageMatch = ( + (secondEntry.data?.value || generateSecondSpookyImage?.data || "") as string + ).match(/]*>/); + const secondSpookyImageSource = + secondSpookyImageMatch && secondSpookyImageMatch[1] + ? secondSpookyImageMatch[1] + : ""; - const onImageLoad = () => { - if (!spookyImageLoaded) { - setSpookyImageLoaded(true); - setLastSpookyImageLoaded((state: number) => - state > place ? state : place, - ); - } - }; + const firstPlace = places[0] || 0; + const secondPlace = places[1] || 0; + + const firstImageError = !!(entry.error || generateSpookyImage.error); + const secondImageError = !!( + secondEntry.error || generateSecondSpookyImage.error + ); return (
- + = place || - lastSpookyImageLoaded + 1 === place + ? lastSpookyImageLoaded >= firstPlace || + lastSpookyImageLoaded + 1 === firstPlace : true) ) } - onQueue={lastSpookyImageLoaded < place - 1} + onQueue={lastSpookyImageLoaded < firstPlace - 1} + saveImage={saveImage} + setLastSpookyImageLoaded={setLastSpookyImageLoaded} + error={firstImageError} /> - {/* + = secondPlace || + lastSpookyImageLoaded + 1 === secondPlace + : true) + ) + } + onQueue={lastSpookyImageLoaded < secondPlace - 1} + saveImage={saveSecondImage} + setLastSpookyImageLoaded={setLastSpookyImageLoaded} + error={secondImageError} /> - */} +

{album.name}

-
    +
      {tracks.map((track) => (
    • {track.name}
    • ))} diff --git a/src/app/_components/sad-face-icon.tsx b/src/app/_components/sad-face-icon.tsx new file mode 100644 index 0000000..9a64a0f --- /dev/null +++ b/src/app/_components/sad-face-icon.tsx @@ -0,0 +1,38 @@ +interface SadFaceIconProps { + color: string; + className?: string; +} + +export function SadFaceIcon({ color, className }: SadFaceIconProps) { + return ( + + + + + + ); +} + +export default SadFaceIcon; diff --git a/src/app/_components/showcase.tsx b/src/app/_components/showcase.tsx index 8af26a1..b42f8f4 100644 --- a/src/app/_components/showcase.tsx +++ b/src/app/_components/showcase.tsx @@ -27,16 +27,18 @@ export function Showcase({

      Tracks by album

      {Object.values(tracksByAlbum) .sort((a, b) => b.position - a.position) - .map((album, index) => ( - - ))} + .map((album, index) => { + return ( + + ); + })}

      Artists images

      { - const options = { - effect: - "gen_background_replace:prompt_a bizarre and super creepy background acording with main object theme-max creativity", - }; +export const makeImageSpooky = (publicId: string, number?: number) => { + const options: Record = {}; + + if (number === 2) { + options.effect = + "gen_recolor:prompt_main_object_or_motive_on_image;to-color_green"; + } else { + options.effect = + "gen_background_replace:prompt_a bizarre and super creepy background acording with main object theme-max creativity"; + } try { const result = cloudinary.v2.image(publicId, { ...options });