Hey is a decentralized and permissionless social media app built with Lens Protocol 🌿

feat: add Pro settings route and icon to AccountSettings for enhanced user options

yoginth.com 9b7130ff bd44f6a7

verified
+124 -1
+83
apps/web/src/components/Settings/Pro/DefaultToNameSetting.tsx
··· 1 + import { PERMISSIONS } from "@hey/data/constants"; 2 + import { useJoinGroupMutation, useLeaveGroupMutation } from "@hey/indexer"; 3 + import type { ApolloClientError } from "@hey/types/errors"; 4 + import { useCallback, useState } from "react"; 5 + import ToggleWithHelper from "@/components/Shared/ToggleWithHelper"; 6 + import errorToast from "@/helpers/errorToast"; 7 + import useTransactionLifecycle from "@/hooks/useTransactionLifecycle"; 8 + import useWaitForTransactionToComplete from "@/hooks/useWaitForTransactionToComplete"; 9 + import { useAccountStore } from "@/store/persisted/useAccountStore"; 10 + 11 + const DefaultToNameSetting = () => { 12 + const { currentAccount } = useAccountStore(); 13 + const [isSubmitting, setIsSubmitting] = useState(false); 14 + const handleTransactionLifecycle = useTransactionLifecycle(); 15 + const waitForTransactionToComplete = useWaitForTransactionToComplete(); 16 + 17 + const onCompleted = async (hash: string) => { 18 + await waitForTransactionToComplete(hash); 19 + location.reload(); 20 + }; 21 + 22 + const onError = useCallback((error: ApolloClientError) => { 23 + errorToast(error); 24 + }, []); 25 + 26 + const [joinGroup] = useJoinGroupMutation({ 27 + onCompleted: async ({ joinGroup }) => { 28 + if (joinGroup.__typename === "JoinGroupResponse") { 29 + return await onCompleted(joinGroup.hash); 30 + } 31 + 32 + return await handleTransactionLifecycle({ 33 + onCompleted, 34 + onError, 35 + transactionData: joinGroup 36 + }); 37 + }, 38 + onError 39 + }); 40 + 41 + const [leaveGroup] = useLeaveGroupMutation({ 42 + onCompleted: async ({ leaveGroup }) => { 43 + if (leaveGroup.__typename === "LeaveGroupResponse") { 44 + return await onCompleted(leaveGroup.hash); 45 + } 46 + 47 + return await handleTransactionLifecycle({ 48 + onCompleted, 49 + onError, 50 + transactionData: leaveGroup 51 + }); 52 + }, 53 + onError 54 + }); 55 + 56 + if (!currentAccount) { 57 + return null; 58 + } 59 + 60 + const togglePreferName = async () => { 61 + setIsSubmitting(true); 62 + 63 + const variables = { request: { group: PERMISSIONS.PREFER_NAME_IN_FEED } }; 64 + 65 + if (currentAccount?.preferNameInFeed) { 66 + return await leaveGroup({ variables }); 67 + } 68 + 69 + return await joinGroup({ variables }); 70 + }; 71 + 72 + return ( 73 + <ToggleWithHelper 74 + description="Show display names instead of usernames across the feeds in Hey" 75 + disabled={isSubmitting} 76 + heading="Prefer display names" 77 + on={currentAccount?.preferNameInFeed} 78 + setOn={togglePreferName} 79 + /> 80 + ); 81 + }; 82 + 83 + export default DefaultToNameSetting;
+32
apps/web/src/components/Settings/Pro/index.tsx
··· 1 + import BackButton from "@/components/Shared/BackButton"; 2 + import NotLoggedIn from "@/components/Shared/NotLoggedIn"; 3 + import PageLayout from "@/components/Shared/PageLayout"; 4 + import ProFeatureNotice from "@/components/Shared/ProFeatureNotice"; 5 + import { Card, CardHeader } from "@/components/Shared/UI"; 6 + import { useAccountStore } from "@/store/persisted/useAccountStore"; 7 + import DefaultToNameSetting from "./DefaultToNameSetting"; 8 + 9 + const ProSettings = () => { 10 + const { currentAccount } = useAccountStore(); 11 + 12 + if (!currentAccount) { 13 + return <NotLoggedIn />; 14 + } 15 + 16 + return ( 17 + <PageLayout title="Pro settings"> 18 + <Card> 19 + <CardHeader icon={<BackButton path="/settings" />} title="Pro" /> 20 + {currentAccount.hasSubscribed ? ( 21 + <div className="space-y-4 p-5"> 22 + <DefaultToNameSetting /> 23 + </div> 24 + ) : ( 25 + <ProFeatureNotice className="m-5" feature="pro settings" /> 26 + )} 27 + </Card> 28 + </PageLayout> 29 + ); 30 + }; 31 + 32 + export default ProSettings;
+7 -1
apps/web/src/components/Settings/index.tsx
··· 8 8 GiftIcon, 9 9 GlobeAltIcon, 10 10 NoSymbolIcon, 11 - PaintBrushIcon 11 + PaintBrushIcon, 12 + SparklesIcon 12 13 } from "@heroicons/react/24/outline"; 13 14 import type { AccountFragment } from "@hey/indexer"; 14 15 import { Link } from "react-router"; ··· 36 37 icon: <CurrencyDollarIcon className="size-5" />, 37 38 title: "Monetize", 38 39 url: "/settings/monetize" 40 + }, 41 + { 42 + icon: <SparklesIcon className="size-5" />, 43 + title: "Pro", 44 + url: "/settings/pro" 39 45 }, 40 46 { 41 47 icon: <GiftIcon className="size-5" />,
+2
apps/web/src/routes.tsx
··· 25 25 import ManagerSettings from "@/components/Settings/Manager"; 26 26 import { default as AccountMonetizeSettings } from "@/components/Settings/Monetize"; 27 27 import { default as AccountPersonalizeSettings } from "@/components/Settings/Personalize"; 28 + import ProSettings from "@/components/Settings/Pro"; 28 29 import SessionsSettings from "@/components/Settings/Sessions"; 29 30 import UsernameSettings from "@/components/Settings/Username"; 30 31 import Custom404 from "@/components/Shared/404"; ··· 67 68 path="personalize" 68 69 /> 69 70 <Route element={<AccountMonetizeSettings />} path="monetize" /> 71 + <Route element={<ProSettings />} path="pro" /> 70 72 <Route element={<RewardsSettings />} path="rewards" /> 71 73 <Route element={<BlockedSettings />} path="blocked" /> 72 74 <Route element={<DeveloperSettings />} path="developer" />