diff --git a/src/app/(home)/about/page.tsx b/src/app/(home)/about/page.tsx index cec0b144..673084ef 100644 --- a/src/app/(home)/about/page.tsx +++ b/src/app/(home)/about/page.tsx @@ -2,6 +2,7 @@ import Link from "next/link" import { memo } from "react" import { Logo } from "~/components/common/Logo" +import { BlockNumber } from "~/components/home/BlockNumber" import { default as OriginEntranceButton } from "~/components/home/EntranceButton" import { Integration } from "~/components/home/Integrations" import { ShowCase } from "~/components/home/Showcase" @@ -110,11 +111,11 @@ async function Home() { return (
-

+

{features.map((feature) => ( {t(feature.title)} {t(".")} @@ -283,6 +284,7 @@ async function Home() {

{t(`features.${feature.title}.extra.description`)}
+ { + const keyCount = useRef(0) + const animteTonumberString = includeComma + ? Math.abs(animateToNumber).toLocaleString() + : String(Math.abs(animateToNumber)) + const animateToNumbersArr = Array.from(animteTonumberString, Number).map( + (x, idx) => (isNaN(x) ? animteTonumberString[idx] : x), + ) + const prevAnimateToNumbersArr = usePrevious(animateToNumbersArr) + + const [numberHeight, setNumberHeight] = useState(height || 0) + + const numberDivRef = useRef(null) + + useEffect(() => { + if (!numberHeight) { + const currentHeight = + numberDivRef.current?.getClientRects()?.[0]?.height + if (currentHeight) { + setNumberHeight(currentHeight) + } + } + }, [numberDivRef, numberHeight]) + + return ( + <> + {numberHeight !== 0 && ( +
+ {animateToNumber < 0 &&
-
} + {animateToNumbersArr.map((n, index) => { + if ( + typeof n === "string" || + !prevAnimateToNumbersArr || + prevAnimateToNumbersArr[index] === n + ) { + return
{n}
+ } + + const from = + -1 * (numberHeight * (prevAnimateToNumbersArr[index] as number)) + let to = + -1 * (numberHeight * (animateToNumbersArr[index] as number)) + const id = nanoid() + if (animateToNumbersArr[index] === 0) { + to = -1 * (numberHeight * 10) + } + + return ( +
+ {/* eslint-disable-next-line react/no-unknown-property */} + +
+ {NUMBERS.map((number, i) => ( +
{number}
+ ))} +
+
+ ) + })} +
+ )} + {!numberHeight && ( +
+ {0} +
+ )} + + ) + }, + (prevProps, nextProps) => { + return ( + prevProps.animateToNumber === nextProps.animateToNumber && + prevProps.includeComma === nextProps.includeComma + ) + }, +) + +AnimatedNumber.displayName = "AnimatedNumber" + +export default AnimatedNumber diff --git a/src/components/common/BlockchainInfo.tsx b/src/components/common/BlockchainInfo.tsx index 4902a97e..b20e7130 100644 --- a/src/components/common/BlockchainInfo.tsx +++ b/src/components/common/BlockchainInfo.tsx @@ -27,7 +27,7 @@ export const BlockchainInfo = ({ : "page" : "blog" - const [realBlockNumber, setRealBlockNumber] = useState(null) + const [realBlockNumber, setRealBlockNumber] = useState(null) const { data: blockNumber } = useGetBlockNumber() useEffect(() => { @@ -38,7 +38,12 @@ export const BlockchainInfo = ({ useEffect(() => { const interval = setInterval(() => { - setRealBlockNumber((prevCount) => (prevCount || BigInt(0)) + BigInt(1)) + setRealBlockNumber((prevCount) => { + if (prevCount) { + return prevCount + 1 + } + return null + }) }, 1000) return () => clearInterval(interval) @@ -81,7 +86,7 @@ export const BlockchainInfo = ({ `(${t("Confirmed by {{blockNumber}} blocks", { blockNumber: realBlockNumber - - BigInt(page?.blockNumber || site?.blockNumber || 0), + (page?.blockNumber || site?.blockNumber || 0), })})`} diff --git a/src/components/home/BlockNumber.tsx b/src/components/home/BlockNumber.tsx new file mode 100644 index 00000000..1bbbe128 --- /dev/null +++ b/src/components/home/BlockNumber.tsx @@ -0,0 +1,44 @@ +"use client" + +import { useEffect, useState } from "react" + +import AnimatedNumber from "~/components/common/AnimatedNumber" +import { useTranslation } from "~/lib/i18n/client" +import { useGetBlockNumber } from "~/queries/site" + +export const BlockNumber = () => { + const { t } = useTranslation("common") + + const [realBlockNumber, setRealBlockNumber] = useState(null) + const { data: blockNumber } = useGetBlockNumber() + + useEffect(() => { + if (blockNumber) { + setRealBlockNumber(blockNumber) + } + }, [blockNumber]) + + useEffect(() => { + const interval = setInterval(() => { + setRealBlockNumber((prevCount) => { + if (prevCount) { + return prevCount + 1 + } + return null + }) + }, 1000) + + return () => clearInterval(interval) + }, []) + + return ( +
+ {t("Current Block Height")} + +
+ ) +} diff --git a/src/components/home/HomeSidebar.tsx b/src/components/home/HomeSidebar.tsx index 797d4c0e..9c14fdeb 100644 --- a/src/components/home/HomeSidebar.tsx +++ b/src/components/home/HomeSidebar.tsx @@ -1,22 +1,48 @@ +import { Hydrate, dehydrate } from "@tanstack/react-query" + import { CharacterFloatCard } from "~/components/common/CharacterFloatCard" import { SearchInput } from "~/components/common/SearchInput" import { Avatar } from "~/components/ui/Avatar" import { UniLink } from "~/components/ui/UniLink" import { getSiteLink } from "~/lib/helpers" -import { getTranslation } from "~/lib/i18n" +import { Trans, getTranslation } from "~/lib/i18n" +import getQueryClient from "~/lib/query-client" import { getShowcase } from "~/queries/home.server" +import { getBlockNumber } from "~/queries/site.server" import { FollowAllButton } from "../common/FollowAllButton" +import { BlockNumber } from "./BlockNumber" import PromotionLinks from "./PromotionLinks" import ShowMoreContainer from "./ShowMoreContainer" export async function HomeSidebar({ hideSearch }: { hideSearch?: boolean }) { const showcaseSites = await getShowcase() - const { t } = await getTranslation("index") + const { t, i18n } = await getTranslation("index") + const queryClient = getQueryClient() + await getBlockNumber(queryClient) + + const dehydratedState = dehydrate(queryClient) return ( - <> + + + + An{" "} + + open-source + {" "} + creative community written on the{" "} + + blockchain + + . + + + {!hideSearch && }

{t("Suggested creators for you")}

@@ -63,6 +89,6 @@ export async function HomeSidebar({ hideSearch }: { hideSearch?: boolean }) {
- +
) } diff --git a/src/hooks/usePrevious.ts b/src/hooks/usePrevious.ts new file mode 100644 index 00000000..d698858d --- /dev/null +++ b/src/hooks/usePrevious.ts @@ -0,0 +1,11 @@ +import { useEffect, useRef } from "react" + +export const usePrevious = (value: T): T => { + const ref = useRef() + + useEffect(() => { + ref.current = value + }) + + return ref.current! +} diff --git a/src/lib/i18n/locales/zh/common.json b/src/lib/i18n/locales/zh/common.json index ec130f88..4a6c8e2c 100644 --- a/src/lib/i18n/locales/zh/common.json +++ b/src/lib/i18n/locales/zh/common.json @@ -96,5 +96,6 @@ "min": "分钟", "Pinned": "置顶", "Blockchain ID": "区块链标识", - "Confirmed by {{blockNumber}} blocks": "已被 {{blockNumber}} 个区块确认" + "Confirmed by {{blockNumber}} blocks": "已被 {{blockNumber}} 个区块确认", + "Current Block Height": "当前区块高度" } diff --git a/src/models/site.model.ts b/src/models/site.model.ts index b495fd1b..5b59d322 100644 --- a/src/models/site.model.ts +++ b/src/models/site.model.ts @@ -515,5 +515,5 @@ export async function getBlockNumber() { }), }) ).json() - return BigInt(result.result) + return Number(BigInt(result.result)) } diff --git a/src/queries/site.server.ts b/src/queries/site.server.ts index 970368c4..a260babe 100644 --- a/src/queries/site.server.ts +++ b/src/queries/site.server.ts @@ -219,3 +219,15 @@ export const getCharacterColors = async (character?: ExpandedCharacter) => { } }> } + +export const getBlockNumber = async (queryClient: QueryClient) => { + const key = ["getBlockNumber"] + await queryClient.prefetchQuery(key, async () => { + return cacheGet({ + key: key, + getValueFun: async () => { + return siteModel.getBlockNumber() + }, + }) + }) +}