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

Remove API

+13 -249
-2
apps/mobile/components/Shared/SinglePost/PostBody.tsx
··· 9 9 interface PostBodyProps { 10 10 contentClassName?: string; 11 11 post: AnyPostFragment; 12 - quoted?: boolean; 13 12 showMore?: boolean; 14 13 } 15 14 16 15 const PostBody = ({ 17 16 contentClassName = "", 18 17 post, 19 - quoted = false, 20 18 showMore = false 21 19 }: PostBodyProps) => { 22 20 const targetPost = isRepost(post) ? post.repostOf : post;
+1 -3
apps/mobile/components/Shared/SinglePost/index.tsx
··· 8 8 timelineItem?: TimelineItemFragment; 9 9 post: AnyPostFragment; 10 10 showMore?: boolean; 11 - showType?: boolean; 12 11 } 13 12 14 13 const SinglePost = ({ 15 14 timelineItem, 16 15 post, 17 - showMore = true, 18 - showType = true 16 + showMore = true 19 17 }: SinglePostProps) => { 20 18 const rootPost = timelineItem ? timelineItem?.primary : post; 21 19
+1 -3
apps/web/src/components/Comment/CommentFeed.tsx
··· 66 66 hasMore={hasMore} 67 67 items={filteredComments} 68 68 loading={loading} 69 - renderItem={(comment) => ( 70 - <SinglePost key={comment.id} post={comment} showType={false} /> 71 - )} 69 + renderItem={(comment) => <SinglePost key={comment.id} post={comment} />} 72 70 /> 73 71 ); 74 72 };
+1 -1
apps/web/src/components/Comment/NoneRelevantFeed.tsx
··· 93 93 hasMore={hasMore} 94 94 items={filteredComments} 95 95 renderItem={(comment) => ( 96 - <SinglePost key={comment.id} post={comment} showType={false} /> 96 + <SinglePost key={comment.id} post={comment} /> 97 97 )} 98 98 /> 99 99 ) : null}
-3
apps/web/src/components/Common/Layout.tsx
··· 16 16 import { useTheme } from "@/hooks/useTheme"; 17 17 import { useAccountStore } from "@/store/persisted/useAccountStore"; 18 18 import { hydrateAuthTokens, signOut } from "@/store/persisted/useAuthStore"; 19 - import { usePreferencesStore } from "@/store/persisted/usePreferencesStore"; 20 19 import { useProStore } from "@/store/persisted/useProStore"; 21 20 import ReloadTabsWatcher from "./ReloadTabsWatcher"; 22 21 ··· 25 24 const { theme } = useTheme(); 26 25 const { currentAccount, setCurrentAccount } = useAccountStore(); 27 26 const { setProBannerDismissed } = useProStore(); 28 - const { resetPreferences } = usePreferencesStore(); 29 27 const isMounted = useIsClient(); 30 28 const { accessToken } = hydrateAuthTokens(); 31 29 ··· 35 33 }, [pathname]); 36 34 37 35 const onError = useCallback(() => { 38 - resetPreferences(); 39 36 signOut(); 40 37 reloadAllTabs(); 41 38 }, []);
-32
apps/web/src/components/Common/Providers/PreferencesProvider.tsx
··· 1 - import { useQuery } from "@tanstack/react-query"; 2 - import type { ReactNode } from "react"; 3 - import { useEffect } from "react"; 4 - import { hono } from "@/helpers/fetcher"; 5 - import { useAccountStore } from "@/store/persisted/useAccountStore"; 6 - import { usePreferencesStore } from "@/store/persisted/usePreferencesStore"; 7 - 8 - interface PreferencesProviderProps { 9 - children: ReactNode; 10 - } 11 - 12 - const PreferencesProvider = ({ children }: PreferencesProviderProps) => { 13 - const { currentAccount } = useAccountStore(); 14 - const { setAppIcon, setIncludeLowScore } = usePreferencesStore(); 15 - 16 - const { data: preferences } = useQuery({ 17 - enabled: Boolean(currentAccount?.address), 18 - queryFn: () => hono.preferences.get(), 19 - queryKey: ["preferences", currentAccount?.address] 20 - }); 21 - 22 - useEffect(() => { 23 - if (preferences) { 24 - setIncludeLowScore(preferences.includeLowScore); 25 - setAppIcon(preferences.appIcon); 26 - } 27 - }, [preferences]); 28 - 29 - return <>{children}</>; 30 - }; 31 - 32 - export default PreferencesProvider;
+3 -6
apps/web/src/components/Common/Providers/index.tsx
··· 6 6 import ErrorBoundary from "@/components/Common/ErrorBoundary"; 7 7 import authLink from "@/helpers/authLink"; 8 8 import { ThemeProvider } from "@/hooks/useTheme"; 9 - import PreferencesProvider from "./PreferencesProvider"; 10 9 import Web3Provider from "./Web3Provider"; 11 10 12 11 export const queryClient = new QueryClient({ ··· 25 24 <QueryClientProvider client={queryClient}> 26 25 <Web3Provider> 27 26 <ApolloProvider client={lensApolloClient}> 28 - <PreferencesProvider> 29 - <HelmetProvider> 30 - <ThemeProvider>{children}</ThemeProvider> 31 - </HelmetProvider> 32 - </PreferencesProvider> 27 + <HelmetProvider> 28 + <ThemeProvider>{children}</ThemeProvider> 29 + </HelmetProvider> 33 30 </ApolloProvider> 34 31 </Web3Provider> 35 32 </QueryClientProvider>
+1 -1
apps/web/src/components/Composer/Actions/CollectSettings/SplitConfig.tsx
··· 64 64 if (i === index) { 65 65 return { 66 66 ...recipient, 67 - [type]: type === "address" ? value : Number.parseInt(value) 67 + [type]: type === "address" ? value : Number.parseInt(value, 10) 68 68 }; 69 69 } 70 70 return recipient;
+1 -3
apps/web/src/components/Notification/List.tsx
··· 19 19 import cn from "@/helpers/cn"; 20 20 import useLoadMoreOnIntersect from "@/hooks/useLoadMoreOnIntersect"; 21 21 import { useNotificationStore } from "@/store/persisted/useNotificationStore"; 22 - import { usePreferencesStore } from "@/store/persisted/usePreferencesStore"; 23 22 import NotificationShimmer from "./Shimmer"; 24 23 import TokenDistributedNotification from "./Type/TokenDistributedNotification"; 25 24 ··· 40 39 } 41 40 42 41 const List = ({ feedType }: ListProps) => { 43 - const { includeLowScore } = usePreferencesStore(); 44 42 const { setLastSeenNotificationId } = useNotificationStore(); 45 43 46 44 const getNotificationType = useCallback(() => { ··· 64 62 65 63 const request: NotificationRequest = { 66 64 filter: { 67 - includeLowScore, 65 + includeLowScore: true, 68 66 notificationTypes: getNotificationType() 69 67 } 70 68 };
+1 -1
apps/web/src/components/Post/QuotedPost.tsx
··· 40 40 {post.isDeleted ? ( 41 41 <HiddenPost type={post.__typename} /> 42 42 ) : ( 43 - <PostBody post={post} quoted showMore /> 43 + <PostBody post={post} showMore /> 44 44 )} 45 45 </PostWrapper> 46 46 );
+1 -1
apps/web/src/components/Post/Quotes.tsx
··· 64 64 <div className="virtual-divider-list-window"> 65 65 <WindowVirtualizer> 66 66 {quotes.map((quote) => ( 67 - <SinglePost key={quote.id} post={quote} showType={false} /> 67 + <SinglePost key={quote.id} post={quote} /> 68 68 ))} 69 69 {hasMore && <span ref={loadMoreRef} />} 70 70 </WindowVirtualizer>
-75
apps/web/src/components/Settings/Preferences/AppIcon.tsx
··· 1 - import { CheckCircleIcon as CheckCircleIconOutline } from "@heroicons/react/24/outline"; 2 - import { CheckCircleIcon as CheckCircleIconSolid } from "@heroicons/react/24/solid"; 3 - import { STATIC_IMAGES_URL } from "@hey/data/constants"; 4 - import { useMutation } from "@tanstack/react-query"; 5 - import { toast } from "sonner"; 6 - import ProFeatureNotice from "@/components/Shared/ProFeatureNotice"; 7 - import { Image, Tooltip } from "@/components/Shared/UI"; 8 - import errorToast from "@/helpers/errorToast"; 9 - import { hono } from "@/helpers/fetcher"; 10 - import { useAccountStore } from "@/store/persisted/useAccountStore"; 11 - import { usePreferencesStore } from "@/store/persisted/usePreferencesStore"; 12 - 13 - const icons = [ 14 - { id: 0, name: "Default" }, 15 - { id: 1, name: "Pride" }, 16 - { id: 2, name: "Emerald" }, 17 - { id: 3, name: "Indigo" }, 18 - { id: 4, name: "Violet" } 19 - ]; 20 - 21 - const AppIcon = () => { 22 - const { currentAccount } = useAccountStore(); 23 - const { appIcon, setAppIcon } = usePreferencesStore(); 24 - 25 - const { mutate, isPending } = useMutation({ 26 - mutationFn: ({ appIcon }: { appIcon: number }) => 27 - hono.preferences.update({ appIcon }), 28 - onError: errorToast, 29 - onSuccess: (data) => { 30 - setAppIcon(data.appIcon ?? 0); 31 - toast.success("App icon updated"); 32 - } 33 - }); 34 - 35 - const handleSelectIcon = (iconId: number) => { 36 - mutate({ appIcon: iconId }); 37 - }; 38 - 39 - if (!currentAccount?.hasSubscribed) { 40 - return <ProFeatureNotice className="m-5" feature="custom app icons" />; 41 - } 42 - 43 - return ( 44 - <div className="m-5 flex flex-col gap-y-5"> 45 - <b>Choose App Icon</b> 46 - <div className="flex flex-wrap items-center gap-x-8"> 47 - {icons.map((icon) => ( 48 - <Tooltip content={icon.name} key={icon.id} placement="top"> 49 - <button 50 - className="flex flex-col items-center space-y-2" 51 - disabled={isPending} 52 - onClick={() => handleSelectIcon(icon.id)} 53 - type="button" 54 - > 55 - <Image 56 - alt={icon.name} 57 - className="size-10" 58 - height={40} 59 - src={`${STATIC_IMAGES_URL}/app-icon/${icon.id}.png`} 60 - width={40} 61 - /> 62 - {icon.id === appIcon ? ( 63 - <CheckCircleIconSolid className="size-5 text-green-600" /> 64 - ) : ( 65 - <CheckCircleIconOutline className="size-5 text-gray-500 dark:text-gray-200" /> 66 - )} 67 - </button> 68 - </Tooltip> 69 - ))} 70 - </div> 71 - </div> 72 - ); 73 - }; 74 - 75 - export default AppIcon;
-36
apps/web/src/components/Settings/Preferences/IncludeLowScore.tsx
··· 1 - import { SwatchIcon } from "@heroicons/react/24/outline"; 2 - import { useMutation } from "@tanstack/react-query"; 3 - import { toast } from "sonner"; 4 - import ToggleWithHelper from "@/components/Shared/ToggleWithHelper"; 5 - import errorToast from "@/helpers/errorToast"; 6 - import { hono } from "@/helpers/fetcher"; 7 - import { usePreferencesStore } from "@/store/persisted/usePreferencesStore"; 8 - 9 - const IncludeLowScore = () => { 10 - const { includeLowScore, setIncludeLowScore } = usePreferencesStore(); 11 - 12 - const { mutate, isPending } = useMutation({ 13 - mutationFn: ({ includeLowScore }: { includeLowScore: boolean }) => 14 - hono.preferences.update({ includeLowScore }), 15 - onError: errorToast, 16 - onSuccess: (data) => { 17 - setIncludeLowScore(data.includeLowScore); 18 - toast.success("Notification preference updated"); 19 - } 20 - }); 21 - 22 - return ( 23 - <div className="m-5"> 24 - <ToggleWithHelper 25 - description="Turn on low-signal notification filter" 26 - disabled={isPending} 27 - heading="Notification Signal filter" 28 - icon={<SwatchIcon className="size-5" />} 29 - on={includeLowScore} 30 - setOn={() => mutate({ includeLowScore: !includeLowScore })} 31 - /> 32 - </div> 33 - ); 34 - }; 35 - 36 - export default IncludeLowScore;
-31
apps/web/src/components/Settings/Preferences/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 { Card, CardHeader } from "@/components/Shared/UI"; 5 - import { useAccountStore } from "@/store/persisted/useAccountStore"; 6 - import AppIcon from "./AppIcon"; 7 - import IncludeLowScore from "./IncludeLowScore"; 8 - 9 - const PreferencesSettings = () => { 10 - const { currentAccount } = useAccountStore(); 11 - 12 - if (!currentAccount) { 13 - return <NotLoggedIn />; 14 - } 15 - 16 - return ( 17 - <PageLayout title="Preferences settings"> 18 - <Card> 19 - <CardHeader 20 - icon={<BackButton path="/settings" />} 21 - title="Preferences" 22 - /> 23 - <IncludeLowScore /> 24 - <div className="divider" /> 25 - <AppIcon /> 26 - </Card> 27 - </PageLayout> 28 - ); 29 - }; 30 - 31 - export default PreferencesSettings;
-6
apps/web/src/components/Settings/index.tsx
··· 1 1 import { 2 - AdjustmentsVerticalIcon, 3 2 ArrowRightIcon, 4 3 AtSymbolIcon, 5 4 CodeBracketIcon, ··· 52 51 icon: <AtSymbolIcon className="size-5" />, 53 52 title: "Username", 54 53 url: "/settings/username" 55 - }, 56 - { 57 - icon: <AdjustmentsVerticalIcon className="size-5" />, 58 - title: "Preferences", 59 - url: "/settings/preferences" 60 54 }, 61 55 { 62 56 icon: <FingerPrintIcon className="size-5" />,
-4
apps/web/src/components/Shared/Navbar/NavItems/Logout.tsx
··· 3 3 import errorToast from "@/helpers/errorToast"; 4 4 import reloadAllTabs from "@/helpers/reloadAllTabs"; 5 5 import { signOut } from "@/store/persisted/useAuthStore"; 6 - import { usePreferencesStore } from "@/store/persisted/usePreferencesStore"; 7 6 8 7 interface LogoutProps { 9 8 className?: string; ··· 11 10 } 12 11 13 12 const Logout = ({ className = "", onClick }: LogoutProps) => { 14 - const { resetPreferences } = usePreferencesStore(); 15 - 16 13 const handleLogout = async () => { 17 14 try { 18 - resetPreferences(); 19 15 signOut(); 20 16 reloadAllTabs(); 21 17 } catch (error) {
+1 -3
apps/web/src/components/Shared/Navbar/index.tsx
··· 21 21 import useHasNewNotifications from "@/hooks/useHasNewNotifications"; 22 22 import { useAuthModalStore } from "@/store/non-persisted/modal/useAuthModalStore"; 23 23 import { useAccountStore } from "@/store/persisted/useAccountStore"; 24 - import { usePreferencesStore } from "@/store/persisted/usePreferencesStore"; 25 24 import SignedAccount from "./SignedAccount"; 26 25 27 26 const navigationItems = { ··· 96 95 const Navbar = () => { 97 96 const { pathname } = useLocation(); 98 97 const { currentAccount } = useAccountStore(); 99 - const { appIcon } = usePreferencesStore(); 100 98 const { setShowAuthModal } = useAuthModalStore(); 101 99 102 100 const handleLogoClick = useCallback( ··· 120 118 alt="Logo" 121 119 className="size-8" 122 120 height={32} 123 - src={`${STATIC_IMAGES_URL}/app-icon/${appIcon}.png`} 121 + src={`${STATIC_IMAGES_URL}/app-icon/0.png`} 124 122 width={32} 125 123 /> 126 124 </Link>
+1 -12
apps/web/src/helpers/fetcher.ts
··· 1 1 import { HEY_API_URL } from "@hey/data/constants"; 2 2 import { Status } from "@hey/data/enums"; 3 - import type { AppStatus, Oembed, Preferences, STS } from "@hey/types/api"; 3 + import type { AppStatus, Oembed, STS } from "@hey/types/api"; 4 4 import { hydrateAuthTokens } from "@/store/persisted/useAuthStore"; 5 5 import { isTokenExpiringSoon, refreshTokens } from "./tokenManager"; 6 6 ··· 81 81 oembed: { 82 82 get: (url: string): Promise<Oembed> => { 83 83 return fetchApi<Oembed>(`/oembed/get?url=${url}`, { method: "GET" }); 84 - } 85 - }, 86 - preferences: { 87 - get: (): Promise<Preferences> => { 88 - return fetchApi<Preferences>("/preferences/get", { method: "GET" }); 89 - }, 90 - update: (preferences: Partial<Preferences>): Promise<Preferences> => { 91 - return fetchApi<Preferences>("/preferences/update", { 92 - body: JSON.stringify(preferences), 93 - method: "POST" 94 - }); 95 84 } 96 85 } 97 86 };
+1 -1
apps/web/src/hooks/usePostMetadata.tsx
··· 83 83 }), 84 84 video: { 85 85 cover: videoThumbnail.url, 86 - duration: Number.parseInt(videoDurationInSeconds), 86 + duration: Number.parseInt(videoDurationInSeconds, 10), 87 87 item: primaryAttachment.uri, 88 88 type: primaryAttachment.mimeType, 89 89 ...(license && { license })
-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 PreferencesSettings from "@/components/Settings/Preferences"; 29 28 import SessionsSettings from "@/components/Settings/Sessions"; 30 29 import UsernameSettings from "@/components/Settings/Username"; 31 30 import Custom404 from "@/components/Shared/404"; ··· 74 73 <Route element={<DeveloperSettings />} path="developer" /> 75 74 <Route element={<FundsSettings />} path="funds" /> 76 75 <Route element={<ManagerSettings />} path="manager" /> 77 - <Route element={<PreferencesSettings />} path="preferences" /> 78 76 <Route element={<SessionsSettings />} path="sessions" /> 79 77 <Route element={<UsernameSettings />} path="username" /> 80 78 </Route>
-23
apps/web/src/store/persisted/usePreferencesStore.ts
··· 1 - import { Localstorage } from "@hey/data/storage"; 2 - import { createPersistedTrackedStore } from "@/store/createTrackedStore"; 3 - 4 - interface State { 5 - appIcon: number; 6 - includeLowScore: boolean; 7 - resetPreferences: () => void; 8 - setAppIcon: (appIcon: number) => void; 9 - setIncludeLowScore: (includeLowScore: boolean) => void; 10 - } 11 - 12 - const { useStore: usePreferencesStore } = createPersistedTrackedStore<State>( 13 - (set) => ({ 14 - appIcon: 0, 15 - includeLowScore: false, 16 - resetPreferences: () => set(() => ({ includeLowScore: false })), 17 - setAppIcon: (appIcon) => set(() => ({ appIcon })), 18 - setIncludeLowScore: (includeLowScore) => set(() => ({ includeLowScore })) 19 - }), 20 - { name: Localstorage.PreferencesStore } 21 - ); 22 - 23 - export { usePreferencesStore };