feat(power): restrict power usage to wallet
This commit is contained in:
parent
88ad11a2ae
commit
e1daec3013
|
|
@ -117,7 +117,7 @@ export const FeedForm: Component<{
|
|||
isError: feedQuery.isError,
|
||||
})
|
||||
}
|
||||
}, [feedQuery.isLoading])
|
||||
}, [feedQuery.data?.feed.url, feedQuery.isError, feedQuery.isLoading, id, url])
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -250,7 +250,7 @@ const FeedInnerForm = ({
|
|||
|
||||
useEffect(() => {
|
||||
setClickOutSideToDismiss(!form.formState.isDirty)
|
||||
}, [form.formState.isDirty])
|
||||
}, [form.formState.isDirty, setClickOutSideToDismiss])
|
||||
|
||||
useEffect(() => {
|
||||
if (subscription) {
|
||||
|
|
@ -262,7 +262,7 @@ const FeedInnerForm = ({
|
|||
form.setValue("hideFromTimeline", subscription.hideFromTimeline)
|
||||
subscription?.title && form.setValue("title", subscription.title)
|
||||
}
|
||||
}, [subscription])
|
||||
}, [form, subscription])
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
|
|
@ -272,7 +272,7 @@ const FeedInnerForm = ({
|
|||
) {
|
||||
form.setValue("view", `${analytics.view}`)
|
||||
}
|
||||
}, [analytics, subscription, defaultValues?.view])
|
||||
}, [analytics, defaultValues?.view, form, subscription])
|
||||
|
||||
const followMutation = useMutation({
|
||||
mutationFn: async (values: z.infer<typeof formSchema>) => {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ import { useTOTPModalWrapper } from "~/modules/profile/hooks"
|
|||
import { Balance } from "~/modules/wallet/balance"
|
||||
import { useWallet, wallet as walletActions } from "~/queries/wallet"
|
||||
|
||||
const RSS3_CONVERSION_RATE = 0.043
|
||||
|
||||
export const WithdrawButton = () => {
|
||||
const { t } = useTranslation("settings")
|
||||
const { present } = useModalStack()
|
||||
|
|
@ -54,18 +56,22 @@ const WithdrawModalContent = ({ dismiss }: { dismiss: () => void }) => {
|
|||
const wallet = useWallet()
|
||||
const cashablePowerTokenBigInt = [BigInt(wallet.data?.[0]!.cashablePowerToken || 0n), 18] as const
|
||||
const cashablePowerTokenNumber = toNumber(cashablePowerTokenBigInt)
|
||||
const walletAddress = wallet.data?.[0]?.address ?? "-"
|
||||
|
||||
const formSchema = z.object({
|
||||
address: z.string().startsWith("0x").length(42),
|
||||
amount: z.number().positive().max(cashablePowerTokenNumber),
|
||||
toRss3: z.boolean().optional(),
|
||||
toRss3: z.boolean(),
|
||||
})
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
toRss3: true,
|
||||
},
|
||||
})
|
||||
|
||||
const rss3ConversionRate: number | null = null
|
||||
const withdrawAmount = form.watch("amount")
|
||||
const receiveAmount = Number.isFinite(withdrawAmount) ? withdrawAmount * RSS3_CONVERSION_RATE : 0
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async ({
|
||||
|
|
@ -91,7 +97,7 @@ const WithdrawModalContent = ({ dismiss }: { dismiss: () => void }) => {
|
|||
const present = useTOTPModalWrapper(mutation.mutateAsync, { force: true })
|
||||
|
||||
const onSubmit = (values: z.infer<typeof formSchema>) => {
|
||||
present(values)
|
||||
present({ ...values, toRss3: true })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -126,6 +132,9 @@ const WithdrawModalContent = ({ dismiss }: { dismiss: () => void }) => {
|
|||
</div>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 lg:w-96">
|
||||
<div className="rounded-md border border-orange/20 bg-orange/10 p-3 text-xs leading-relaxed text-text-secondary">
|
||||
{t("wallet.withdraw.gasFeeNotice", { address: walletAddress })}
|
||||
</div>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="address"
|
||||
|
|
@ -161,7 +170,7 @@ const WithdrawModalContent = ({ dismiss }: { dismiss: () => void }) => {
|
|||
<FormField
|
||||
control={form.control}
|
||||
name="toRss3"
|
||||
render={({ field }) => (
|
||||
render={() => (
|
||||
<FormItem>
|
||||
<div className="flex items-center gap-2">
|
||||
<FormLabel className="flex items-center gap-1">
|
||||
|
|
@ -173,7 +182,7 @@ const WithdrawModalContent = ({ dismiss }: { dismiss: () => void }) => {
|
|||
<TooltipPortal>
|
||||
<TooltipContent>
|
||||
<span className="text-xs text-gray-500">
|
||||
<span>1 POWER = {rss3ConversionRate ?? "-"} RSS3</span>
|
||||
<span>1 POWER = {RSS3_CONVERSION_RATE} RSS3</span>
|
||||
</span>
|
||||
</TooltipContent>
|
||||
</TooltipPortal>
|
||||
|
|
@ -181,17 +190,15 @@ const WithdrawModalContent = ({ dismiss }: { dismiss: () => void }) => {
|
|||
</FormLabel>
|
||||
<FormControl className="!mt-0">
|
||||
<span className="inline-flex">
|
||||
<Switch checked={field.value} onCheckedChange={field.onChange} />
|
||||
<Switch checked={true} disabled />
|
||||
</span>
|
||||
</FormControl>
|
||||
</div>
|
||||
{field.value && rss3ConversionRate !== null && (
|
||||
<span className="text-xs text-gray-500">
|
||||
{t("wallet.withdraw.receiveRSS3", {
|
||||
amount: ((form.watch("amount") || 0) * rss3ConversionRate).toFixed(4),
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-xs text-gray-500">
|
||||
{t("wallet.withdraw.receiveRSS3", {
|
||||
amount: receiveAmount.toFixed(4),
|
||||
})}
|
||||
</span>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export function AddModalContent({
|
|||
if (addRSSHubMutation.isSuccess) {
|
||||
dismiss()
|
||||
}
|
||||
}, [addRSSHubMutation.isSuccess])
|
||||
}, [addRSSHubMutation.isSuccess, dismiss])
|
||||
|
||||
useEffect(() => {
|
||||
if (details.data?.instance.baseUrl) {
|
||||
|
|
@ -64,12 +64,11 @@ export function AddModalContent({
|
|||
accessKey: details.data.instance.accessKey || undefined,
|
||||
})
|
||||
}
|
||||
}, [details.data])
|
||||
}, [details.data, form])
|
||||
|
||||
const codes = [
|
||||
`FOLLOW_OWNER_USER_ID=${me?.handle || me?.id} # User id or handle of your follow account`,
|
||||
`FOLLOW_DESCRIPTION=${instance?.description || `${me?.name}'s instance`} # The description of your instance`,
|
||||
`FOLLOW_PRICE=${instance?.price || 100} # The monthly price of your instance, set to 0 means free.`,
|
||||
`FOLLOW_USER_LIMIT=${instance?.userLimit || 1000} # The user limit of your instance, set it to 0 or 1 can make your instance private, leaving it empty means no restriction`,
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,10 @@
|
|||
import { Button } from "@follow/components/ui/button/index.js"
|
||||
import { Card, CardContent } from "@follow/components/ui/card/index.js"
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@follow/components/ui/form/index.jsx"
|
||||
import { Input } from "@follow/components/ui/input/Input.js"
|
||||
import { whoami } from "@follow/store/user/getters"
|
||||
import type { RSSHubListItem } from "@follow-app/client-sdk"
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useEffect } from "react"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { Trans, useTranslation } from "react-i18next"
|
||||
import { z } from "zod"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { useAuthQuery } from "~/hooks/common"
|
||||
import { UserAvatar } from "~/modules/user/UserAvatar"
|
||||
import { Queries } from "~/queries"
|
||||
import { useSetRSSHubMutation } from "~/queries/rsshub"
|
||||
|
||||
import { useTOTPModalWrapper } from "../profile/hooks"
|
||||
|
|
@ -34,35 +19,12 @@ export function SetModalContent({
|
|||
const { t } = useTranslation("settings")
|
||||
const setRSSHubMutation = useSetRSSHubMutation()
|
||||
const preset = useTOTPModalWrapper(setRSSHubMutation.mutateAsync)
|
||||
const details = useAuthQuery(Queries.rsshub.get({ id: instance.id }))
|
||||
const hasPurchase = !!details.data?.purchase
|
||||
const price = instance.ownerUserId === whoami()?.id ? 0 : instance.price
|
||||
|
||||
const formSchema = z.object({
|
||||
months: z.coerce
|
||||
.number()
|
||||
.min(hasPurchase ? 0 : 1)
|
||||
.max(12),
|
||||
})
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
months: hasPurchase ? 0 : 1,
|
||||
},
|
||||
})
|
||||
|
||||
const months = form.watch("months")
|
||||
|
||||
const onSubmit = (data: z.infer<typeof formSchema>) => {
|
||||
preset({ id: instance.id, durationInMonths: data.months })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (setRSSHubMutation.isSuccess) {
|
||||
dismiss()
|
||||
}
|
||||
}, [setRSSHubMutation.isSuccess])
|
||||
}, [setRSSHubMutation.isSuccess, dismiss])
|
||||
|
||||
return (
|
||||
<div className="max-w-[550px] space-y-4 lg:min-w-[550px]">
|
||||
|
|
@ -85,12 +47,6 @@ export function SetModalContent({
|
|||
<td className="text-sm text-text-secondary">{t("rsshub.table.description")}</td>
|
||||
<td className="line-clamp-2">{instance.description}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-sm text-text-secondary">{t("rsshub.table.price")}</td>
|
||||
<td className="flex items-center gap-1">
|
||||
{instance.price} <i className="i-mgc-power text-folo" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-sm text-text-secondary">{t("rsshub.table.userCount")}</td>
|
||||
<td>{instance.userCount}</td>
|
||||
|
|
@ -103,64 +59,15 @@ export function SetModalContent({
|
|||
</table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{details.data?.purchase && (
|
||||
<div>
|
||||
<div className="text-sm text-text-secondary">
|
||||
{t("rsshub.useModal.purchase_expires_at")}
|
||||
</div>
|
||||
<div className="line-clamp-2">
|
||||
{new Date(details.data.purchase.expiresAt).toLocaleString()}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||
{price > 0 && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="months"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-center gap-4">
|
||||
<FormLabel>{t("rsshub.useModal.months_label")}</FormLabel>
|
||||
<FormControl className="!mt-0">
|
||||
<div className="flex items-center gap-10">
|
||||
<div className="space-x-2">
|
||||
<Input
|
||||
className="w-24"
|
||||
type="number"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]*"
|
||||
max={12}
|
||||
min={hasPurchase ? 0 : 1}
|
||||
{...field}
|
||||
/>
|
||||
<span className="text-sm text-text-secondary">
|
||||
{t("rsshub.useModal.month")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<div className="flex items-center justify-end">
|
||||
<Button type="submit" isLoading={setRSSHubMutation.isPending}>
|
||||
{price ? (
|
||||
<Trans
|
||||
ns="settings"
|
||||
i18nKey={"rsshub.useModal.useWith"}
|
||||
components={{ Power: <i className="i-mgc-power ml-1 text-white" /> }}
|
||||
values={{ amount: price * months }}
|
||||
/>
|
||||
) : (
|
||||
t("rsshub.table.use")
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
<div className="flex items-center justify-end">
|
||||
<Button
|
||||
type="button"
|
||||
isLoading={setRSSHubMutation.isPending}
|
||||
onClick={() => preset({ id: instance.id })}
|
||||
>
|
||||
{t("rsshub.table.use")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,8 +47,12 @@ export const PaidBadge: Component<{
|
|||
</TooltipTrigger>
|
||||
<TooltipPortal>
|
||||
<TooltipContent>
|
||||
{paidLevel === SettingPaidLevels.FreeLimited && t("control.paid_badge.free_limited")}
|
||||
{paidLevel === SettingPaidLevels.Basic && t("control.paid_badge.basic_or_higher")}
|
||||
{paidLevel === SettingPaidLevels.FreeLimited && (
|
||||
<span>{t("control.paid_badge.free_limited")}</span>
|
||||
)}
|
||||
{paidLevel === SettingPaidLevels.Basic && (
|
||||
<span>{t("control.paid_badge.basic_or_higher")}</span>
|
||||
)}
|
||||
</TooltipContent>
|
||||
</TooltipPortal>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ export const ProfileButton: FC<ProfileButtonProps> = memo((props) => {
|
|||
}}
|
||||
icon={<i className="i-mgc-power-outline" />}
|
||||
>
|
||||
{t("user_button.power")}
|
||||
{t("user_button.wallet")}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Logo } from "@follow/components/icons/logo.jsx"
|
|||
import { Button } from "@follow/components/ui/button/index.js"
|
||||
import { RSSHubLogo } from "@follow/components/ui/platform-icon/icons.js"
|
||||
import { whoami } from "@follow/store/user/getters"
|
||||
import { cn, formatNumber } from "@follow/utils/utils"
|
||||
import { cn } from "@follow/utils/utils"
|
||||
import type { RSSHubListItem } from "@follow-app/client-sdk"
|
||||
import { memo, useCallback, useEffect } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
|
@ -110,7 +110,6 @@ const InstanceCard = memo(({ item }: { item: InstanceItem }) => {
|
|||
)
|
||||
|
||||
const title = isOfficial ? "Folo Official" : ""
|
||||
const price = isOfficial ? 0 : instance.price
|
||||
const description = isOfficial ? "Folo Built-in RSSHub" : instance.description
|
||||
|
||||
const usersStat = isOfficial ? "*" : instance.userCount || 0
|
||||
|
|
@ -166,11 +165,6 @@ const InstanceCard = memo(({ item }: { item: InstanceItem }) => {
|
|||
<div className="flex items-center gap-1">{tags}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="flex items-center gap-1 text-sm font-medium">
|
||||
{formatNumber(price ?? 0)} <i className="i-mgc-power size-3 text-folo" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="mb-3 line-clamp-1 text-xs text-text-secondary">{description}</p>
|
||||
|
|
@ -276,7 +270,7 @@ function List({ data }: { data?: RSSHubListItem[] }) {
|
|||
|
||||
// full load last
|
||||
if (loadA === 1 && loadB === 1) {
|
||||
return a.price - b.price
|
||||
return 0
|
||||
}
|
||||
if (loadA === 1) {
|
||||
return 1
|
||||
|
|
@ -285,7 +279,7 @@ function List({ data }: { data?: RSSHubListItem[] }) {
|
|||
return -1
|
||||
}
|
||||
|
||||
return a.price - b.price || loadA - loadB
|
||||
return loadA - loadB
|
||||
}) || []),
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ export default ({ mode }) => {
|
|||
host: true,
|
||||
port: 2233,
|
||||
watch: {
|
||||
ignored: ["**/dist/**", "**/out/**", "**/public/**", ".git/**"],
|
||||
ignored: ["**/dist/**", "**/out/**", "**/public/**", ".git/**", "**/.env", "**/.env.*"],
|
||||
},
|
||||
cors: true,
|
||||
headers: {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { MagicCard } from '~/components/ui/magic-card'
|
|||
const tweetList = [
|
||||
{
|
||||
id: '1833056589135442345',
|
||||
text: "Very nice news aggregation, and it gives 2 power token everyday, so far I just try move front end people I followed in, haven't done yet, will try move more rss subscribe.",
|
||||
text: "Very nice news aggregation. So far I just try move front end people I followed in, haven't done yet, will try move more rss subscribe.",
|
||||
name: '🦋 AnneInCoding',
|
||||
screenName: '@anneincoding',
|
||||
profileImageUrl:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ export default defineConfig({
|
|||
],
|
||||
|
||||
server: {
|
||||
watch: {
|
||||
ignored: ["**/.env", "**/.env.*"],
|
||||
},
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "https://api.follow.is",
|
||||
|
|
|
|||
|
|
@ -241,7 +241,6 @@
|
|||
"feed_form.feedback": "Feedback",
|
||||
"feed_form.fill_default": "Fill",
|
||||
"feed_form.follow": "Follow",
|
||||
"feed_form.follow_with_fee": "Follow with {{fee}} Power",
|
||||
"feed_form.followed": "🎉 Followed.",
|
||||
"feed_form.hide_from_timeline": "Hide from Timeline",
|
||||
"feed_form.hide_from_timeline_description": "Whether this subscription's entries are visible on your main view timeline.",
|
||||
|
|
@ -504,9 +503,9 @@
|
|||
"user_button.ai": "AI",
|
||||
"user_button.download_desktop_app": "Download Desktop app",
|
||||
"user_button.log_out": "Log out",
|
||||
"user_button.power": "Power",
|
||||
"user_button.preferences": "Preferences",
|
||||
"user_button.profile": "Profile",
|
||||
"user_button.wallet": "Wallet",
|
||||
"user_profile.about": "About",
|
||||
"user_profile.close": "Close",
|
||||
"user_profile.created_lists": "Created Lists",
|
||||
|
|
|
|||
|
|
@ -241,7 +241,6 @@
|
|||
"feed_form.feedback": "Retour",
|
||||
"feed_form.fill_default": "Remplir",
|
||||
"feed_form.follow": "Suivre",
|
||||
"feed_form.follow_with_fee": "Suivre avec {{fee}} Puissance",
|
||||
"feed_form.followed": "🎉 Suivi.",
|
||||
"feed_form.hide_from_timeline": "Masquer de la chronologie",
|
||||
"feed_form.hide_from_timeline_description": "Si les entrées de cet abonnement sont visibles sur votre chronologie principale.",
|
||||
|
|
@ -503,9 +502,9 @@
|
|||
"user_button.ai": "IA",
|
||||
"user_button.download_desktop_app": "Télécharger appli bureau",
|
||||
"user_button.log_out": "Déconnexion",
|
||||
"user_button.power": "Puissance",
|
||||
"user_button.preferences": "Préférences",
|
||||
"user_button.profile": "Profil",
|
||||
"user_button.wallet": "Portefeuille",
|
||||
"user_profile.about": "À propos",
|
||||
"user_profile.close": "Fermer",
|
||||
"user_profile.created_lists": "Listes créées",
|
||||
|
|
|
|||
|
|
@ -241,7 +241,6 @@
|
|||
"feed_form.feedback": "フィードバック",
|
||||
"feed_form.fill_default": "入力する",
|
||||
"feed_form.follow": "フォロー",
|
||||
"feed_form.follow_with_fee": " {{fee}} Power で購読できます。",
|
||||
"feed_form.followed": "🎉 フォローしました。",
|
||||
"feed_form.hide_from_timeline": "タイムラインから非表示",
|
||||
"feed_form.hide_from_timeline_description": "このサブスクリプションのエントリーがメインビューのタイムラインに表示されるかどうか。",
|
||||
|
|
@ -504,9 +503,9 @@
|
|||
"user_button.ai": "AI",
|
||||
"user_button.download_desktop_app": "アプリをダウンロード",
|
||||
"user_button.log_out": "ログアウト",
|
||||
"user_button.power": "Power",
|
||||
"user_button.preferences": "設定",
|
||||
"user_button.profile": "プロフィール",
|
||||
"user_button.wallet": "ウォレット",
|
||||
"user_profile.about": "About",
|
||||
"user_profile.close": "閉じる",
|
||||
"user_profile.created_lists": "作成したリスト",
|
||||
|
|
|
|||
|
|
@ -241,7 +241,6 @@
|
|||
"feed_form.feedback": "反馈",
|
||||
"feed_form.fill_default": "填充",
|
||||
"feed_form.follow": "订阅",
|
||||
"feed_form.follow_with_fee": "使用 {{fee}} Power 订阅",
|
||||
"feed_form.followed": "🎉 订阅成功",
|
||||
"feed_form.hide_from_timeline": "在时间线上隐藏",
|
||||
"feed_form.hide_from_timeline_description": "开启后,此订阅将不再显示在主时间线中",
|
||||
|
|
@ -504,9 +503,9 @@
|
|||
"user_button.ai": "AI",
|
||||
"user_button.download_desktop_app": "下载客户端",
|
||||
"user_button.log_out": "登出",
|
||||
"user_button.power": "Power",
|
||||
"user_button.preferences": "设置",
|
||||
"user_button.profile": "个人资料",
|
||||
"user_button.wallet": "钱包",
|
||||
"user_profile.about": "关于",
|
||||
"user_profile.close": "关闭",
|
||||
"user_profile.created_lists": "创建的列表",
|
||||
|
|
|
|||
|
|
@ -241,7 +241,6 @@
|
|||
"feed_form.feedback": "回饋",
|
||||
"feed_form.fill_default": "填充",
|
||||
"feed_form.follow": "跟隨",
|
||||
"feed_form.follow_with_fee": "使用 {{fee}} Power 跟隨",
|
||||
"feed_form.followed": "🎉 跟隨成功。",
|
||||
"feed_form.hide_from_timeline": "從時間軸隱藏",
|
||||
"feed_form.hide_from_timeline_description": "開啟後,此訂閱將不再顯示在主時間軸中",
|
||||
|
|
@ -504,9 +503,9 @@
|
|||
"user_button.ai": "AI",
|
||||
"user_button.download_desktop_app": "下載桌面應用程式",
|
||||
"user_button.log_out": "登出",
|
||||
"user_button.power": "Power",
|
||||
"user_button.preferences": "偏好設定",
|
||||
"user_button.profile": "個人檔案",
|
||||
"user_button.wallet": "錢包",
|
||||
"user_profile.about": "關於",
|
||||
"user_profile.close": "關閉",
|
||||
"user_profile.created_lists": "已創建列表",
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
"invitation.earlyAccess": "Folo is currently requires an invitation code to use.",
|
||||
"invitation.earlyAccessMessage": "😰 Sorry, Folo is currently requires an invitation code to use.",
|
||||
"invitation.generateButton": "Generate new code",
|
||||
"invitation.generateCost": "You can spend {{INVITATION_PRICE}} Power to generate an invitation code for your friends.",
|
||||
"invitation.generateCost": "You can generate an invitation code for your friends.",
|
||||
"invitation.getCodeMessage": "You can get an invitation code in the following ways:",
|
||||
"invitation.title": "Invitation Code",
|
||||
"login.backToWebApp": "Back To Web App",
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
"invitation.earlyAccess": "Folo nécessite actuellement un code d'invitation.",
|
||||
"invitation.earlyAccessMessage": "😰 Désolé, Folo nécessite actuellement un code d'invitation pour être utilisé.",
|
||||
"invitation.generateButton": "Générer un nouveau code",
|
||||
"invitation.generateCost": "Vous pouvez dépenser {{INVITATION_PRICE}} Power pour générer un code d'invitation pour vos amis.",
|
||||
"invitation.generateCost": "Vous pouvez générer un code d'invitation pour vos amis.",
|
||||
"invitation.getCodeMessage": "Vous pouvez obtenir un code d'invitation des manières suivantes :",
|
||||
"invitation.title": "Code d'invitation",
|
||||
"login.backToWebApp": "Retour à l'application Web",
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
"invitation.earlyAccess": "現在、Folo はアーリーアクセス中で、利用には招待コードが必要です。",
|
||||
"invitation.earlyAccessMessage": "😰 申し訳ありませんが、Folo は現在アーリーアクセス中で、招待コードが必要です。",
|
||||
"invitation.generateButton": "新しいコードを生成",
|
||||
"invitation.generateCost": "友達のために招待コードを生成するには、{{INVITATION_PRICE}} Power を消費できます。",
|
||||
"invitation.generateCost": "友達のために招待コードを生成できます。",
|
||||
"invitation.getCodeMessage": "以下の方法で招待コードを入手できます:",
|
||||
"invitation.title": "招待コード",
|
||||
"login.backToWebApp": "ウェブアプリに戻る",
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
"invitation.earlyAccess": "Folo 目前处于早期体验阶段,需要邀请码才能使用。",
|
||||
"invitation.earlyAccessMessage": "😰 抱歉,Folo 目前处于早期体验阶段,需要邀请码才能使用。",
|
||||
"invitation.generateButton": "生成邀请码",
|
||||
"invitation.generateCost": "花费 {{INVITATION_PRICE}} Power 生成一个邀请码给你的朋友。",
|
||||
"invitation.generateCost": "你可以为你的朋友生成一个邀请码。",
|
||||
"invitation.getCodeMessage": "通过以下方式获取:",
|
||||
"invitation.title": "邀请码",
|
||||
"login.backToWebApp": "返回网页版",
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
"invitation.earlyAccess": "Folo 目前處於搶先體驗階段,需要邀請碼才能使用。",
|
||||
"invitation.earlyAccessMessage": "😰 抱歉,Folo 目前處於搶先體驗階段,需要邀請碼才能使用。",
|
||||
"invitation.generateButton": "產生新邀請碼",
|
||||
"invitation.generateCost": "您可以花費 {{INVITATION_PRICE}} Power 為您的朋友產生邀請碼。",
|
||||
"invitation.generateCost": "您可以為朋友產生邀請碼。",
|
||||
"invitation.getCodeMessage": "您可以通過以下方式獲取邀請碼:",
|
||||
"invitation.title": "邀請碼",
|
||||
"login.backToWebApp": "返回網頁應用程式",
|
||||
|
|
|
|||
|
|
@ -530,14 +530,14 @@
|
|||
"invitation.confirmModal.cancel": "Cancel",
|
||||
"invitation.confirmModal.confirm": "Do you want to continue?",
|
||||
"invitation.confirmModal.continue": "Continue",
|
||||
"invitation.confirmModal.message": "Generating an invitation code will cost you {{INVITATION_PRICE}} <PowerIcon /> Power.",
|
||||
"invitation.confirmModal.message": "Generating an invitation code will use one invitation quota.",
|
||||
"invitation.confirmModal.title": "Confirm",
|
||||
"invitation.created_at": "Created at",
|
||||
"invitation.earlyAccess": "Folo is currently requires an invitation code to use.",
|
||||
"invitation.earlyAccessMessage": "😰 Sorry, Folo is currently requires an invitation code to use.",
|
||||
"invitation.generate": "Generate",
|
||||
"invitation.generateButton": "Generate New Code",
|
||||
"invitation.generateCost": "You can spend {{INVITATION_PRICE}} <PowerIcon /> Power to generate an invitation code for your friends.",
|
||||
"invitation.generateCost": "You can generate an invitation code for your friends.",
|
||||
"invitation.getCodeMessage": "You can get an invitation code through the following methods:",
|
||||
"invitation.limitationMessage": "Based on your usage time, you can generate up to {{limitation}} invitation codes.",
|
||||
"invitation.newInvitationSuccess": "🎉 New invitation generated, invite code is copied",
|
||||
|
|
@ -737,7 +737,6 @@
|
|||
"rsshub.table.limit_reached": "Limit Reached",
|
||||
"rsshub.table.official": "Official",
|
||||
"rsshub.table.owner": "Owner",
|
||||
"rsshub.table.price": "Monthly Price",
|
||||
"rsshub.table.private": "Private",
|
||||
"rsshub.table.unavailable": "Unavailable",
|
||||
"rsshub.table.unlimited": "Unlimited",
|
||||
|
|
@ -746,11 +745,7 @@
|
|||
"rsshub.table.userLimit": "User Limit",
|
||||
"rsshub.table.yours": "Yours",
|
||||
"rsshub.useModal.about": "About this Instance",
|
||||
"rsshub.useModal.month": "month",
|
||||
"rsshub.useModal.months_label": "The number of months you want to purchase",
|
||||
"rsshub.useModal.purchase_expires_at": "You have purchased this Instance, and your purchase expires at",
|
||||
"rsshub.useModal.title": "RSSHub Instance",
|
||||
"rsshub.useModal.useWith": "Use with {{amount}} <Power />",
|
||||
"spotlight.add_rule": "Add rule",
|
||||
"spotlight.case_sensitive": "Case sensitive",
|
||||
"spotlight.color": "Color",
|
||||
|
|
@ -865,6 +860,7 @@
|
|||
"wallet.withdraw.availableBalance": "You have <Balance></Balance> withdrawable Power in your wallet.",
|
||||
"wallet.withdraw.button": "Withdraw",
|
||||
"wallet.withdraw.error": "Withdrawal failed: {{error}}",
|
||||
"wallet.withdraw.gasFeeNotice": "You are responsible for the Ethereum mainnet gas fee. Make sure this wallet address has enough ETH to submit one transaction before withdrawing: {{address}}.",
|
||||
"wallet.withdraw.modalTitle": "Withdraw Power",
|
||||
"wallet.withdraw.receiveRSS3": "You will receive {{amount}} RSS3",
|
||||
"wallet.withdraw.submitButton": "Submit",
|
||||
|
|
|
|||
|
|
@ -526,14 +526,14 @@
|
|||
"invitation.confirmModal.cancel": "Annuler",
|
||||
"invitation.confirmModal.confirm": "Voulez-vous continuer ?",
|
||||
"invitation.confirmModal.continue": "Continuer",
|
||||
"invitation.confirmModal.message": "Générer un code d'invitation vous coûtera {{INVITATION_PRICE}} <PowerIcon /> Puissance.",
|
||||
"invitation.confirmModal.message": "Générer un code d'invitation utilisera un quota d'invitation.",
|
||||
"invitation.confirmModal.title": "Confirmer",
|
||||
"invitation.created_at": "Créé le",
|
||||
"invitation.earlyAccess": "Folo nécessite actuellement un code d'invitation pour être utilisé.",
|
||||
"invitation.earlyAccessMessage": "😰 Désolé, Folo nécessite actuellement un code d'invitation pour être utilisé.",
|
||||
"invitation.generate": "Générer",
|
||||
"invitation.generateButton": "Générer un nouveau code",
|
||||
"invitation.generateCost": "Vous pouvez dépenser {{INVITATION_PRICE}} <PowerIcon /> Puissance pour générer un code d'invitation pour vos amis.",
|
||||
"invitation.generateCost": "Vous pouvez générer un code d'invitation pour vos amis.",
|
||||
"invitation.getCodeMessage": "Vous pouvez obtenir un code d'invitation via les méthodes suivantes :",
|
||||
"invitation.limitationMessage": "En fonction de votre temps d'utilisation, vous pouvez générer jusqu'à {{limitation}} codes d'invitation.",
|
||||
"invitation.newInvitationSuccess": "🎉 Nouvelle invitation générée, code copié",
|
||||
|
|
@ -719,7 +719,6 @@
|
|||
"rsshub.table.limit_reached": "Limite atteinte",
|
||||
"rsshub.table.official": "Officiel",
|
||||
"rsshub.table.owner": "Propriétaire",
|
||||
"rsshub.table.price": "Prix mensuel",
|
||||
"rsshub.table.private": "Privé",
|
||||
"rsshub.table.unavailable": "Indisponible",
|
||||
"rsshub.table.unlimited": "Illimité",
|
||||
|
|
@ -728,11 +727,7 @@
|
|||
"rsshub.table.userLimit": "Limite d'utilisateurs",
|
||||
"rsshub.table.yours": "Le vôtre",
|
||||
"rsshub.useModal.about": "À propos de cette instance",
|
||||
"rsshub.useModal.month": "mois",
|
||||
"rsshub.useModal.months_label": "Le nombre de mois que vous souhaitez acheter",
|
||||
"rsshub.useModal.purchase_expires_at": "Vous avez acheté cette instance, et votre achat expire le",
|
||||
"rsshub.useModal.title": "Instance RSSHub",
|
||||
"rsshub.useModal.useWith": "Utiliser avec {{amount}} <Power />",
|
||||
"subscription.actions.comingSoon": "Bientôt disponible",
|
||||
"subscription.actions.current": "Plan actuel",
|
||||
"subscription.actions.manage_error": "Une erreur s'est produite lors de l'ouverture de la gestion de l'abonnement.",
|
||||
|
|
@ -830,6 +825,7 @@
|
|||
"wallet.withdraw.availableBalance": "Vous avez <Balance></Balance> puissance retirable dans votre portefeuille.",
|
||||
"wallet.withdraw.button": "Retirer",
|
||||
"wallet.withdraw.error": "Retrait échoué : {{error}}",
|
||||
"wallet.withdraw.gasFeeNotice": "Vous êtes responsable des gas fees du réseau principal Ethereum. Avant le retrait, assurez-vous que cette adresse de portefeuille dispose d'assez d'ETH pour soumettre une transaction : {{address}}.",
|
||||
"wallet.withdraw.modalTitle": "Retirer de la puissance",
|
||||
"wallet.withdraw.receiveRSS3": "Vous recevrez {{amount}} RSS3",
|
||||
"wallet.withdraw.submitButton": "Soumettre",
|
||||
|
|
|
|||
|
|
@ -526,14 +526,14 @@
|
|||
"invitation.confirmModal.cancel": "キャンセル",
|
||||
"invitation.confirmModal.confirm": "続けますか?",
|
||||
"invitation.confirmModal.continue": "続行",
|
||||
"invitation.confirmModal.message": "招待コードを生成するには、{{INVITATION_PRICE}} <PowerIcon /> Power が必要です。",
|
||||
"invitation.confirmModal.message": "招待コードを生成すると招待枠を 1 つ使用します。",
|
||||
"invitation.confirmModal.title": "確認",
|
||||
"invitation.created_at": "作成日",
|
||||
"invitation.earlyAccess": "現在、Folo は<strong>アーリーアクセス</strong>中で、招待コードが必要です。",
|
||||
"invitation.earlyAccessMessage": "😰 申し訳ありません。Folo は現在アーリーアクセス中で、招待コードが必要です。",
|
||||
"invitation.generate": "生成",
|
||||
"invitation.generateButton": "新しいコードを生成",
|
||||
"invitation.generateCost": "{{INVITATION_PRICE}} <PowerIcon /> Power を消費して、友達のために招待コードを生成できます。",
|
||||
"invitation.generateCost": "友達のために招待コードを生成できます。",
|
||||
"invitation.getCodeMessage": "以下の方法で招待コードを取得できます:",
|
||||
"invitation.limitationMessage": "あなたの使用時間に応じて、最大 {{limitation}} 個の招待コードを生成できます。",
|
||||
"invitation.newInvitationSuccess": "🎉 新しい招待コードが生成され、クリップボードにコピーされました",
|
||||
|
|
@ -733,7 +733,6 @@
|
|||
"rsshub.table.limit_reached": "制限に達しました",
|
||||
"rsshub.table.official": "公式",
|
||||
"rsshub.table.owner": "所有者",
|
||||
"rsshub.table.price": "月額の費用",
|
||||
"rsshub.table.private": "プライベート",
|
||||
"rsshub.table.unavailable": "利用不可",
|
||||
"rsshub.table.unlimited": "無制限",
|
||||
|
|
@ -742,11 +741,7 @@
|
|||
"rsshub.table.userLimit": "ユーザー制限",
|
||||
"rsshub.table.yours": "あなたの",
|
||||
"rsshub.useModal.about": "このインスタンスについて",
|
||||
"rsshub.useModal.month": "月",
|
||||
"rsshub.useModal.months_label": "購入したい月数",
|
||||
"rsshub.useModal.purchase_expires_at": "このインスタンスを購入しました、利用期限は",
|
||||
"rsshub.useModal.title": "RSSHub インスタンス",
|
||||
"rsshub.useModal.useWith": "使用する {{amount}} <Power />",
|
||||
"spotlight.add_rule": "ルールを追加",
|
||||
"spotlight.case_sensitive": "大文字と小文字を区別",
|
||||
"spotlight.color": "色",
|
||||
|
|
@ -861,6 +856,7 @@
|
|||
"wallet.withdraw.availableBalance": "引き出し可能な Power は<Balance></Balance>です。",
|
||||
"wallet.withdraw.button": "引き出し",
|
||||
"wallet.withdraw.error": "引き出しに失敗しました:{{error}}",
|
||||
"wallet.withdraw.gasFeeNotice": "Ethereum メインネットの gas fee はご自身で支払う必要があります。引き出し前に、このウォレットアドレスに 1 回のトランザクションを送信できるだけの ETH があることを確認してください: {{address}}。",
|
||||
"wallet.withdraw.modalTitle": "Power を引き出す",
|
||||
"wallet.withdraw.receiveRSS3": "{{amount}} RSS3を受け取ります",
|
||||
"wallet.withdraw.submitButton": "送信",
|
||||
|
|
|
|||
|
|
@ -530,14 +530,14 @@
|
|||
"invitation.confirmModal.cancel": "取消",
|
||||
"invitation.confirmModal.confirm": "确认继续?",
|
||||
"invitation.confirmModal.continue": "继续",
|
||||
"invitation.confirmModal.message": "生成邀请码将花费 {{INVITATION_PRICE}} <PowerIcon>Power</PowerIcon>。",
|
||||
"invitation.confirmModal.message": "生成邀请码将消耗一个邀请码额度。",
|
||||
"invitation.confirmModal.title": "确认",
|
||||
"invitation.created_at": "创建于",
|
||||
"invitation.earlyAccess": "Folo 目前处于<strong>早期开发</strong>状态,需要邀请码才能使用。",
|
||||
"invitation.earlyAccessMessage": "😰 抱歉,Folo 目前处于抢先体验阶段,需要邀请码才能使用。",
|
||||
"invitation.generate": "生成",
|
||||
"invitation.generateButton": "生成邀请码",
|
||||
"invitation.generateCost": "你可以花费 {{INVITATION_PRICE}} <PowerIcon /> Power 为你的朋友生成邀请码。",
|
||||
"invitation.generateCost": "你可以为你的朋友生成一个邀请码。",
|
||||
"invitation.getCodeMessage": "通过以下方式获取邀请码:",
|
||||
"invitation.limitationMessage": "根据你的使用时间,你可以生成最多 {{limitation}} 个邀请码。",
|
||||
"invitation.newInvitationSuccess": "🎉 邀请码已生成,已复制到剪贴板",
|
||||
|
|
@ -737,7 +737,6 @@
|
|||
"rsshub.table.limit_reached": "达到限制",
|
||||
"rsshub.table.official": "官方",
|
||||
"rsshub.table.owner": "所有者",
|
||||
"rsshub.table.price": "月度价格",
|
||||
"rsshub.table.private": "私有",
|
||||
"rsshub.table.unavailable": "不可用",
|
||||
"rsshub.table.unlimited": "无限制",
|
||||
|
|
@ -746,11 +745,7 @@
|
|||
"rsshub.table.userLimit": "用户限制",
|
||||
"rsshub.table.yours": "你的",
|
||||
"rsshub.useModal.about": "关于此实例",
|
||||
"rsshub.useModal.month": "个月",
|
||||
"rsshub.useModal.months_label": "你想购买的月份数量",
|
||||
"rsshub.useModal.purchase_expires_at": "你已购买此实例,到期时间为",
|
||||
"rsshub.useModal.title": "RSSHub 实例",
|
||||
"rsshub.useModal.useWith": "使用 {{amount}} <Power />",
|
||||
"spotlight.add_rule": "添加规则",
|
||||
"spotlight.case_sensitive": "区分大小写",
|
||||
"spotlight.color": "颜色",
|
||||
|
|
@ -865,6 +860,7 @@
|
|||
"wallet.withdraw.availableBalance": "钱包中有 <Balance></Balance> Power 可提现。",
|
||||
"wallet.withdraw.button": "提现",
|
||||
"wallet.withdraw.error": "提现失败:{{error}}",
|
||||
"wallet.withdraw.gasFeeNotice": "你需要自行支付以太坊主网 gas fee。提现前请确保这个钱包地址有足够 ETH 发起一笔交易:{{address}}。",
|
||||
"wallet.withdraw.modalTitle": "提现 Power",
|
||||
"wallet.withdraw.receiveRSS3": "你将收到 {{amount}} RSS3",
|
||||
"wallet.withdraw.submitButton": "提交",
|
||||
|
|
|
|||
|
|
@ -526,14 +526,14 @@
|
|||
"invitation.confirmModal.cancel": "取消",
|
||||
"invitation.confirmModal.confirm": "您想繼續嗎?",
|
||||
"invitation.confirmModal.continue": "繼續",
|
||||
"invitation.confirmModal.message": "產生邀請碼將會花費您 {{INVITATION_PRICE}} <PowerIcon>Power</PowerIcon>。",
|
||||
"invitation.confirmModal.message": "產生邀請碼將使用一個邀請碼額度。",
|
||||
"invitation.confirmModal.title": "確認",
|
||||
"invitation.created_at": "建立者:",
|
||||
"invitation.earlyAccess": "Folo 目前處於<strong>早期開發</strong>狀態,需要邀請碼才能使用。",
|
||||
"invitation.earlyAccessMessage": "😰 抱歉,關注目前處於搶先體驗階段,需要邀請碼才能使用。",
|
||||
"invitation.generate": "產生",
|
||||
"invitation.generateButton": "產生邀請碼",
|
||||
"invitation.generateCost": "您可以花費 {{INVITATION_PRICE}} <PowerIcon>Power</PowerIcon> 為您的朋友產生邀請碼。",
|
||||
"invitation.generateCost": "您可以為朋友產生邀請碼。",
|
||||
"invitation.getCodeMessage": "您可以通過以下方式獲取邀請碼:",
|
||||
"invitation.limitationMessage": "基於您的使用時間,您最多可以產生 {{limitation}} 個邀請碼。",
|
||||
"invitation.newInvitationSuccess": "🎉 邀請碼已產生,邀請碼已複製",
|
||||
|
|
@ -719,7 +719,6 @@
|
|||
"rsshub.table.limit_reached": "達到限制",
|
||||
"rsshub.table.official": "官方",
|
||||
"rsshub.table.owner": "建立者",
|
||||
"rsshub.table.price": "每月價格",
|
||||
"rsshub.table.private": "私人",
|
||||
"rsshub.table.unavailable": "不可用",
|
||||
"rsshub.table.unlimited": "無限制",
|
||||
|
|
@ -728,11 +727,7 @@
|
|||
"rsshub.table.userLimit": "使用者限制",
|
||||
"rsshub.table.yours": "你的",
|
||||
"rsshub.useModal.about": "關於此實例伺服器",
|
||||
"rsshub.useModal.month": "個月",
|
||||
"rsshub.useModal.months_label": "你想購買的月份數量",
|
||||
"rsshub.useModal.purchase_expires_at": "你已購買此實例伺服器,到期時間為",
|
||||
"rsshub.useModal.title": "RSSHub 實例伺服器",
|
||||
"rsshub.useModal.useWith": "使用 {{amount}} <Power />",
|
||||
"subscription.actions.comingSoon": "即將推出",
|
||||
"subscription.actions.current": "目前方案",
|
||||
"subscription.actions.manage_error": "開啟訂閱管理時發生問題。",
|
||||
|
|
@ -830,6 +825,7 @@
|
|||
"wallet.withdraw.availableBalance": "錢包中有 <Balance></Balance> Power 可提領。",
|
||||
"wallet.withdraw.button": "提領",
|
||||
"wallet.withdraw.error": "提領失敗:{{error}}",
|
||||
"wallet.withdraw.gasFeeNotice": "你需要自行支付以太坊主網 gas fee。提領前請確保這個錢包地址有足夠 ETH 發起一筆交易:{{address}}。",
|
||||
"wallet.withdraw.modalTitle": "提領 Power",
|
||||
"wallet.withdraw.receiveRSS3": "你將收到 {{amount}} RSS3",
|
||||
"wallet.withdraw.submitButton": "送出",
|
||||
|
|
|
|||
Loading…
Reference in New Issue