diff --git a/eslint.config.mjs b/eslint.config.mjs index e9a46f695..2dd995663 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -24,6 +24,7 @@ export default defineConfig( rules: { "unicorn/prefer-math-trunc": "off", "@eslint-react/no-clone-element": 0, + "no-restricted-syntax": 0, "no-restricted-globals": [ "error", { diff --git a/src/renderer/src/components/ui/loading.tsx b/src/renderer/src/components/ui/loading.tsx index b47fee760..87bd7e012 100644 --- a/src/renderer/src/components/ui/loading.tsx +++ b/src/renderer/src/components/ui/loading.tsx @@ -1,19 +1,111 @@ import { cn } from "@renderer/lib/utils" +import React, { cloneElement } from "react" interface LoadingCircleProps { size: "small" | "medium" | "large" } const sizeMap = { - small: "text-md", - medium: "text-xl", - large: "text-3xl", + small: 16, + medium: 24, + large: 30, } export const LoadingCircle: Component = ({ className, size, }) => ( -
+
) + +const smallIconSizeMap = { + small: 12, + medium: 14, + large: 16, +} +export const LoadingWithIcon: Component< + LoadingCircleProps & { + icon: React.JSX.Element + order?: "loading-first" | "icon-first" + } +> = ({ order = "loading-first", size, className, icon, children }) => { + const rootStyle = { width: sizeMap[size], height: sizeMap[size] } + + const smallIconStyle = { + height: smallIconSizeMap[size], + width: smallIconSizeMap[size], + } + + const Children = children &&
{children}
+ if (order === "icon-first") { + return ( +
+
+ + {cloneElement(icon, { + style: { + ...icon.props.style, + fontSize: sizeMap[size], + }, + className: cn(icon.props.className), + })} + + + + +
+ + {Children} +
+ ) + } else { + return ( +
+
+ + + + + {cloneElement(icon, { + style: { + ...icon.props.style, + fontSize: smallIconSizeMap[size], + }, + className: icon.props.className, + })} + +
+ {Children} +
+ ) + } +} diff --git a/src/renderer/src/modules/entry-content/index.tsx b/src/renderer/src/modules/entry-content/index.tsx index 07257bfb5..702439f83 100644 --- a/src/renderer/src/modules/entry-content/index.tsx +++ b/src/renderer/src/modules/entry-content/index.tsx @@ -32,7 +32,7 @@ import { useFeedById, useFeedHeaderTitle } from "@renderer/store/feed" import type { FC } from "react" import { useEffect, useLayoutEffect, useRef } from "react" -import { LoadingCircle } from "../../components/ui/loading" +import { LoadingWithIcon } from "../../components/ui/loading" import { EntryPlaceholderDaily } from "../ai/ai-daily/EntryPlaceholderDaily" import { EntryTranslation } from "../entry-column/translation" import { setEntryContentScrollToTop, setEntryTitleMeta } from "./atoms" @@ -235,7 +235,12 @@ export const EntryContentRender: Component<{ entryId: string }> = ({ {!content && (
{isPending ? ( - + + } + /> ) : error ? (
@@ -308,7 +313,10 @@ const ReadabilityContent = ({ entryId }: { entryId: string }) => {

) : (
- + } + /> Fetching original content and processing... diff --git a/src/renderer/src/modules/profile/user-profile-modal.tsx b/src/renderer/src/modules/profile/user-profile-modal.tsx index a33256930..e5eb1816c 100644 --- a/src/renderer/src/modules/profile/user-profile-modal.tsx +++ b/src/renderer/src/modules/profile/user-profile-modal.tsx @@ -8,7 +8,10 @@ import { AvatarImage, } from "@renderer/components/ui/avatar" import { ActionButton, Button } from "@renderer/components/ui/button" -import { LoadingCircle } from "@renderer/components/ui/loading" +import { + LoadingCircle, + LoadingWithIcon, +} from "@renderer/components/ui/loading" import { useCurrentModal, useModalStack } from "@renderer/components/ui/modal" import { ScrollArea } from "@renderer/components/ui/scroll-area" import { useAuthQuery } from "@renderer/hooks/common" @@ -277,8 +280,9 @@ export const UserProfileModalContent: FC<{ viewportClassName="[&>div]:space-y-4 pb-4" > {subscriptions.isLoading ? ( - } className="center h-48 w-full max-w-full" /> ) : ( diff --git a/src/renderer/src/modules/settings/setting-builder.tsx b/src/renderer/src/modules/settings/setting-builder.tsx index f8e2785e4..c557b66d8 100644 --- a/src/renderer/src/modules/settings/setting-builder.tsx +++ b/src/renderer/src/modules/settings/setting-builder.tsx @@ -1,4 +1,5 @@ /* eslint-disable @eslint-react/no-array-index-key */ +import { isNil } from "lodash-es" import type { FC, ReactNode } from "react" import * as React from "react" import { isValidElement } from "react" @@ -49,7 +50,7 @@ export const createSettingBuilder = const settingObject = useSetting() return settings - .filter((i) => typeof i !== "boolean") + .filter((i) => !isNil(i)) .map((setting, index) => { if (isValidElement(setting)) return setting if (typeof setting === "function") { diff --git a/src/renderer/src/modules/settings/tabs/wallet/my-wallet-section/index.tsx b/src/renderer/src/modules/settings/tabs/wallet/my-wallet-section/index.tsx index 5b47d5cf4..ca2b8e8a1 100644 --- a/src/renderer/src/modules/settings/tabs/wallet/my-wallet-section/index.tsx +++ b/src/renderer/src/modules/settings/tabs/wallet/my-wallet-section/index.tsx @@ -1,6 +1,6 @@ import { useWhoami } from "@renderer/atoms/user" import { Divider } from "@renderer/components/ui/divider" -import { LoadingCircle } from "@renderer/components/ui/loading" +import { LoadingWithIcon } from "@renderer/components/ui/loading" import { Tooltip, TooltipContent, @@ -22,7 +22,11 @@ export const MyWalletSection = () => { if (wallet.isPending) { return (
- + } + size="large" + className="-translate-y-full" + />
) } @@ -63,9 +67,7 @@ export const MyWalletSection = () => {
- Cashable Power - {" "} - + Cashable Power {myWallet.cashablePowerToken} @@ -77,8 +79,8 @@ export const MyWalletSection = () => { 1. Cashable Power can be withdrawn to your wallet for trading.

- 2. Cashable Power is the Power you have recharged and the tips you - have received. + 2. Cashable Power is the Power you have recharged and the tips + you have received.

diff --git a/src/renderer/src/modules/settings/tabs/wallet/transaction-section/index.tsx b/src/renderer/src/modules/settings/tabs/wallet/transaction-section/index.tsx index 9da58c033..e9ded55a4 100644 --- a/src/renderer/src/modules/settings/tabs/wallet/transaction-section/index.tsx +++ b/src/renderer/src/modules/settings/tabs/wallet/transaction-section/index.tsx @@ -53,10 +53,10 @@ export const TransactionsSection = () => { Amount - + From - + To @@ -152,7 +152,7 @@ const UserRenderer = ({ const name = isMe ? "You" : user?.name || APP_NAME return ( -
+
{name === APP_NAME ? ( ) : ( diff --git a/src/renderer/src/modules/wallet/tip-modal.tsx b/src/renderer/src/modules/wallet/tip-modal.tsx index 279a24074..0c80a7bdd 100644 --- a/src/renderer/src/modules/wallet/tip-modal.tsx +++ b/src/renderer/src/modules/wallet/tip-modal.tsx @@ -1,14 +1,20 @@ import { useWhoami } from "@renderer/atoms/user" import { Button } from "@renderer/components/ui/button" import { Divider } from "@renderer/components/ui/divider" -import { LoadingCircle } from "@renderer/components/ui/loading" +import { + LoadingWithIcon, +} from "@renderer/components/ui/loading" import { useCurrentModal } from "@renderer/components/ui/modal" import { RadioGroup } from "@renderer/components/ui/radio-group" import { RadioCard } from "@renderer/components/ui/radio-group/RadioCard" import { Balance } from "@renderer/components/ui/wallet/balance" import { UserAvatar } from "@renderer/components/user-button" import { nextFrame } from "@renderer/lib/dom" -import { useWallet, useWalletTipMutation, useWalletTransactions } from "@renderer/queries/wallet" +import { + useWallet, + useWalletTipMutation, + useWalletTransactions, +} from "@renderer/queries/wallet" import { from, toNumber } from "dnum" import type { FC } from "react" import { useState } from "react" @@ -18,28 +24,63 @@ import { useSettingModal } from "../settings/modal/hooks-hack" const DEFAULT_RECOMMENDED_TIP = 1 +const useMyWallet = () => { + const user = useWhoami() + const myWallet = useWallet({ userId: user?.id }) + return myWallet +} + +const Loading = () => ( +
+ } size="large" /> +
+) + export const TipModalContent: FC<{ userId?: string feedId?: string +}> = (props) => { + const myWallet = useMyWallet() + + if (!myWallet.data) { + return ( + + ) + } + return +} +const TipModalContent_: FC<{ + userId?: string + feedId?: string }> = ({ userId, feedId }) => { - const user = useWhoami() - const myWallet = useWallet({ userId: user?.id }) + const myWallet = useMyWallet() const myWalletData = myWallet.data?.[0] const dPowerBigInt = BigInt(myWalletData?.dailyPowerToken ?? 0) const cPowerBigInt = BigInt(myWalletData?.cashablePowerToken ?? 0) const balanceBigInt = cPowerBigInt + dPowerBigInt - const balanceNumber = toNumber(from(balanceBigInt, 18), { digits: 2, trailingZeros: true }) + const balanceNumber = toNumber(from(balanceBigInt, 18), { + digits: 2, + trailingZeros: true, + }) - const transactionsQuery = useWalletTransactions({ toUserId: userId, toFeedId: feedId }) + const transactionsQuery = useWalletTransactions({ + toUserId: userId, + toFeedId: feedId, + }) const tipMutation = useWalletTipMutation() - const [amount, setAmount] = useState(DEFAULT_RECOMMENDED_TIP > balanceNumber ? balanceNumber : DEFAULT_RECOMMENDED_TIP) + const [amount, setAmount] = useState( + DEFAULT_RECOMMENDED_TIP > balanceNumber ? + balanceNumber : + DEFAULT_RECOMMENDED_TIP, + ) const amountBigInt = from(amount, 18)[0] - const wrongNumberRange = amountBigInt > balanceBigInt || amountBigInt <= BigInt(0) + const wrongNumberRange = + amountBigInt > balanceBigInt || amountBigInt <= BigInt(0) const { dismiss } = useCurrentModal() @@ -51,9 +92,7 @@ export const TipModalContent: FC<{ if (transactionsQuery.isPending || myWallet.isPending) { return ( -
- -
+ ) } @@ -88,14 +127,12 @@ export const TipModalContent: FC<{

{amountBigInt} {" "} - has been sent to the author. + has been sent to the + author.

-
@@ -108,15 +145,27 @@ export const TipModalContent: FC<{ {userId ? ( <>

Feed Owner

- + ) : ( <>

- No one has claimed this feed yet. The received Power will be securely held in the blockchain contract until it is claimed. + + No one has claimed this feed yet. The received Power will be + securely held in the blockchain contract until it is claimed. +

- +
)} @@ -136,8 +185,16 @@ export const TipModalContent: FC<{ onValueChange={(value) => setAmount(Number(value))} >
- - + +
@@ -152,7 +209,6 @@ export const TipModalContent: FC<{
- )}