From 2aa4fe118e850fe57ac5cd201f5e7efe4c25a22f Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 10 Oct 2024 14:06:09 +0800 Subject: [PATCH] chore: split achievement code Signed-off-by: Innei --- apps/renderer/src/components/user-button.tsx | 28 +- .../achievement/AchievementModalContent.tsx | 283 ++++++++++++++++++ .../src/modules/achievement/hooks.tsx | 283 +----------------- 3 files changed, 300 insertions(+), 294 deletions(-) create mode 100644 apps/renderer/src/modules/achievement/AchievementModalContent.tsx diff --git a/apps/renderer/src/components/user-button.tsx b/apps/renderer/src/components/user-button.tsx index a35ea4a3e..6fccb16ca 100644 --- a/apps/renderer/src/components/user-button.tsx +++ b/apps/renderer/src/components/user-button.tsx @@ -87,19 +87,21 @@ export const ProfileButton: FC = memo((props) => { - - - + {x !== 0 && y !== 0 && ( + + + + )} = { + [AchievementsActionIdMap.FIRST_CLAIM_FEED]: { + title: "achievement.first_claim_feed", + description: "achievement.first_claim_feed_description", + }, +} + +export const AchievementModalContent: FC = () => { + const jotaiStore = useStore() + const queryClient = useQueryClient() + + const defaultAchievements = useSingleton(buildDefaultAchievements) + + const _achievementType = apiClient.achievement.$get({ + query: { + type: "all", + }, + }) + type Achievement = Awaited["data"] + const { + data: achievements, + isLoading, + refetch, + } = useQuery({ + queryKey: ["achievements"], + meta: { + persist: true, + }, + queryFn: async () => { + const res = await apiClient.achievement.$get({ + query: { + type: "all", + }, + }) + + jotaiStore.set(achievementsDataAtom.current, res.data) + return res.data + }, + initialData: defaultAchievements.current as Achievement, + }) + + useEffect(() => { + if (!achievements) return + let shouldPolling = false + const pollingChain = new Chain() + for (const achievement of achievements) { + if (achievement.type === "checking") { + shouldPolling = true + break + } + } + + if (shouldPolling) { + pollingChain.wait(2000).next(() => { + refetch() + }) + } + + return () => { + pollingChain.abort() + } + }, [achievements, refetch]) + + const { mutateAsync: mintAchievement, isPending: isMinting } = useMutation({ + mutationFn: async (actionId: number) => { + return apiClient.achievement.$put({ + json: { + actionId, + }, + }) + }, + }) + const achievementsDataAtom = useSingleton(() => atom()) + const { mutateAsync: checkAchievement, isPending: checkPending } = useMutation({ + mutationFn: async (actionId: number) => { + return apiClient.achievement.check.$post({ + json: { + actionId, + }, + }) + }, + onSuccess: () => { + refetch() + }, + }) + const t = useI18n() + + return ( +
+ + +
{t("words.achievement")}
+ + + + {t("words.power")} + + + ), + }} + /> + + +
    + {isLoading ? ( +
    + } size="large" /> +
    + ) : ( + achievements?.map((achievement) => { + const copy = achievementActionIdCopyMap[achievement.actionId] + if (!copy) return null + + return ( +
  • +
    +
    + {t(copy.title)} + + {achievement.power && ( + + {achievement.power} + + + )} +
    +
    + {t(copy.description)} +
    +
    + + {achievement.type === "checking" && ( +
    + + {t("words.mint")} +
    + )} + + {achievement.type === "incomplete" && ( + + )} + + {achievement.type === "received" && ( +
    + + {t("achievement.all_done")} +
    + )} + {achievement.type === "completed" && ( + + )} +
  • + ) + }) + )} +
+
+ ) +} + +const buildDefaultAchievements = () => { + return [ + { + id: nanoid(), + actionId: AchievementsActionIdMap.FIRST_CLAIM_FEED, + type: "checking", + progress: 0, + progressMax: 0, + }, + ] +} diff --git a/apps/renderer/src/modules/achievement/hooks.tsx b/apps/renderer/src/modules/achievement/hooks.tsx index f64af8224..709e1f098 100644 --- a/apps/renderer/src/modules/achievement/hooks.tsx +++ b/apps/renderer/src/modules/achievement/hooks.tsx @@ -1,38 +1,9 @@ -import { DotLottieReact } from "@lottiefiles/dotlottie-react" -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" -import { useSingleton } from "foxact/use-singleton" -import { atom, useStore } from "jotai" -import { nanoid } from "nanoid" -import type { FC } from "react" -import { useCallback, useEffect } from "react" -import { Trans } from "react-i18next" +import { useCallback } from "react" -import { Button } from "~/components/ui/button" -import { styledButtonVariant } from "~/components/ui/button/variants" -import { LoadingCircle, LoadingWithIcon } from "~/components/ui/loading" import { useModalStack } from "~/components/ui/modal" import { SlideUpModal } from "~/components/ui/modal/stacked/custom-modal" -import { useI18n } from "~/hooks/common" -import { apiClient } from "~/lib/api-fetch" -import { Chain } from "~/lib/chain" -import { cn } from "~/lib/utils" -import achievementAnimationUri from "~/lottie/achievement.lottie?url" -const absoluteachievementAnimationUri = new URL(achievementAnimationUri, import.meta.url).href - -enum AchievementsActionIdMap { - FIRST_CLAIM_FEED = 0, -} - -const achievementActionIdCopyMap: Record< - AchievementsActionIdMap, - { title: I18nKeys; description: I18nKeys } -> = { - [AchievementsActionIdMap.FIRST_CLAIM_FEED]: { - title: "achievement.first_claim_feed", - description: "achievement.first_claim_feed_description", - }, -} +import { AchievementModalContent } from "./AchievementModalContent" export const useAchievementModal = () => { const { present } = useModalStack() @@ -47,253 +18,3 @@ export const useAchievementModal = () => { }) }, [present]) } - -const buildDefaultAchievements = () => { - return [ - { - id: nanoid(), - actionId: AchievementsActionIdMap.FIRST_CLAIM_FEED, - type: "checking", - progress: 0, - progressMax: 0, - }, - ] -} -export const AchievementModalContent: FC = () => { - const jotaiStore = useStore() - const queryClient = useQueryClient() - - const defaultAchievements = useSingleton(buildDefaultAchievements) - - const _achievementType = apiClient.achievement.$get({ - query: { - type: "all", - }, - }) - type Achievement = Awaited["data"] - const { - data: achievements, - isLoading, - refetch, - } = useQuery({ - queryKey: ["achievements"], - meta: { - persist: true, - }, - queryFn: async () => { - const res = await apiClient.achievement.$get({ - query: { - type: "all", - }, - }) - - jotaiStore.set(achievementsDataAtom.current, res.data) - return res.data - }, - initialData: defaultAchievements.current as Achievement, - }) - - useEffect(() => { - if (!achievements) return - let shouldPolling = false - const pollingChain = new Chain() - for (const achievement of achievements) { - if (achievement.type === "checking") { - shouldPolling = true - break - } - } - - if (shouldPolling) { - pollingChain.wait(2000).next(() => { - refetch() - }) - } - - return () => { - pollingChain.abort() - } - }, [achievements, refetch]) - - const { mutateAsync: mintAchievement, isPending: isMinting } = useMutation({ - mutationFn: async (actionId: number) => { - return apiClient.achievement.$put({ - json: { - actionId, - }, - }) - }, - }) - const achievementsDataAtom = useSingleton(() => atom()) - const { mutateAsync: checkAchievement, isPending: checkPending } = useMutation({ - mutationFn: async (actionId: number) => { - return apiClient.achievement.check.$post({ - json: { - actionId, - }, - }) - }, - onSuccess: () => { - refetch() - }, - }) - const t = useI18n() - - return ( -
- - -
{t("words.achievement")}
- - - - {t("words.power")} - - - ), - }} - /> - - -
    - {isLoading ? ( -
    - } size="large" /> -
    - ) : ( - achievements?.map((achievement) => { - const copy = achievementActionIdCopyMap[achievement.actionId] - if (!copy) return null - - return ( -
  • -
    -
    - {t(copy.title)} - - {achievement.power && ( - - {achievement.power} - - - )} -
    -
    - {t(copy.description)} -
    -
    - - {achievement.type === "checking" && ( -
    - - {t("words.mint")} -
    - )} - - {achievement.type === "incomplete" && ( - - )} - - {achievement.type === "received" && ( -
    - - {t("achievement.all_done")} -
    - )} - {achievement.type === "completed" && ( - - )} -
  • - ) - }) - )} -
-
- ) -}