feat: add block number in home

This commit is contained in:
DIYgod 2023-07-27 23:03:33 +01:00
parent e9c80277ad
commit e15ea3f9fa
No known key found for this signature in database
9 changed files with 231 additions and 11 deletions

View File

@ -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 (
<div>
<div className="h-[calc(100vh-6rem)] w-full flex justify-center flex-col relative text-center">
<h2 className="text-6xl sm:text-8xl font-bold mb-5">
<h2 className="text-4xl sm:text-8xl font-bold mb-5">
{features.map((feature) => (
<span
key={feature.title}
className={`text-feature text-feature-${feature.title.toLocaleLowerCase()} block sm:inline-block sm:mr-1 mb-2`}
className={`text-feature text-feature-${feature.title.toLocaleLowerCase()} inline-block sm:mr-1`}
>
{t(feature.title)}
{t(".")}
@ -283,6 +284,7 @@ async function Home() {
</span>
</div>
<div>{t(`features.${feature.title}.extra.description`)}</div>
<BlockNumber />
<a
target="_blank"
href={getSiteLink({ subdomain: "xlog" })}

View File

@ -0,0 +1,119 @@
import { nanoid } from "nanoid"
import { memo, useEffect, useRef, useState } from "react"
import { usePrevious } from "~/hooks/usePrevious"
import { cn } from "~/lib/utils"
const NUMBERS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
const AnimatedNumber = memo(
({
animateToNumber,
includeComma,
height,
className,
}: {
animateToNumber: number
includeComma?: boolean
height?: number
className?: string
}) => {
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<HTMLDivElement | null>(null)
useEffect(() => {
if (!numberHeight) {
const currentHeight =
numberDivRef.current?.getClientRects()?.[0]?.height
if (currentHeight) {
setNumberHeight(currentHeight)
}
}
}, [numberDivRef, numberHeight])
return (
<>
{numberHeight !== 0 && (
<div className={cn("flex", className)}>
{animateToNumber < 0 && <div>-</div>}
{animateToNumbersArr.map((n, index) => {
if (
typeof n === "string" ||
!prevAnimateToNumbersArr ||
prevAnimateToNumbersArr[index] === n
) {
return <div key={index}>{n}</div>
}
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 (
<div
key={index}
style={{
height: numberHeight,
overflow: "hidden",
}}
>
{/* eslint-disable-next-line react/no-unknown-property */}
<style jsx>{`
@keyframes move${id} {
from {
transform: translateY(${from}px);
}
to {
transform: translateY(${to}px);
}
}
`}</style>
<div
key={`${keyCount.current++}`}
style={{
animation: `move${id} 0.3s ease-in-out forwards`,
}}
>
{NUMBERS.map((number, i) => (
<div key={i}>{number}</div>
))}
</div>
</div>
)
})}
</div>
)}
{!numberHeight && (
<div ref={numberDivRef} style={{ position: "absolute", top: -9999 }}>
{0}
</div>
)}
</>
)
},
(prevProps, nextProps) => {
return (
prevProps.animateToNumber === nextProps.animateToNumber &&
prevProps.includeComma === nextProps.includeComma
)
},
)
AnimatedNumber.displayName = "AnimatedNumber"
export default AnimatedNumber

View File

@ -27,7 +27,7 @@ export const BlockchainInfo = ({
: "page"
: "blog"
const [realBlockNumber, setRealBlockNumber] = useState<bigint | null>(null)
const [realBlockNumber, setRealBlockNumber] = useState<number | null>(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),
})})`}
</span>
</BlockchainInfoLink>

View File

@ -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<number | null>(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 (
<div className="flex flex-col items-center">
{t("Current Block Height")}
<AnimatedNumber
animateToNumber={realBlockNumber || blockNumber || 0}
includeComma={true}
height={24}
></AnimatedNumber>
</div>
)
}

View File

@ -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 (
<>
<Hydrate state={dehydratedState}>
<PromotionLinks />
<UniLink
href="/about"
className="text-zinc-800 text-center block space-y-4"
>
<Trans i18n={i18n} i18nKey="description" ns="index">
An{" "}
<span className="underline decoration-2 text-green-400 font-medium">
open-source
</span>{" "}
creative community written on the{" "}
<span className="underline decoration-2 text-yellow-400 font-medium">
blockchain
</span>
.
</Trans>
<BlockNumber />
</UniLink>
{!hideSearch && <SearchInput />}
<div className="text-center text-zinc-700 space-y-3">
<p className="font-bold text-lg">{t("Suggested creators for you")}</p>
@ -63,6 +89,6 @@ export async function HomeSidebar({ hideSearch }: { hideSearch?: boolean }) {
</>
</ShowMoreContainer>
</div>
</>
</Hydrate>
)
}

11
src/hooks/usePrevious.ts Normal file
View File

@ -0,0 +1,11 @@
import { useEffect, useRef } from "react"
export const usePrevious = <T>(value: T): T => {
const ref = useRef<T>()
useEffect(() => {
ref.current = value
})
return ref.current!
}

View File

@ -96,5 +96,6 @@
"min": "分钟",
"Pinned": "置顶",
"Blockchain ID": "区块链标识",
"Confirmed by {{blockNumber}} blocks": "已被 {{blockNumber}} 个区块确认"
"Confirmed by {{blockNumber}} blocks": "已被 {{blockNumber}} 个区块确认",
"Current Block Height": "当前区块高度"
}

View File

@ -515,5 +515,5 @@ export async function getBlockNumber() {
}),
})
).json()
return BigInt(result.result)
return Number(BigInt(result.result))
}

View File

@ -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()
},
})
})
}