From d51b713d2c2ac6f9d7558abc63f4685e9a9fece1 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 29 Apr 2023 03:58:37 +0800 Subject: [PATCH] refactor: extract reaction AvatarStack (#454) --- src/components/common/CharacterListItem.tsx | 2 +- src/components/common/ReactionLike.tsx | 47 ++++++++------------ src/components/common/ReactionMint.tsx | 49 +++++++++------------ src/components/common/ReactionTip.tsx | 48 +++++++------------- src/components/ui/AvatarStack.tsx | 48 ++++++++++++++++++++ src/hooks/useDarkMode.ts | 3 +- src/lib/constants.ts | 5 +++ src/lib/env.ts | 5 --- src/lib/helpers.ts | 4 +- src/lib/noop.ts | 3 ++ src/pages/api/redirection.tsx | 2 +- 11 files changed, 118 insertions(+), 98 deletions(-) create mode 100644 src/components/ui/AvatarStack.tsx create mode 100644 src/lib/noop.ts diff --git a/src/components/common/CharacterListItem.tsx b/src/components/common/CharacterListItem.tsx index e4940610..72b773ad 100644 --- a/src/components/common/CharacterListItem.tsx +++ b/src/components/common/CharacterListItem.tsx @@ -4,12 +4,12 @@ import { CharacterFloatCard } from "~/components/common/CharacterFloatCard" import { BlockchainIcon } from "~/components/icons/BlockchainIcon" import { CSB_SCAN } from "~/lib/env" import { getSiteLink } from "~/lib/helpers" +import { noopArr } from "~/lib/noop" import { Avatar } from "../ui/Avatar" import { UniLink } from "../ui/UniLink" import { FollowingButton } from "./FollowingButton" -const noopArr = [] as any[] const CharacterListItem: React.FC<{ character: any sub: any diff --git a/src/components/common/ReactionLike.tsx b/src/components/common/ReactionLike.tsx index cd9853df..b9b4e5c0 100644 --- a/src/components/common/ReactionLike.tsx +++ b/src/components/common/ReactionLike.tsx @@ -1,6 +1,6 @@ import confetti from "canvas-confetti" import { Trans, useTranslation } from "next-i18next" -import { useEffect, useRef, useState } from "react" +import { useEffect, useMemo, useRef, useState } from "react" import { CharacterList } from "~/components/common/CharacterList" import { Modal } from "~/components/ui/Modal" @@ -16,7 +16,7 @@ import { useToggleLikePage, } from "~/queries/page" -import { Avatar } from "../ui/Avatar" +import { AvatarStack } from "../ui/AvatarStack" import { Button } from "../ui/Button" export const ReactionLike: React.FC<{ @@ -77,6 +77,19 @@ export const ReactionLike: React.FC<{ } }, [toggleLikePage.isSuccess]) + const avatars = useMemo( + () => + likes + ?.sort((a, b) => + b.character?.metadata?.content?.avatars?.[0] ? 1 : -1, + ) + .slice(0, 3) + .map(($) => ({ + images: $.character?.metadata?.content?.avatars, + name: $.character?.metadata?.content?.name, + })), + [likes], + ) return ( <>
@@ -108,33 +121,11 @@ export const ReactionLike: React.FC<{ {likeCount} {size !== "sm" && ( - + /> )}
+ mints.data?.pages?.[0]?.list + ?.sort((a, b: any) => + b.character?.metadata?.content?.avatars?.[0] ? 1 : -1, + ) + .slice(0, 3) + .map((mint: any) => ({ + images: mint.character?.metadata?.content?.avatars, + name: mint.character?.metadata?.content?.name, + })) || noopArr, + [mints], + ) + return ( <>
@@ -101,33 +116,11 @@ export const ReactionMint: React.FC<{ {mints.data?.pages?.[0]?.count || 0} {size !== "sm" && ( -
    setIsMintListOpen(true)} - > - {mints.data?.pages?.[0]?.list - ?.sort((a, b: any) => - b.character?.metadata?.content?.avatars?.[0] ? 1 : -1, - ) - .slice(0, 3) - .map((mint: any, index) => ( -
  • - -
  • - ))} - {(mints.data?.pages?.[0]?.count || 0) > 3 && ( -
  • -
    - +{mints.data!.pages?.[0]?.count - 3} -
    -
  • - )} -
+ count={mints.data?.pages?.[0]?.count || 0} + /> )}
+ tips.data?.pages?.[0]?.list?.sort((a, b: any) => + b.character?.metadata?.content?.avatars?.[0] ? 1 : -1, + ) || noopArr, + [tips.data?.pages], + ) + return ( <>
@@ -63,35 +72,12 @@ export const ReactionTip: React.FC<{ })()} {tips.data?.pages?.[0]?.count || 0} - { -
    - {tips.data?.pages?.[0]?.list - ?.sort((a, b: any) => - b.character?.metadata?.content?.avatars?.[0] ? 1 : -1, - ) - .slice(0, 3) - .map((tip: any, index) => ( -
  • - -
  • - ))} - {(tips.data?.pages?.[0]?.count || 0) > 3 && ( -
  • -
    - +{tips.data!.pages?.[0]?.count - 3} -
    -
  • - )} -
- } + +
void + avatars: { + name: string | null | undefined + images: string[] | null | undefined + }[] + count: number + + /** + * @default 3 + */ + showCount?: number +} +export const AvatarStack: FC = (props) => { + const { avatars, count, onClick, showCount = 3 } = props + return ( +
    + {avatars.slice(0, showCount).map((avatar) => { + return ( +
  • + +
  • + ) + })} + {count > showCount && ( +
  • +
    + +{count - showCount} +
    +
  • + )} +
+ ) +} diff --git a/src/hooks/useDarkMode.ts b/src/hooks/useDarkMode.ts index 789f663e..d9919808 100644 --- a/src/hooks/useDarkMode.ts +++ b/src/hooks/useDarkMode.ts @@ -1,6 +1,7 @@ import { useEffect, useRef, useState } from "react" import { create } from "zustand" +import { noop } from "~/lib/noop" import { delStorage, getStorage, setStorage } from "~/lib/storage" import { isServerSide } from "~/lib/utils" @@ -150,8 +151,6 @@ const useDarkModeInternal = ( } } -const noop = () => {} - const mockElement = { classList: { add: noop, diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 201a02c0..57858ceb 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -3,3 +3,8 @@ export const IS_BROWSER = typeof document !== "undefined" export const IS_PROD = IS_BROWSER ? !location.hostname.endsWith("localhost") : process.env.NODE_ENV === "production" +export const IS_DEV = process.env.NODE_ENV === "development" + +export const IS_VERCEL_PREVIEW = + process.env.NEXT_PUBLIC_VERCEL_ENV === "preview" || + process.env.VERCEL_ENV === "preview" diff --git a/src/lib/env.ts b/src/lib/env.ts index 1ea21746..c976f180 100644 --- a/src/lib/env.ts +++ b/src/lib/env.ts @@ -20,8 +20,3 @@ export const IPFS_GATEWAY = process.env.NEXT_PUBLIC_IPFS_GATEWAY || "https://ipfs.4everland.xyz/ipfs/" export const MIRA_LINK = process.env.NEXT_PUBLIC_MIRA_LINK || "https://mira.crossbell.io" -export const IS_VERCEL_PREVIEW = - process.env.NEXT_PUBLIC_VERCEL_ENV === "preview" || - process.env.VERCEL_ENV === "preview" - -export const IS_DEV = process.env.NODE_ENV === "development" diff --git a/src/lib/helpers.ts b/src/lib/helpers.ts index fcdb7918..1a3d205e 100644 --- a/src/lib/helpers.ts +++ b/src/lib/helpers.ts @@ -2,8 +2,8 @@ import { NoteEntity } from "crossbell.js" import { Note, Profile } from "~/lib/types" -import { IS_PROD } from "./constants" -import { IS_VERCEL_PREVIEW, OUR_DOMAIN } from "./env" +import { IS_PROD, IS_VERCEL_PREVIEW } from "./constants" +import { OUR_DOMAIN } from "./env" import { isServerSide } from "./utils" export const getSiteLink = ({ diff --git a/src/lib/noop.ts b/src/lib/noop.ts new file mode 100644 index 00000000..be1f98f3 --- /dev/null +++ b/src/lib/noop.ts @@ -0,0 +1,3 @@ +export const noop = () => void 0 + +export const noopArr = [] as any[] diff --git a/src/pages/api/redirection.tsx b/src/pages/api/redirection.tsx index cf29b5b2..2f4676f7 100644 --- a/src/pages/api/redirection.tsx +++ b/src/pages/api/redirection.tsx @@ -1,8 +1,8 @@ import { NoteEntity } from "crossbell.js" import { NextApiRequest, NextApiResponse } from "next" +import { IS_VERCEL_PREVIEW } from "~/lib/constants" import { getDefaultSlug } from "~/lib/default-slug" -import { IS_VERCEL_PREVIEW } from "~/lib/env" import { getSiteLink } from "~/lib/helpers" import { checkDomainServer } from "~/models/site.model"