From cc012098985cf8a9a64cce0ab0b3251275ab36be Mon Sep 17 00:00:00 2001 From: DIYgod Date: Tue, 25 Apr 2023 20:55:14 +0100 Subject: [PATCH] feat: filter out the already followed users before following all --- src/components/common/FollowAllButton.tsx | 64 +++++++++++++++++++++++ src/components/main/MainSidebar.tsx | 50 ++++-------------- src/models/site.model.ts | 34 ++++++++++++ src/pages/index.tsx | 50 +++++------------- 4 files changed, 121 insertions(+), 77 deletions(-) create mode 100644 src/components/common/FollowAllButton.tsx diff --git a/src/components/common/FollowAllButton.tsx b/src/components/common/FollowAllButton.tsx new file mode 100644 index 00000000..779c9fa4 --- /dev/null +++ b/src/components/common/FollowAllButton.tsx @@ -0,0 +1,64 @@ +import { useTranslation } from "next-i18next" +import { useState } from "react" + +import { useAccountState } from "@crossbell/connect-kit" +import { useRefCallback } from "@crossbell/util-hooks" + +import { Button } from "~/components/ui/Button" +import { getSubscriptionsFromList } from "~/models/site.model" +import { useSubscribeToSites } from "~/queries/site" + +export const FollowAllButton: React.FC<{ + size?: "sm" | "xl" + characterIds?: number[] + siteIds?: string[] + className?: string +}> = ({ size, characterIds = [], siteIds = [], className }) => { + const subscribeToSites = useSubscribeToSites() + const { t } = useTranslation("index") + const account = useAccountState((s) => s.computed.account) + const [noMore, setNoMore] = useState(false) + + const doSubscribeToSites = useRefCallback(() => { + if (account?.characterId) { + getSubscriptionsFromList(characterIds, account.characterId).then( + (res) => { + const list = characterIds.filter((id) => !res.includes(id)) + if (list.length) { + subscribeToSites.mutate({ + characterIds: list, + siteIds: siteIds, + } as any) + } else { + setNoMore(true) + } + }, + ) + } else { + subscribeToSites.mutate({ + characterIds: characterIds, + siteIds: siteIds, + } as any) + } + }) + + const followAll = () => { + doSubscribeToSites() + } + + return ( + + ) +} diff --git a/src/components/main/MainSidebar.tsx b/src/components/main/MainSidebar.tsx index 2b5d2854..41b9254c 100644 --- a/src/components/main/MainSidebar.tsx +++ b/src/components/main/MainSidebar.tsx @@ -1,43 +1,20 @@ import { useTranslation } from "next-i18next" import { useState } from "react" -import { useRefCallback } from "@crossbell/util-hooks" - import { CharacterFloatCard } from "~/components/common/CharacterFloatCard" import { SearchInput } from "~/components/common/SearchInput" -import { Button } from "~/components/ui/Button" import { Image } from "~/components/ui/Image" import { UniLink } from "~/components/ui/UniLink" import { getSiteLink } from "~/lib/helpers" -import { - useAccountSites, - useGetShowcase, - useSubscribeToSites, -} from "~/queries/site" +import { useGetShowcase } from "~/queries/site" import topics from "../../../data/topics.json" +import { FollowAllButton } from "../common/FollowAllButton" export function MainSidebar({ hideSearch }: { hideSearch?: boolean }) { const showcaseSites = useGetShowcase() const { t } = useTranslation("index") - const userSite = useAccountSites() - const subscribeToSites = useSubscribeToSites() - - const doSubscribeToSites = useRefCallback(() => { - subscribeToSites.mutate({ - characterIds: showcaseSites.data - ?.map((s: { characterId?: string }) => s.characterId) - .filter(Boolean) - .map(Number), - siteIds: showcaseSites.data?.map((s: { handle: string }) => s.handle), - } as any) - }) - - const followAll = () => { - doSubscribeToSites() - } - const [showcaseMore, setShowcaseMore] = useState(false) return ( @@ -66,20 +43,15 @@ export function MainSidebar({ hideSearch }: { hideSearch?: boolean }) {

{t("Suggested creators for you")}

- + s.characterId) + .filter(Boolean) + .map(Number)} + siteIds={showcaseSites.data?.map( + (s: { handle: string }) => s.handle, + )} + />
    { return list } +export const getSubscriptionsFromList = async ( + list: number[], + fromCharacterId: number, +) => { + const client = createClient({ + url: "https://indexer.crossbell.io/v1/graphql", + exchanges: [cacheExchange, fetchExchange], + }) + + const response = await client + .query( + ` + query getFollows($list: [Int!], $fromCharacterId: Int!) { + links( + where: { + linkType: { equals: "follow" }, + fromCharacterId: { equals: $fromCharacterId }, + toCharacterId: { in: $list } + }, + ) { + toCharacterId + } + } + `, + { + list, + fromCharacterId, + }, + ) + .toPromise() + + return response.data?.links.map((link: any) => link.toCharacterId) +} + export const getSubscription = async ( siteId: string, handle: string, diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9908b7b1..33971b2f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -13,11 +13,11 @@ import { XShopLogo, XSyncLogo, } from "@crossbell/ui" -import { useRefCallback } from "@crossbell/util-hooks" import { RssIcon } from "@heroicons/react/24/outline" import { QueryClient, dehydrate } from "@tanstack/react-query" import { CharacterFloatCard } from "~/components/common/CharacterFloatCard" +import { FollowAllButton } from "~/components/common/FollowAllButton" import { Logo } from "~/components/common/Logo" import { MainLayout } from "~/components/main/MainLayout" import { Button } from "~/components/ui/Button" @@ -27,11 +27,7 @@ import { UniLink } from "~/components/ui/UniLink" import { CSB_SCAN, GITHUB_LINK } from "~/lib/env" import { getSiteLink } from "~/lib/helpers" import { languageDetector } from "~/lib/language-detector" -import { - useAccountSites, - useGetShowcase, - useSubscribeToSites, -} from "~/queries/site" +import { useGetShowcase } from "~/queries/site" import { prefetchGetSites } from "~/queries/site.server" export const getServerSideProps: GetServerSideProps = async (ctx) => { @@ -233,23 +229,6 @@ function Home() { }, ] - const userSite = useAccountSites() - const subscribeToSites = useSubscribeToSites() - - const doSubscribeToSites = useRefCallback(() => { - subscribeToSites.mutate({ - characterIds: showcaseSites.data - ?.map((s: { characterId?: string }) => s.characterId) - .filter(Boolean) - .map(Number), - siteIds: showcaseSites.data?.map((s: { handle: string }) => s.handle), - } as any) - }) - - const followAll = () => { - doSubscribeToSites() - } - const [showcaseMore, setShowcaseMore] = useState(false) return ( @@ -460,22 +439,17 @@ function Home() { "Discover these awesome teams and creators on xLog (sorted by update time)", )}

    - + size="xl" + characterIds={showcaseSites.data + ?.map((s: { characterId?: string }) => s.characterId) + .filter(Boolean) + .map(Number)} + siteIds={showcaseSites.data?.map( + (s: { handle: string }) => s.handle, + )} + />