diff --git a/apps/renderer/src/modules/activation/ActivationModalContent.tsx b/apps/renderer/src/modules/activation/ActivationModalContent.tsx index 716322c35b..36217d8759 100644 --- a/apps/renderer/src/modules/activation/ActivationModalContent.tsx +++ b/apps/renderer/src/modules/activation/ActivationModalContent.tsx @@ -18,6 +18,7 @@ import { import { Input } from "~/components/ui/input" import { useCurrentModal } from "~/components/ui/modal" import { getFetchErrorMessage } from "~/lib/error-parser" +import { cn } from "~/lib/utils" import confettiUrl from "~/lottie/confetti.lottie?url" import { auth } from "~/queries/auth" import { useInvitationMutation } from "~/queries/invitations" @@ -26,7 +27,13 @@ const formSchema = z.object({ code: z.string().min(1), }) const absoluteConfettiUrl = new URL(confettiUrl, import.meta.url).href -export const ActivationModalContent = () => { +export const ActivationModalContent = ({ + className, + hideDescription, +}: { + className?: string + hideDescription?: boolean +}) => { const form = useForm>({ resolver: zodResolver(formSchema), }) @@ -64,14 +71,16 @@ export const ActivationModalContent = () => {
( - {t("activation.description")} + {!hideDescription && ( + {t("activation.description")} + )} -
{t("discover.popular")}
+
+ {!hideTitle &&
{t("discover.popular")}
} -
+
{keys.map((key) => ( ))} diff --git a/apps/renderer/src/modules/new-user-guide/atoms.ts b/apps/renderer/src/modules/new-user-guide/atoms.ts deleted file mode 100644 index 2cc5fbd75e..0000000000 --- a/apps/renderer/src/modules/new-user-guide/atoms.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { atom } from "jotai" - -import { createAtomHooks } from "~/lib/jotai" - -export const [ - , - useHaveUsedOtherRSSReaderAtom, - useHaveUsedOtherRSSReader, - , - getHaveUsedOtherRSSReader, - setHaveUsedOtherRSSReader, -] = createAtomHooks(atom(false)) diff --git a/apps/renderer/src/modules/new-user-guide/guide-modal-content.tsx b/apps/renderer/src/modules/new-user-guide/guide-modal-content.tsx index 782b21b1a6..d39ee3c385 100644 --- a/apps/renderer/src/modules/new-user-guide/guide-modal-content.tsx +++ b/apps/renderer/src/modules/new-user-guide/guide-modal-content.tsx @@ -12,16 +12,15 @@ import { mountLottie } from "~/components/ui/lottie-container" import { Markdown } from "~/components/ui/markdown/Markdown" import { useI18n } from "~/hooks/common" import confettiUrl from "~/lottie/confetti.lottie?url" +import { MyWalletSection } from "~/modules/power/my-wallet-section" import { settings } from "~/queries/settings" +import { ActivationModalContent } from "../activation/ActivationModalContent" import { DiscoverImport } from "../discover/import" +import { ProfileSettingForm } from "../profile/profile-setting-form" import { settingSyncQueue } from "../settings/helper/sync-queue" import { LanguageSelector } from "../settings/tabs/general" -import { useHaveUsedOtherRSSReader } from "./atoms" import { BehaviorGuide } from "./steps/behavior" -import { TrendingFeeds } from "./steps/feeds" -import { Introduction } from "./steps/introduction" -import { RookieCheck } from "./steps/rookie" import { RSSHubGuide } from "./steps/rsshub" const containerWidth = 600 @@ -51,7 +50,7 @@ function Intro() { return (
-

{t("new_user_guide.intro.title")}

+

{t("new_user_guide.intro.title")}

{t("new_user_guide.intro.description")}

@@ -73,90 +72,67 @@ export function GuideModalContent({ onClose }: { onClose: () => void }) { const t = useI18n() const [step, setStep] = useState(0) const [direction, setDirection] = useState(1) - const haveUsedOtherRSSReader = useHaveUsedOtherRSSReader() const guideSteps = useMemo( () => [ { - icon: "i-mgc-grid-cute-re", - title: "Features", - content: createElement(Introduction, { - features: [ - { - icon: "i-mgc-magic-2-cute-re", - title: t.settings("titles.actions"), - description: t.app("new_user_guide.step.features.actions.description"), - }, - { - icon: "i-mgc-department-cute-re", - title: t.settings("titles.integration"), - description: t.app("new_user_guide.step.features.integration.description"), - }, - { - icon: "i-mgc-rada-cute-re", - title: t.settings("titles.lists"), - description: t.settings("lists.info"), - }, - { - icon: "i-mgc-hotkey-cute-re", - title: t.settings("titles.shortcuts"), - description: ( -

- {t.app("new_user_guide.step.features.shortcuts.description1")}{" "} - H, - }} - /> -

- ), - }, - ], - }), + title: t.app("new_user_guide.step.migrate.profile"), + content: , + icon: "i-mgc-user-setting-cute-re", }, { - title: "Power", - icon: "i-mgc-power", - content: ( - - {t.app("new_user_guide.step.power.description")} - - ), + title: t.app("new_user_guide.step.activation.title"), + description: t.app("new_user_guide.step.activation.description"), + content: , + icon: "i-mgc-love-cute-re", }, { - title: t.app("new_user_guide.step.start_question.title"), - content: createElement(RookieCheck), - icon: "i-mgc-question-cute-re", + title: t.app("new_user_guide.step.migrate.wallet"), + content: , + icon: , }, - haveUsedOtherRSSReader && { - title: t.app("new_user_guide.step.behavior.title"), + { + title: t.app("new_user_guide.step.behavior.unread_question.content"), + description: t.app("new_user_guide.step.behavior.unread_question.description"), content: createElement(BehaviorGuide), - icon: tw`i-mingcute-cursor-3-line`, + icon: tw`i-mgc-cursor-3-cute-re`, + }, + { + title: t.app("new_user_guide.step.migrate.title"), + content: createElement(DiscoverImport), + icon: "i-mgc-file-import-cute-re", }, { title: t.app("new_user_guide.step.rsshub.title"), + description: t.app("new_user_guide.step.rsshub.info"), content: createElement(RSSHubGuide), icon: , }, - haveUsedOtherRSSReader - ? { - title: t.app("new_user_guide.step.import.title"), - content: createElement(DiscoverImport), - icon: "i-mingcute-file-import-line", - } - : { - title: t.app("new_user_guide.step.trending.title"), - content: createElement(TrendingFeeds), - icon: "i-mgc-trending-up-cute-re", - }, + { + title: t.app("new_user_guide.step.shortcuts.title"), + content: ( +
+

{t.app("new_user_guide.step.shortcuts.description1")}

+

+ H, + }} + /> +

+
+ ), + icon: "i-mgc-hotkey-cute-re", + }, ].filter((i) => !!i) as { title: string icon: React.ReactNode content: FunctionComponentElement + description?: string }[], - [haveUsedOtherRSSReader, t], + [t], ) const totalSteps = useMemo(() => guideSteps.length, [guideSteps]) @@ -179,20 +155,9 @@ export function GuideModalContent({ onClose }: { onClose: () => void }) { return ( - {!!title && ( -

- {typeof guideSteps[step - 1].icon === "string" ? ( - - ) : ( - guideSteps[step - 1].icon - )} - {title} -

- )} - -
+
void }) { x: { type: "spring", stiffness: 300, damping: 30 }, opacity: { duration: 0.1 }, }} - className="mt-20 px-6 pb-24" + className="mt-12 px-20 pb-24" > + {!!title && ( +
+

+ {typeof guideSteps[step - 1].icon === "string" ? ( + + ) : ( + guideSteps[step - 1].icon + )} + {title} +

+ {!!guideSteps[step - 1].description && ( +
+ + {guideSteps[step - 1].description!} + +
+ )} +
+ )} {status === "initial" ? ( ) : status === "active" ? ( @@ -225,7 +209,7 @@ export function GuideModalContent({ onClose }: { onClose: () => void }) { ))}
- {step !== 0 && step <= totalSteps && ( + {step !== 0 && ( -
- - -
- - {t("wallet.balance.withdrawable")} - - - {myWallet.cashablePowerToken} - -
-
- - -

{t("wallet.balance.withdrawableTooltip")}

-
-
-
-
-
- -
- - - - {serverConfigs?.DISABLE_PERSONAL_DAILY_POWER && ( -
- {t("wallet.power.rewardDescription3")} +
+
+ + + ), + }} + /> +
+ + + +
+
+
+ + {BigInt(myWallet.powerToken || 0n)} + +
- )} -
{t("wallet.power.rewardDescription")}
-
- - {BigInt(myWallet.todayDailyPower || 0n)} + + +
+ + {t("wallet.balance.withdrawable")} + + + {myWallet.cashablePowerToken} - ), - Link:
+
+ + +

{t("wallet.balance.withdrawableTooltip")}

+
+
+
+
+
+ +
+
+ + + {serverConfigs?.DISABLE_PERSONAL_DAILY_POWER && ( +
+ {t("wallet.power.rewardDescription3")}
-
-
-
- - -
- - {BigInt(myWallet.todayDailyPower || 0n)} + )} +
{t("wallet.power.rewardDescription")}
+
+ + {BigInt(myWallet.todayDailyPower || 0n)} + + ), + Link:
+
+
+
+ +
- + + {BigInt(myWallet.todayDailyPower || 0n)}
+
- +
) } diff --git a/apps/renderer/src/modules/profile/profile-setting-form.tsx b/apps/renderer/src/modules/profile/profile-setting-form.tsx index 0a299a6690..5853a718e0 100644 --- a/apps/renderer/src/modules/profile/profile-setting-form.tsx +++ b/apps/renderer/src/modules/profile/profile-setting-form.tsx @@ -20,6 +20,7 @@ import { import { Input } from "~/components/ui/input" import { apiClient } from "~/lib/api-fetch" import { toastFetchError } from "~/lib/error-parser" +import { cn } from "~/lib/utils" const formSchema = z.object({ handle: z.string().max(50), @@ -27,7 +28,13 @@ const formSchema = z.object({ image: z.string().url(), }) -export const ProfileSettingForm = () => { +export const ProfileSettingForm = ({ + className, + buttonClassName, +}: { + className?: string + buttonClassName?: string +}) => { const { t } = useTranslation("settings") const user = useWhoami() @@ -64,7 +71,7 @@ export const ProfileSettingForm = () => { return ( - + { )} /> -
+
diff --git a/icons/mgc/cursor_3_cute_re.svg b/icons/mgc/cursor_3_cute_re.svg new file mode 100644 index 0000000000..84f7fba7a8 --- /dev/null +++ b/icons/mgc/cursor_3_cute_re.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/locales/app/en.json b/locales/app/en.json index 6721900499..f64bc51acc 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -181,23 +181,33 @@ "new_user_guide.intro.title": "Welcome to Follow!", "new_user_guide.outro.description": "You have completed the guide. Enjoy your journey!", "new_user_guide.outro.title": "You're all set!", + "new_user_guide.step.activation.description": "Don't worry, you can continue to use Follow without an invitation code.", + "new_user_guide.step.activation.title": "Activate your account", + "new_user_guide.step.automation.description": "- Follow leverages advanced AI to assist your operations.\n- Action rules allow you to automate various actions on sources that meet specific conditions.\n- Integrations allow you to save entries to other services.", "new_user_guide.step.behavior.title": "Behavior", - "new_user_guide.step.behavior.unread_question.content": "How do you feel about unread entries?", - "new_user_guide.step.behavior.unread_question.option1": "I don't really care about unread.", - "new_user_guide.step.behavior.unread_question.option2": "I want to completely control the unread status.", + "new_user_guide.step.behavior.unread_question.content": "Select how you would like to mark as read.", + "new_user_guide.step.behavior.unread_question.description": "Don't worry, you can also change it later in the preferences.", + "new_user_guide.step.behavior.unread_question.option1": "Radical: Automatically marked as read when displayed.", + "new_user_guide.step.behavior.unread_question.option2": "Balanced: Automatically marked as read when hovered over or scrolled out of view.", + "new_user_guide.step.behavior.unread_question.option3": "Conservative: Marked as read only when clicked.", "new_user_guide.step.features.actions.description": "Action rules allow you to perform different actions for different feeds.\n- Using AI to summarize or translate.\n- Configure how to read entries.\n- Enable notifications for new entries or silence them.\n- Rewrite or block specific entries.\n- Send new entries to a webhook address.", "new_user_guide.step.features.integration.description": "Integrations allow you to save entries to other services. Currently supported services are:\n- Eagle\n- Readwise\n- Instapaper\n- Obsidian", - "new_user_guide.step.features.shortcuts.description1": "Shortcut keys can help you operate Follow more conveniently and efficiently.", - "new_user_guide.step.features.shortcuts.description2": "You can quickly view all shortcut keys by pressing .", - "new_user_guide.step.import.title": "Import", - "new_user_guide.step.power.description": "- Power is an ERC-20 token on the VSL blockchain.\n- 20 free Power can be claimed every day.\n- Power can be used to tip feeds on Follow, claim your feeds to receive tips.", - "new_user_guide.step.rsshub.info": "[RSSHub](https://docs.rsshub.app) is the world's largest RSS Network, and Follow is deeply integrated with it. You can subscribe to RSSHub's routes in Follow by filling in the required parameters.", - "new_user_guide.step.rsshub.title": "RSSHub", + "new_user_guide.step.migrate.profile": "Setup your profile", + "new_user_guide.step.migrate.title": "Migrate from OPML file", + "new_user_guide.step.migrate.wallet": "Check your wallet", + "new_user_guide.step.power.description": "Follow uses blockchain technology as an incentive mechanism for active users and outstanding creators. Users can obtain more services and benefits by holding and using Power Token. Creators can obtain more rewards by providing high-quality content and services.", + "new_user_guide.step.rsshub.info": "Everything is RSSible. Our [RSSHub](https://github.com/DIYgod/RSSHub) community, comprising over 1,000 developers, has spent six years adapting nearly a thousand websites to provide almost all the content you need. This includes platforms like X (Twitter), Instagram, PlayStation, Spotify, Telegram, YouTube, and more. You can also write your own scripts to adapt additional websites.", + "new_user_guide.step.rsshub.title": "Subscribe from RSSHub", + "new_user_guide.step.shortcuts.description1": "Shortcut keys allow you to use Follow more conveniently and efficiently.", + "new_user_guide.step.shortcuts.description2": "Press to quickly view all shortcut keys at any time.", + "new_user_guide.step.shortcuts.title": "Shortcuts", "new_user_guide.step.start_question.content": "Have you used other RSS readers before?", "new_user_guide.step.start_question.option1": "Yes, I have used other RSS readers.", "new_user_guide.step.start_question.option2": "No, this is my first time using an RSS reader.", "new_user_guide.step.start_question.title": "Question", "new_user_guide.step.trending.title": "Popular Feeds", + "new_user_guide.step.views.description": "Follow uses different views for various types of content to offer an experience equal to or better than the original platform", + "new_user_guide.step.views.title": "Views", "notify.unSupportDisplay": "Some websites can't be displayed here. Download desktop app to view it.", "notify.unSupportWidth": "{{app_name}} is not yet supported on mobile devices", "notify.unSupportWidth_1": "Your device width is {{width}}, which is less than the minimum supported width {{minWidth}}.", @@ -230,7 +240,6 @@ "search.placeholder": "Search...", "search.result_count_local_mode": "(Local mode)", "search.tooltip.local_search": "This search covers locally available data. Try a Refetch to include the latest data.", - "shortcuts.guide.title": "Shortcuts Guideline", "sidebar.add_more_feeds": "Add more feeds", "sidebar.category_remove_dialog.cancel": "Cancel", "sidebar.category_remove_dialog.continue": "Continue",