From 3a35a971f1435b6667b1a555b48a2556cf2c2782 Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 24 Oct 2024 16:06:21 +0800 Subject: [PATCH] fix(wallet): balance align Signed-off-by: Innei --- .../src/modules/boost/boost-certification.tsx | 8 +- .../modules/power/my-wallet-section/index.tsx | 6 +- apps/renderer/src/modules/wallet/balance.tsx | 8 +- .../(with-layout)/feed/[id]/index.tsx | 11 - .../pages/(external)/(with-layout)/layout.tsx | 105 ---------- .../(with-layout)/list/[id]/index.tsx | 11 - .../(with-layout)/profile/[id]/index.tsx | 11 - .../(with-layout)/share/feeds/[id]/index.tsx | 139 ------------- .../(with-layout)/share/lists/[id]/index.tsx | 122 ----------- .../(with-layout)/share/users/[id]/index.tsx | 143 ------------- .../src/pages/(external)/invitation.tsx | 196 ------------------ configs/tailwind-extend.css | 16 ++ .../components/src/ui/button/variants.tsx | 2 +- 13 files changed, 27 insertions(+), 751 deletions(-) delete mode 100644 apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx delete mode 100644 apps/renderer/src/pages/(external)/(with-layout)/layout.tsx delete mode 100644 apps/renderer/src/pages/(external)/(with-layout)/list/[id]/index.tsx delete mode 100644 apps/renderer/src/pages/(external)/(with-layout)/profile/[id]/index.tsx delete mode 100644 apps/renderer/src/pages/(external)/(with-layout)/share/feeds/[id]/index.tsx delete mode 100644 apps/renderer/src/pages/(external)/(with-layout)/share/lists/[id]/index.tsx delete mode 100644 apps/renderer/src/pages/(external)/(with-layout)/share/users/[id]/index.tsx delete mode 100644 apps/renderer/src/pages/(external)/invitation.tsx diff --git a/apps/renderer/src/modules/boost/boost-certification.tsx b/apps/renderer/src/modules/boost/boost-certification.tsx index 81db21cd9..3244a1834 100644 --- a/apps/renderer/src/modules/boost/boost-certification.tsx +++ b/apps/renderer/src/modules/boost/boost-certification.tsx @@ -27,7 +27,7 @@ export const BoostCertification = ({ { @@ -38,9 +38,9 @@ export const BoostCertification = ({ - -
- + +
+ {t("boost.feed_being_boosted")}
diff --git a/apps/renderer/src/modules/power/my-wallet-section/index.tsx b/apps/renderer/src/modules/power/my-wallet-section/index.tsx index 17576d42c..d7b43a681 100644 --- a/apps/renderer/src/modules/power/my-wallet-section/index.tsx +++ b/apps/renderer/src/modules/power/my-wallet-section/index.tsx @@ -149,11 +149,7 @@ export const MyWalletSection = ({ className }: { className?: string }) => { values={{ blockchainName: "VSL" }} components={{ Balance: ( - + {BigInt(myWallet.todayDailyPower || 0n)} ), diff --git a/apps/renderer/src/modules/wallet/balance.tsx b/apps/renderer/src/modules/wallet/balance.tsx index 373916f30..ed30ee9e5 100644 --- a/apps/renderer/src/modules/wallet/balance.tsx +++ b/apps/renderer/src/modules/wallet/balance.tsx @@ -23,10 +23,12 @@ export const Balance = ({ const formattedFull = format(n, { digits: 18, trailingZeros: true }) const Content = ( -
- {withSuffix && } + + {withSuffix && ( + + )} {formatted} -
+ ) if (!withTooltip) return Content diff --git a/apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx b/apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx deleted file mode 100644 index 92d99845c..000000000 --- a/apps/renderer/src/pages/(external)/(with-layout)/feed/[id]/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { redirect } from "react-router-dom" - -/** - * @deprecated remove after split application - */ -export const loader = async ({ params }: { params: { id: string } }) => { - return redirect(`/share/feeds/${params.id}`) -} -export function Component() { - return null -} diff --git a/apps/renderer/src/pages/(external)/(with-layout)/layout.tsx b/apps/renderer/src/pages/(external)/(with-layout)/layout.tsx deleted file mode 100644 index 401d0bb65..000000000 --- a/apps/renderer/src/pages/(external)/(with-layout)/layout.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { FollowIcon } from "@follow/components/icons/follow.jsx" -import { Logo } from "@follow/components/icons/logo.jsx" -import { cn } from "@follow/utils/utils" -import type { MotionValue } from "framer-motion" -import { useMotionValueEvent, useScroll } from "framer-motion" -import type { FC } from "react" -import { cloneElement, useState } from "react" -import { useTranslation } from "react-i18next" -import { Link, Outlet } from "react-router-dom" - -import { whoami } from "~/atoms/user" -import { usePresentUserProfileModal } from "~/modules/profile/hooks" -import { UserAvatar } from "~/modules/user/UserAvatar" - -const useMotionValueToState = (value: MotionValue) => { - const [state, setState] = useState(value.get()) - useMotionValueEvent(value, "change", (v) => setState(v)) - return state -} -/** @deprecated */ -export function Component() { - return ( - <> -
-
- -
- - ) -} - -function Header() { - const present = usePresentUserProfileModal() - const { t } = useTranslation("external") - - const { scrollY } = useScroll() - const scrollYState = useMotionValueToState(scrollY) - - return ( -
-
-
- -
-
-
- -
- -
- } - label={t("header.app")} - /> - - } - label={t("header.download")} - /> -
-
- -
-
-
- ) -} - -const HoverableLink: FC<{ - label: string - icon: React.JSX.Element - href: string - className?: string -}> = ({ icon, label, href, className }) => ( - - - {cloneElement(icon, { className: `size-4 ${icon.props.className}` })} - - - - {label} - {label} - - - -) diff --git a/apps/renderer/src/pages/(external)/(with-layout)/list/[id]/index.tsx b/apps/renderer/src/pages/(external)/(with-layout)/list/[id]/index.tsx deleted file mode 100644 index 41d1fe86a..000000000 --- a/apps/renderer/src/pages/(external)/(with-layout)/list/[id]/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { redirect } from "react-router-dom" - -export const loader = async ({ params }: { params: { id: string } }) => { - return redirect(`/share/lists/${params.id}`) -} -/** - * @deprecated remove after split application - */ -export function Component() { - return null -} diff --git a/apps/renderer/src/pages/(external)/(with-layout)/profile/[id]/index.tsx b/apps/renderer/src/pages/(external)/(with-layout)/profile/[id]/index.tsx deleted file mode 100644 index 7e61c0ac1..000000000 --- a/apps/renderer/src/pages/(external)/(with-layout)/profile/[id]/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { redirect } from "react-router-dom" - -export const loader = async ({ params }: { params: { id: string } }) => { - return redirect(`/share/users/${params.id}`) -} -/** - * @deprecated remove after split application - */ -export function Component() { - return null -} diff --git a/apps/renderer/src/pages/(external)/(with-layout)/share/feeds/[id]/index.tsx b/apps/renderer/src/pages/(external)/(with-layout)/share/feeds/[id]/index.tsx deleted file mode 100644 index 7143b49d5..000000000 --- a/apps/renderer/src/pages/(external)/(with-layout)/share/feeds/[id]/index.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { FollowIcon } from "@follow/components/icons/follow.jsx" -import { Button } from "@follow/components/ui/button/index.js" -import { LoadingCircle } from "@follow/components/ui/loading/index.jsx" -import type { FeedViewType } from "@follow/constants" -import { views } from "@follow/constants" -import { useTitle } from "@follow/hooks" -import type { FeedModel } from "@follow/models/types" -import { cn } from "@follow/utils/utils" -import type { FC } from "react" -import { useTranslation } from "react-i18next" -import { useParams, useSearchParams } from "react-router-dom" -import { toast } from "sonner" - -import { PoweredByFooter } from "~/components/common/PoweredByFooter" -import { usePresentFeedFormModal } from "~/hooks/biz/useFeedFormModal" -import { getItemComponentByView } from "~/modules/entry-column/Items" -import type { UniversalItemProps } from "~/modules/entry-column/types" -import { FeedCertification } from "~/modules/feed/feed-certification" -import { FeedIcon } from "~/modules/feed/feed-icon" -import { useEntriesPreview } from "~/queries/entries" -import { useFeed } from "~/queries/feed" - -export function Component() { - const { id } = useParams() - const [search] = useSearchParams() - const view = Number.parseInt(search.get("view") || "0") - - const feed = useFeed({ - id, - }) - const feedData = feed.data?.feed as FeedModel - const isSubscribed = !!feed.data?.subscription - const entries = useEntriesPreview({ - id, - }) - - const Item: FC = getItemComponentByView(view as FeedViewType) - - const { t } = useTranslation("external") - useTitle(feed.data?.feed.title) - const presentFeedFormModal = usePresentFeedFormModal() - return ( - <> - {feed.isLoading ? ( - - ) : ( - feed.data?.feed && ( -
- -
-
-

{feed.data.feed.title}

- -
-
{feed.data.feed.description}
-
-
- {t("feed.followsAndReads", { - subscriptionCount: feed.data.subscriptionCount, - subscriptionNoun: t("feed.follower", { count: feed.data.subscriptionCount }), - readCount: feed.data.readCount, - readNoun: t("feed.read", { count: feed.data.readCount }), - appName: APP_NAME, - })} -
- - {feedData.url.startsWith("https://") ? ( - - ) : ( - - )} - - -
- {entries.data?.map((entry) => ( - -
- -
-
- ))} -
- -
- ) - )} - - ) -} diff --git a/apps/renderer/src/pages/(external)/(with-layout)/share/lists/[id]/index.tsx b/apps/renderer/src/pages/(external)/(with-layout)/share/lists/[id]/index.tsx deleted file mode 100644 index 3fc564db9..000000000 --- a/apps/renderer/src/pages/(external)/(with-layout)/share/lists/[id]/index.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import { FollowIcon } from "@follow/components/icons/follow.jsx" -import { Button } from "@follow/components/ui/button/index.js" -import { LoadingCircle } from "@follow/components/ui/loading/index.jsx" -import { useTitle } from "@follow/hooks" -import type { ListModel } from "@follow/models/types" -import { useTranslation } from "react-i18next" -import { useParams } from "react-router-dom" -import { toast } from "sonner" - -import { PoweredByFooter } from "~/components/common/PoweredByFooter" -import { usePresentFeedFormModal } from "~/hooks/biz/useFeedFormModal" -import { FeedCertification } from "~/modules/feed/feed-certification" -import { FeedIcon } from "~/modules/feed/feed-icon" -import { useList } from "~/queries/lists" -import { useFeedById } from "~/store/feed/hooks" - -export function Component() { - const { id } = useParams() - - const list = useList({ - id: id!, - }) - const listData = list.data?.list as ListModel - const isSubscribed = !!list.data?.subscription - - const { t } = useTranslation("external") - useTitle(list.data?.list.title) - const presentFeedFormModal = usePresentFeedFormModal() - return ( - <> - {list.isLoading ? ( - - ) : ( - list.data?.list && ( -
- -
-
-

{list.data.list.title}

- -
-
{list.data.list.description}
-
-
- {t("feed.followsAndFeeds", { - subscriptionCount: list.data?.subscriptionCount, - subscriptionNoun: t("feed.follower", { count: list.data?.subscriptionCount }), - feedsCount: list.data?.feedCount || 0, - feedsNoun: t("feed.feeds", { count: listData?.feedIds?.length }), - appName: APP_NAME, - })} -
- - - - -
- {listData.feedIds - ?.slice(0, 5) - .map((feedId) => )} - {"feedCount" in list.data && ( -
{ - presentFeedFormModal({ - listId: id!, - }) - }} - className="text-sm text-zinc-500" - > - {t("feed.follow_to_view_all", { - count: list.data.feedCount || 0, - })} -
- )} -
- -
- ) - )} - - ) -} - -const FeedRow = ({ feedId }: { feedId: string }) => { - const feed = useFeedById(feedId) - if (!feed) return null - return ( - - - {feed.title} - - - ) -} diff --git a/apps/renderer/src/pages/(external)/(with-layout)/share/users/[id]/index.tsx b/apps/renderer/src/pages/(external)/(with-layout)/share/users/[id]/index.tsx deleted file mode 100644 index 526e6e685..000000000 --- a/apps/renderer/src/pages/(external)/(with-layout)/share/users/[id]/index.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import { FollowIcon } from "@follow/components/icons/follow.jsx" -import { Avatar, AvatarFallback, AvatarImage } from "@follow/components/ui/avatar/index.jsx" -import { Button } from "@follow/components/ui/button/index.js" -import { LoadingCircle } from "@follow/components/ui/loading/index.jsx" -import { useTitle } from "@follow/hooks" -import { UrlBuilder } from "@follow/utils/url-builder" -import { cn, isBizId } from "@follow/utils/utils" -import { Fragment } from "react/jsx-runtime" -import { useParams } from "react-router-dom" - -import { useWhoami } from "~/atoms/user" -import { PoweredByFooter } from "~/components/common/PoweredByFooter" -import { usePresentFeedFormModal } from "~/hooks/biz/useFeedFormModal" -import { useAuthQuery, useI18n } from "~/hooks/common" -import { apiClient } from "~/lib/api-fetch" -import { defineQuery } from "~/lib/defineQuery" -import { replaceImgUrlIfNeed } from "~/lib/img-proxy" -import { FeedIcon } from "~/modules/feed/feed-icon" -import { useUserSubscriptionsQuery } from "~/modules/profile/hooks" - -export function Component() { - const t = useI18n() - const { id } = useParams() - - const isHandle = id ? id.startsWith("@") || !isBizId(id) : false - const user = useAuthQuery( - defineQuery(["profiles", id], async () => { - const res = await apiClient.profiles.$get({ - query: { - handle: isHandle ? (id?.startsWith("@") ? id.slice(1) : id) : undefined, - id: isHandle ? undefined : id, - }, - }) - return res.data - }), - { - enabled: !!id, - }, - ) - - const subscriptions = useUserSubscriptionsQuery(user.data?.id) - useTitle(user.data?.name) - const me = useWhoami() - const isMe = user.data?.id === me?.id - const presentFeedFormModal = usePresentFeedFormModal() - - return ( -
- {user.isLoading ? ( - - ) : ( - - - - {user.data?.name?.slice(0, 2)} - -
-
-

{user.data?.name}

-
-
{user.data?.handle}
-
-
- {subscriptions.isLoading ? ( - - ) : ( - Object.keys(subscriptions.data || {}).map((category) => ( -
-
-

{category}

-
-
- {subscriptions.data?.[category].map( - (subscription) => - "feeds" in subscription && ( -
- - -
-
- {subscription.feeds?.title} -
- {subscription.feeds?.description && ( -
- {subscription.feeds.description} -
- )} -
-
- - - -
- ), - )} -
-
- )) - )} -
- -
- )} -
- ) -} diff --git a/apps/renderer/src/pages/(external)/invitation.tsx b/apps/renderer/src/pages/(external)/invitation.tsx deleted file mode 100644 index 5b8d56cd3..000000000 --- a/apps/renderer/src/pages/(external)/invitation.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { Logo } from "@follow/components/icons/logo.jsx" -import { Button } from "@follow/components/ui/button/index.js" -import { styledButtonVariant } from "@follow/components/ui/button/variants.js" -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@follow/components/ui/form/index.jsx" -import { Input } from "@follow/components/ui/input/index.js" -import { Tooltip, TooltipContent, TooltipTrigger } from "@follow/components/ui/tooltip/index.jsx" -import { IN_ELECTRON } from "@follow/shared/constants" -import { zodResolver } from "@hookform/resolvers/zod" -import type { DotLottie } from "@lottiefiles/dotlottie-react" -import { DotLottieReact } from "@lottiefiles/dotlottie-react" -import { m } from "framer-motion" -import type { RefCallback } from "react" -import { useEffect, useState } from "react" -import { useForm } from "react-hook-form" -import { useTranslation } from "react-i18next" -import { useNavigate } from "react-router-dom" -import { z } from "zod" - -import { SocialMediaLinks } from "~/constants/social" -import { useSignOut } from "~/hooks/biz/useSignOut" -import { tipcClient } from "~/lib/client" -import { getFetchErrorMessage } from "~/lib/error-parser" -import confettiUrl from "~/lottie/confetti.lottie?url" -import { useInvitationMutation } from "~/queries/invitations" - -const absoluteConfettiUrl = new URL(confettiUrl, import.meta.url).href - -const formSchema = z.object({ - code: z.string().min(1), -}) -/** - * - * @deprecated - */ -export function Component() { - const { t } = useTranslation("external") - const navigate = useNavigate() - const form = useForm>({ - resolver: zodResolver(formSchema), - }) - const invitationMutation = useInvitationMutation({ - onError(error) { - const message = getFetchErrorMessage(error) - form.setError("code", { message }) - }, - }) - - function onSubmit(values: z.infer) { - invitationMutation.mutate(values.code) - } - - const [showConfetti, setShowConfetti] = useState(false) - - useEffect(() => { - if (invitationMutation.isSuccess) { - setShowConfetti(true) - } - }, [invitationMutation.isSuccess]) - const [dotLottie, setDotLottie] = useState(null) - - useEffect(() => { - function onComplete() { - navigate("/") - } - - if (dotLottie) { - dotLottie.addEventListener("complete", onComplete) - } - - return () => { - if (dotLottie) { - dotLottie.removeEventListener("complete", onComplete) - } - } - }, [dotLottie, navigate]) - - const dotLottieRefCallback: RefCallback = (dotLottie) => { - setDotLottie(dotLottie) - } - - const signOut = useSignOut() - - return ( -
- - -
- - ( - - {t("invitation.title")} - - - -
- -
-
- )} - /> -
- {showConfetti && ( - - )} - - - - - - - {t("login.signOut")} - -
- - -
-

{t("invitation.earlyAccessMessage")}

-

{t("invitation.getCodeMessage")}

-

-

1. {t("invitation.codeOptions.1")}

-

2. {t("invitation.codeOptions.2")}

-

3. {t("invitation.codeOptions.3")}

-

-
-
- {SocialMediaLinks.map((link) => ( - - - - {link.label} - - - ))} -
-
- ) -} diff --git a/configs/tailwind-extend.css b/configs/tailwind-extend.css index 1d3046ee3..8e60cf943 100644 --- a/configs/tailwind-extend.css +++ b/configs/tailwind-extend.css @@ -378,4 +378,20 @@ transform: rotateY(180deg); } } + + @keyframes rocketAnimation { + 0% { + transform: translateY(0); + } + 50% { + transform: translate(2px, -1px); + } + 100% { + transform: translateY(0); + } + } + + .animate-rocket { + animation: rocketAnimation 1s infinite ease-out; + } } diff --git a/packages/components/src/ui/button/variants.tsx b/packages/components/src/ui/button/variants.tsx index f7bee973c..974115ff5 100644 --- a/packages/components/src/ui/button/variants.tsx +++ b/packages/components/src/ui/button/variants.tsx @@ -60,7 +60,7 @@ export const styledButtonVariant = cva( text: cn( "font-semibold text-accent", "hover:contrast-[1.10] active:contrast-125", - "focus:text-accent focus:outline-none", + tw`focus:text-accent focus:outline-none p-0 inline align-baseline`, ), ghost: cn("px-1.5 font-semibold", "hover:bg-theme-button-hover"), },