From 2fe77a563fb52a29c6f097e01320fd06f4f94ab3 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Tue, 2 May 2023 00:32:25 +0100 Subject: [PATCH] Remove dependency Unidata (#473) --- src/components/common/AchievementItem.tsx | 2 +- src/components/common/AchievementModal.tsx | 2 +- src/components/common/BlockchainInfo.tsx | 91 ++-- src/components/common/CharacterCard.tsx | 37 +- src/components/common/CharacterList.tsx | 4 +- src/components/common/CharacterListItem.tsx | 15 +- src/components/common/Comment.tsx | 12 +- src/components/common/CommentInput.tsx | 66 +-- src/components/common/CommentItem.tsx | 23 +- src/components/common/ConnectButton.tsx | 209 ++++---- src/components/common/FollowingButton.tsx | 22 +- src/components/common/FollowingCount.tsx | 12 +- src/components/common/PatronButton.tsx | 4 +- src/components/common/PatronModal.tsx | 47 +- src/components/common/ReactionLike.tsx | 37 +- src/components/common/ReactionMint.tsx | 25 +- src/components/common/ReactionTip.tsx | 19 +- src/components/dashboard/DashboardLayout.tsx | 37 +- src/components/dashboard/PagesManager.tsx | 73 ++- .../PagesManagerBatchSelectActionTab.tsx | 65 ++- src/components/dashboard/PagesManagerMenu.tsx | 50 +- src/components/dashboard/SettingsLayout.tsx | 57 +- src/components/main/MainSidebar.tsx | 8 +- src/components/site/PostFooter.tsx | 17 +- src/components/site/PostMeta.tsx | 66 +-- src/components/site/SiteArchives.tsx | 60 ++- src/components/site/SiteFooter.tsx | 40 +- src/components/site/SiteHeader.tsx | 47 +- src/components/site/SiteHome.tsx | 49 +- src/components/site/SiteLayout.server.tsx | 120 +++-- src/components/site/SiteLayout.tsx | 49 +- src/components/site/SitePage.tsx | 38 +- src/hooks/useUserRole.ts | 10 +- src/lib/expand-unit.ts | 182 +++---- src/lib/helpers.ts | 18 +- src/lib/json-feed.ts | 52 +- src/lib/page-helpers.ts | 20 +- src/lib/redis.server.ts | 4 +- src/lib/types.ts | 49 +- src/models/page.model.ts | 507 +++++++++--------- src/models/site.model.ts | 226 ++------ src/pages/_site/[site]/[page].tsx | 10 +- src/pages/_site/[site]/archives.tsx | 14 +- src/pages/_site/[site]/feed/comments.tsx | 10 +- src/pages/_site/[site]/index.tsx | 6 +- src/pages/_site/[site]/manifest.json.tsx | 8 +- src/pages/_site/[site]/nft.tsx | 2 +- src/pages/_site/[site]/preview/[page].tsx | 30 +- src/pages/_site/[site]/search.tsx | 2 +- src/pages/_site/[site]/sitemap.xml.tsx | 8 +- src/pages/_site/[site]/tag/[tag].tsx | 14 +- src/pages/api/pages.ts | 4 +- src/pages/api/slug2id.ts | 56 +- .../dashboard/[subdomain]/achievements.tsx | 4 +- src/pages/dashboard/[subdomain]/comments.tsx | 2 +- src/pages/dashboard/[subdomain]/editor.tsx | 93 ++-- src/pages/dashboard/[subdomain]/events.tsx | 43 +- .../dashboard/[subdomain]/import/index.tsx | 4 - .../dashboard/[subdomain]/import/markdown.tsx | 8 +- .../dashboard/[subdomain]/import/mirror.tsx | 12 +- src/pages/dashboard/[subdomain]/index.tsx | 20 +- .../dashboard/[subdomain]/settings/css.tsx | 4 +- .../[subdomain]/settings/domains.tsx | 18 +- .../[subdomain]/settings/general.tsx | 23 +- .../[subdomain]/settings/navigation.tsx | 20 +- .../[subdomain]/settings/operator.tsx | 8 +- .../[subdomain]/settings/social-platforms.tsx | 45 +- src/pages/dashboard/[subdomain]/tokens.tsx | 2 +- src/pages/dashboard/index.tsx | 24 +- src/pages/index.tsx | 7 +- src/queries/page.server.ts | 23 +- src/queries/page.ts | 188 +++++-- src/queries/site.server.ts | 4 +- src/queries/site.ts | 119 ++-- src/queries/unidata.ts | 43 +- 75 files changed, 1636 insertions(+), 1713 deletions(-) diff --git a/src/components/common/AchievementItem.tsx b/src/components/common/AchievementItem.tsx index a2493411..cf26507f 100644 --- a/src/components/common/AchievementItem.tsx +++ b/src/components/common/AchievementItem.tsx @@ -38,7 +38,7 @@ export const AchievementItem: React.FC<{ group: AchievementSection["groups"][number] layoutId: string size?: number - characterId?: string + characterId?: number isOwner: boolean }> = ({ group, layoutId, size, characterId, isOwner }) => { const date = useDate() diff --git a/src/components/common/AchievementModal.tsx b/src/components/common/AchievementModal.tsx index bb400692..40fb81a3 100644 --- a/src/components/common/AchievementModal.tsx +++ b/src/components/common/AchievementModal.tsx @@ -18,7 +18,7 @@ export const AchievementModal: React.FC<{ group: AchievementSection["groups"][number] layoutId: string isOwner: boolean - characterId?: string + characterId?: number }> = ({ opened, setOpened, group, layoutId, isOwner, characterId }) => { const date = useDate() const { t } = useTranslation("common") diff --git a/src/components/common/BlockchainInfo.tsx b/src/components/common/BlockchainInfo.tsx index c90bcb06..5cec7ccb 100644 --- a/src/components/common/BlockchainInfo.tsx +++ b/src/components/common/BlockchainInfo.tsx @@ -3,24 +3,26 @@ import { useTranslation } from "next-i18next" import { Disclosure } from "@headlessui/react" import { BlockchainIcon } from "~/components/icons/BlockchainIcon" -import { CSB_SCAN, IPFS_GATEWAY } from "~/lib/env" +import { CSB_SCAN } from "~/lib/env" import { toCid, toGateway, toIPFS } from "~/lib/ipfs-parser" -import { Note, Profile } from "~/lib/types" +import { ExpandedCharacter, ExpandedNote } from "~/lib/types" import { cn } from "~/lib/utils" import { useGetGreenfieldId } from "~/queries/site" export const BlockchainInfo: React.FC<{ - site?: Profile | null - page?: Note | null + site?: ExpandedCharacter + page?: ExpandedNote }> = ({ site, page }) => { const { t } = useTranslation(["common", "site"]) - const ipfs = page - ? page.related_urls?.filter((url) => url.startsWith(IPFS_GATEWAY))?.[0] - : site?.metadata?.uri + const ipfs = (page ? page.metadata?.uri : site?.metadata?.uri) || "" const greenfieldId = useGetGreenfieldId(toCid(ipfs)) - const type = page ? (page?.tags?.includes("post") ? "post" : "page") : "blog" + const type = page + ? page?.metadata?.content?.tags?.includes("post") + ? "post" + : "page" + : "blog" return (
@@ -54,46 +56,53 @@ export const BlockchainInfo: React.FC<{
{t("Owner")}
- {page?.metadata?.owner || site?.metadata?.owner} + {page?.owner || site?.owner}
  • {t("Transaction Hash")}
    - {page - ? page?.related_urls - ?.filter((url) => url.startsWith(CSB_SCAN + "/tx/")) - .map((url, index) => { - return ( - - {t(index === 0 ? "Creation" : "Last Update")}{" "} - {url - .replace(CSB_SCAN + "/tx/", "") - .slice(0, 10)} - ... - {url.replace(CSB_SCAN + "/tx/", "").slice(-10)} - - ) - }) - : site?.metadata?.transactions.map( - (hash: string, index: number) => { - return ( - - {t(index === 0 ? "Creation" : "Last Update")}{" "} - {hash.slice(0, 10)}...{hash.slice(-10)} - - ) - }, - )} + {page ? ( + <> + + {t("Creation")} {page?.transactionHash.slice(0, 10)} + ...{page?.transactionHash.slice(-10)} + + + {t("Last Update")}{" "} + {page?.updatedTransactionHash.slice(0, 10)}... + {page?.updatedTransactionHash.slice(-10)} + + + ) : ( + <> + + {t("Creation")} {site?.transactionHash.slice(0, 10)} + ...{site?.transactionHash.slice(-10)} + + + {t("Last Update")}{" "} + {site?.updatedTransactionHash.slice(0, 10)}... + {site?.updatedTransactionHash.slice(-10)} + + + )}
  • diff --git a/src/components/common/CharacterCard.tsx b/src/components/common/CharacterCard.tsx index 43e27f59..773247e9 100644 --- a/src/components/common/CharacterCard.tsx +++ b/src/components/common/CharacterCard.tsx @@ -6,7 +6,7 @@ import { FollowingCount } from "~/components/common/FollowingCount" import { Titles } from "~/components/common/Titles" import { Avatar } from "~/components/ui/Avatar" import { useDate } from "~/hooks/useDate" -import type { Profile } from "~/lib/types" +import type { ExpandedCharacter } from "~/lib/types" import { cn } from "~/lib/utils" import * as siteModel from "~/models/site.model" @@ -28,7 +28,7 @@ export const CharacterCard: React.FC<{ style, }) => { const [firstOpen, setFirstOpen] = useState("") - const [site, setSite] = useState() + const [site, setSite] = useState() const date = useDate() const { t } = useTranslation("common") @@ -39,9 +39,7 @@ export const CharacterCard: React.FC<{ if (siteId) { siteModel.getSite(siteId).then((site) => setSite(site)) } else if (address) { - siteModel - .getUserSites({ address }) - .then((sites) => setSite(sites?.[0])) + siteModel.getSiteByAddress(address).then((site) => setSite(site)) } } else { setSite(undefined) @@ -64,7 +62,11 @@ export const CharacterCard: React.FC<{ {site ? ( <> - + {!hideFollowButton && ( - {site?.name} + {site?.metadata?.content?.name} - - @{site?.username} + + @{site?.handle} - {site?.description && ( + {site?.metadata?.content?.bio && ( - {site?.description} + {site?.metadata?.content?.bio} )} {!simple && ( - + )} - {!simple && site?.date_created && ( + {!simple && site?.createdAt && ( -
  • - + ) } diff --git a/src/components/common/Comment.tsx b/src/components/common/Comment.tsx index eb87df56..0ceb39c3 100644 --- a/src/components/common/Comment.tsx +++ b/src/components/common/Comment.tsx @@ -3,16 +3,17 @@ import { Virtuoso } from "react-virtuoso" import { CommentInput } from "~/components/common/CommentInput" import { CommentItem } from "~/components/common/CommentItem" -import { Note } from "~/lib/types" +import { ExpandedNote } from "~/lib/types" import { cn } from "~/lib/utils" import { useGetComments } from "~/queries/page" export const Comment: React.FC<{ - page?: Note | null + page?: ExpandedNote className?: string }> = ({ page, className }) => { const comments = useGetComments({ - pageId: page?.id, + characterId: page?.characterId, + noteId: page?.noteId, }) const { t } = useTranslation("common") @@ -37,7 +38,7 @@ export const Comment: React.FC<{ )} - + ( void comment?: NoteEntity & { character?: CharacterEntity | null } -}> = ({ pageId, originalId, onSubmitted, comment }) => { +}> = ({ + characterId, + noteId, + originalCharacterId, + originalNoteId, + onSubmitted, + comment, +}) => { const account = useAccountState((s) => s.computed.account) - const userSites = useAccountSites() const commentPage = useCommentPage() const updateComment = useUpdateComment() - const router = useRouter() - const [viewer, setViewer] = useState(null) const { t } = useTranslation(["common", "site"]) - useEffect(() => { - if (userSites.isSuccess && userSites.data?.length) { - setViewer(userSites.data[0]) - } - }, [userSites, router]) - const form = useForm({ defaultValues: { content: comment?.metadata?.content?.content || "", @@ -45,24 +42,26 @@ export const CommentInput: React.FC<{ }) const handleSubmit = form.handleSubmit(async (values) => { - if (pageId) { + if (characterId && noteId) { if (comment) { if (values.content) { updateComment.mutate({ - pageId, content: values.content, externalUrl: window.location.href, - originalId, characterId: comment.characterId, noteId: comment.noteId, + originalCharacterId, + originalNoteId, }) } } else { commentPage.mutate({ - pageId: pageId, + characterId, + noteId, content: values.content, externalUrl: window.location.href, - originalId: originalId, + originalCharacterId, + originalNoteId, }) } } @@ -79,8 +78,8 @@ export const CommentInput: React.FC<{
    @@ -88,12 +87,8 @@ export const CommentInput: React.FC<{
    {depth < 2 && ( @@ -137,8 +139,10 @@ export const CommentItem: React.FC<{ {replyOpen && (
    setReplyOpen(false)} />
    @@ -146,8 +150,10 @@ export const CommentItem: React.FC<{ {editOpen && (
    setEditOpen(false)} comment={comment} /> @@ -164,7 +170,8 @@ export const CommentItem: React.FC<{ }, ) => ( - {userSites.isSuccess ? ( + {!hideNotification && ( <> - {!hideNotification && ( - <> - {isAllRead ? ( - - ) : ( - - )} -
    -
    -
    - + {isAllRead ? ( + + ) : ( + )} - - - {!hideName && ( - <> -
    +
    +
    + + )} + + + {!hideName && ( + <> +
    + + {account.character?.metadata?.content?.name || + getAccountDisplayName(account)} + + {account.character?.handle && ( + - - {userSites.data?.[0]?.name || - getAccountDisplayName(account)} - - {userSites.data?.[0]?.username && ( - - {"@" + userSites.data?.[0]?.username || - getAccountDisplayName(account)} - - )} -
    - - - )} - - } - dropdown={ -
    - {dropdownLinks.map((link, i) => { - return ( - - - - - {link.label} - - ) - })} -
    - } - /> - - ) : ( - "" - )} + {"@" + account.character?.handle || + getAccountDisplayName(account)} + + )} +
    + + + )} + + } + dropdown={ +
    + {dropdownLinks.map((link, i) => { + return ( + + + + + {link.label} + + ) + })} +
    + } + /> ) })()} diff --git a/src/components/common/FollowingButton.tsx b/src/components/common/FollowingButton.tsx index 075b36b3..6b69dbe2 100644 --- a/src/components/common/FollowingButton.tsx +++ b/src/components/common/FollowingButton.tsx @@ -6,17 +6,16 @@ import { Button } from "~/components/ui/Button" import type { Variant } from "~/components/ui/Button" import { UniLink } from "~/components/ui/UniLink" import { SITE_URL } from "~/lib/env" -import { Profile } from "~/lib/types" +import { ExpandedCharacter } from "~/lib/types" import { cn } from "~/lib/utils" import { - useAccountSites, useGetSubscription, useSubscribeToSite, useUnsubscribeFromSite, } from "~/queries/site" export const FollowingButton: React.FC<{ - site: Profile | undefined | null + site?: ExpandedCharacter variant?: Variant className?: string size?: "sm" | "xl" @@ -24,27 +23,25 @@ export const FollowingButton: React.FC<{ }> = ({ site, variant, className, size, loadingStatusChange }) => { const subscribeToSite = useSubscribeToSite() const unsubscribeFromSite = useUnsubscribeFromSite() - const userSite = useAccountSites() - const characterId = site?.metadata?.proof ? Number(site.metadata.proof) : null const { t } = useTranslation("common") const handleClickSubscribe = () => { - if (characterId) { + if (site?.characterId) { if (subscription.data) { unsubscribeFromSite.mutate({ - characterId, - siteId: site?.username, + characterId: site?.characterId, + siteId: site?.handle, } as any) } else { subscribeToSite.mutate({ - characterId, - siteId: site?.username, + characterId: site?.characterId, + siteId: site?.handle, } as any) } } } - const subscription = useGetSubscription(site?.username) + const subscription = useGetSubscription(site?.characterId) useEffect(() => { if (subscribeToSite.isError) { @@ -99,8 +96,7 @@ export const FollowingButton: React.FC<{ isLoading={ subscription.data ? unsubscribeFromSite.isLoading || subscribeToSite.isLoading - : userSite.isLoading || - unsubscribeFromSite.isLoading || + : unsubscribeFromSite.isLoading || subscribeToSite.isLoading || subscription.isLoading } diff --git a/src/components/common/FollowingCount.tsx b/src/components/common/FollowingCount.tsx index 5ffd7319..6e24e51c 100644 --- a/src/components/common/FollowingCount.tsx +++ b/src/components/common/FollowingCount.tsx @@ -9,18 +9,18 @@ import { } from "~/queries/site" export const FollowingCount: React.FC<{ - siteId?: string + characterId?: number disableList?: boolean -}> = ({ siteId, disableList }) => { +}> = ({ characterId, disableList }) => { let [isFollowListOpen, setIsFollowListOpen] = useState(false) let [isToFollowListOpen, setIsToFollowListOpen] = useState(false) const { t } = useTranslation("common") const subscriptions = useGetSiteSubscriptions({ - siteId: siteId || "", + characterId, }) const toSubscriptions = useGetSiteToSubscriptions({ - siteId: siteId || "", + characterId, }) return ( @@ -34,7 +34,7 @@ export const FollowingCount: React.FC<{ onClick={() => setIsFollowListOpen(true)} > - {subscriptions.data?.pages?.[0]?.total || 0} + {subscriptions.data?.pages?.[0]?.count || 0} {" "} {t("Followers")} @@ -47,7 +47,7 @@ export const FollowingCount: React.FC<{ onClick={() => setIsToFollowListOpen(true)} > - {toSubscriptions.data?.pages?.[0]?.total || 0} + {toSubscriptions.data?.pages?.[0]?.count || 0} {" "} {t("Followings")} diff --git a/src/components/common/PatronButton.tsx b/src/components/common/PatronButton.tsx index c6b8dab7..8a4e566a 100644 --- a/src/components/common/PatronButton.tsx +++ b/src/components/common/PatronButton.tsx @@ -3,11 +3,11 @@ import { useState } from "react" import { PatronModal } from "~/components/common/PatronModal" import { Button } from "~/components/ui/Button" -import { Profile } from "~/lib/types" +import { ExpandedCharacter } from "~/lib/types" import { cn } from "~/lib/utils" export const PatronButton: React.FC<{ - site: Profile | undefined | null + site?: ExpandedCharacter className?: string size?: "sm" | "xl" loadingStatusChange?: (status: boolean) => void diff --git a/src/components/common/PatronModal.tsx b/src/components/common/PatronModal.tsx index 62792cdd..6787fa43 100644 --- a/src/components/common/PatronModal.tsx +++ b/src/components/common/PatronModal.tsx @@ -11,8 +11,7 @@ import { Button } from "~/components/ui/Button" import { Modal } from "~/components/ui/Modal" import { CSB_SCAN, MIRA_LINK } from "~/lib/env" import { getSiteLink } from "~/lib/helpers" -import { Note, Profile } from "~/lib/types" -import { parsePageId } from "~/models/page.model" +import { ExpandedCharacter, ExpandedNote } from "~/lib/types" import { useGetTips, useTipCharacter } from "~/queries/site" import { Tabs } from "../ui/Tabs" @@ -20,17 +19,23 @@ import { UniLink } from "../ui/UniLink" import { CharacterFloatCard } from "./CharacterFloatCard" export const PatronModal: React.FC<{ - site: Profile | undefined | null - page?: Note | null + site?: ExpandedCharacter + page?: ExpandedNote open: boolean setOpen: (open: boolean) => void }> = ({ site, page, open, setOpen }) => { const { t } = useTranslation("common") const tipCharacter = useTipCharacter() - const tips = useGetTips({ - toCharacterId: site?.metadata?.proof, - toNoteId: parsePageId(page?.id || "").noteId, - }) + const tips = useGetTips( + page + ? { + toCharacterId: page?.characterId, + toNoteId: page?.noteId, + } + : { + toCharacterId: site?.characterId, + }, + ) const connectModal = useConnectModal() const radios = [ @@ -66,12 +71,12 @@ export const PatronModal: React.FC<{ ) const submit = () => { - if (currentCharacterId && site?.metadata?.proof && parseInt(value)) { + if (currentCharacterId && site?.characterId && parseInt(value)) { tipCharacter.mutate({ fromCharacterId: currentCharacterId, - toCharacterId: site?.metadata?.proof, + toCharacterId: site?.characterId, amount: parseInt(value), - noteId: parsePageId(page?.id || "").noteId, + noteId: page?.noteId, }) } else { setOpen(false) @@ -100,7 +105,7 @@ export const PatronModal: React.FC<{ tipCharacter.reset() } } - }, [tipCharacter.isSuccess, t, site?.name]) + }, [tipCharacter.isSuccess, t]) useEffect(() => { if (tipCharacter.isError) { @@ -112,10 +117,10 @@ export const PatronModal: React.FC<{ const title = (page ? t("Tip the post: {{name}}", { - name: page.title, + name: page.metadata?.content?.title, }) : t("Become a patron of {{name}}", { - name: site?.name, + name: site?.metadata?.content?.name, })) || "" return ( @@ -135,17 +140,21 @@ export const PatronModal: React.FC<{
    - + - {site?.name} + {site?.metadata?.content?.name} - @{site?.username} + @{site?.handle} - {site?.description && ( + {site?.metadata?.content?.bio && ( - {site?.description} + {site?.metadata?.content?.bio} )}
    diff --git a/src/components/common/ReactionLike.tsx b/src/components/common/ReactionLike.tsx index b5fae760..849216e5 100644 --- a/src/components/common/ReactionLike.tsx +++ b/src/components/common/ReactionLike.tsx @@ -8,7 +8,6 @@ import { Tooltip } from "~/components/ui/Tooltip" import { UniLink } from "~/components/ui/UniLink" import { CSB_SCAN } from "~/lib/env" import { cn } from "~/lib/utils" -import { parsePageId } from "~/models/page.model" import { useCheckLike, useGetLikeCounts, @@ -21,8 +20,9 @@ import { Button } from "../ui/Button" export const ReactionLike: React.FC<{ size?: "sm" | "base" - pageId?: string -}> = ({ size, pageId }) => { + characterId?: number + noteId?: number +}> = ({ size, characterId, noteId }) => { const toggleLikePage = useToggleLikePage() const { t } = useTranslation("common") @@ -30,29 +30,44 @@ export const ReactionLike: React.FC<{ const [isLikeListOpen, setIsLikeListOpen] = useState(false) const likeRef = useRef(null) - const [likes, likesMutation] = useGetLikes({ pageId }) - const [likeStatus] = useCheckLike({ - pageId, + const [likes, likesMutation] = useGetLikes({ + characterId, + noteId, + }) + const [likeStatus] = useCheckLike({ + characterId, + noteId, + }) + const { data: likeCount = 0 } = useGetLikeCounts({ + characterId, + noteId, }) - const { data: likeCount = 0 } = useGetLikeCounts({ pageId }) const [isUnlikeOpen, setIsUnlikeOpen] = useState(false) const like = () => { - if (pageId) { + if (characterId && noteId) { if (likeStatus.isLiked) { setIsLikeOpen(true) } else { - toggleLikePage.mutate({ ...parsePageId(pageId), action: "link" }) + toggleLikePage.mutate({ + characterId, + noteId, + action: "link", + }) } } } const unlike = () => { - if (pageId) { + if (characterId && noteId) { setIsUnlikeOpen(false) if (likeStatus.isLiked) { - toggleLikePage.mutate({ ...parsePageId(pageId), action: "unlink" }) + toggleLikePage.mutate({ + noteId, + characterId, + action: "unlink", + }) } // else do nothing } } diff --git a/src/components/common/ReactionMint.tsx b/src/components/common/ReactionMint.tsx index 57740565..68255be1 100644 --- a/src/components/common/ReactionMint.tsx +++ b/src/components/common/ReactionMint.tsx @@ -12,7 +12,6 @@ import { UniLink } from "~/components/ui/UniLink" import { CSB_SCAN, CSB_XCHAR } from "~/lib/env" import { noopArr } from "~/lib/noop" import { cn } from "~/lib/utils" -import { parsePageId } from "~/models/page.model" import { useCheckMint, useGetMints, useMintPage } from "~/queries/page" import { AvatarStack } from "../ui/AvatarStack" @@ -20,8 +19,9 @@ import { Button } from "../ui/Button" export const ReactionMint: React.FC<{ size?: "sm" | "base" - pageId?: string -}> = ({ size, pageId }) => { + noteId?: number + characterId?: number +}> = ({ size, noteId, characterId }) => { const mintPage = useMintPage() const { t } = useTranslation("common") @@ -32,17 +32,24 @@ export const ReactionMint: React.FC<{ const mintRef = useRef(null) const mints = useGetMints({ - pageId: pageId, + characterId, + noteId, includeCharacter: size !== "sm", }) - const isMint = useCheckMint(pageId) + const isMint = useCheckMint({ + characterId, + noteId, + }) const mint = () => { - if (pageId) { + if (characterId && noteId) { if (isMint.data?.count) { setIsMintOpen(true) } else { - mintPage.mutate(parsePageId(pageId)) + mintPage.mutate({ + characterId, + noteId, + }) } } } @@ -77,11 +84,11 @@ export const ReactionMint: React.FC<{ const avatars = useMemo( () => mints.data?.pages?.[0]?.list - ?.sort((a, b: any) => + ?.sort((a, b) => b.character?.metadata?.content?.avatars?.[0] ? 1 : -1, ) .slice(0, 3) - .map((mint: any) => ({ + .map((mint) => ({ images: mint.character?.metadata?.content?.avatars, name: mint.character?.metadata?.content?.name, })) || noopArr, diff --git a/src/components/common/ReactionTip.tsx b/src/components/common/ReactionTip.tsx index 32f1fbf0..1aeca2ea 100644 --- a/src/components/common/ReactionTip.tsx +++ b/src/components/common/ReactionTip.tsx @@ -6,18 +6,18 @@ import { useAccountState } from "@crossbell/connect-kit" import { PatronModal } from "~/components/common/PatronModal" import { Tooltip } from "~/components/ui/Tooltip" import { noopArr } from "~/lib/noop" -import { Note, Profile } from "~/lib/types" -import { parsePageId } from "~/models/page.model" +import { ExpandedCharacter, ExpandedNote } from "~/lib/types" import { useGetTips } from "~/queries/site" import { AvatarStack } from "../ui/AvatarStack" import { Button } from "../ui/Button" export const ReactionTip: React.FC<{ - pageId?: string - site?: Profile | null - page?: Note | null -}> = ({ pageId, site, page }) => { + characterId?: number + noteId?: number + site?: ExpandedCharacter + page?: ExpandedNote +}> = ({ characterId, noteId, site, page }) => { const { t } = useTranslation("common") const account = useAccountState((s) => s.computed.account) @@ -25,7 +25,6 @@ export const ReactionTip: React.FC<{ const [isTipOpen, setIsTipOpen] = useState(false) const tipRef = useRef(null) - const { characterId, noteId } = parsePageId(pageId || "") const tips = useGetTips({ toCharacterId: characterId, toNoteId: noteId, @@ -37,7 +36,7 @@ export const ReactionTip: React.FC<{ }) const tip = () => { - if (pageId) { + if (characterId && noteId) { setIsTipOpen(true) } } @@ -45,11 +44,11 @@ export const ReactionTip: React.FC<{ const avatars = useMemo( () => tips.data?.pages?.[0]?.list - ?.sort((a, b: any) => + ?.sort((a, b) => b.character?.metadata?.content?.avatars?.[0] ? 1 : -1, ) .slice(0, 3) - .map((mint: any) => ({ + .map((mint) => ({ images: mint.character?.metadata?.content?.avatars, name: mint.character?.metadata?.content?.name, })) || noopArr, diff --git a/src/components/dashboard/DashboardLayout.tsx b/src/components/dashboard/DashboardLayout.tsx index 48f91f7e..4105789e 100644 --- a/src/components/dashboard/DashboardLayout.tsx +++ b/src/components/dashboard/DashboardLayout.tsx @@ -19,7 +19,7 @@ import { toGateway } from "~/lib/ipfs-parser" import { getStorage } from "~/lib/storage" import { cn } from "~/lib/utils" import { useGetPagesBySite } from "~/queries/page" -import { useAccountSites, useGetSite } from "~/queries/site" +import { useGetSite } from "~/queries/site" import { SEOHead } from "../common/SEOHead" import { UniLink } from "../ui/UniLink" @@ -36,12 +36,11 @@ export function DashboardLayout({ const router = useRouter() const subdomain = router.query.subdomain as string const site = useGetSite(subdomain) - const userSite = useAccountSites() const userRole = useUserRole(subdomain) - const [ssrReady, isConnected] = useAccountState(({ ssrReady, computed }) => [ + const [ssrReady, account] = useAccountState(({ ssrReady, computed }) => [ ssrReady, - !!computed.account, + computed.account, ]) const connectModal = useConnectModal() const [ready, setReady] = React.useState(false) @@ -52,7 +51,7 @@ export function DashboardLayout({ useEffect(() => { if (ssrReady) { - if (!isConnected) { + if (!account) { setReady(false) setHasPermission(false) connectModal.show() @@ -65,22 +64,22 @@ export function DashboardLayout({ } } } - }, [ssrReady, userRole.isSuccess, userRole.data, isConnected, connectModal]) + }, [ssrReady, userRole.isSuccess, userRole.data, account, connectModal]) const showNotificationModal = useShowNotificationModal() const { isAllRead } = useNotifications() const pages = useGetPagesBySite({ type: "post", - site: "xlog-events", - take: 1, + characterId: 50153, + limit: 1, }) const [isEventsAllRead, setIsEventsAllRead] = React.useState(true) const latestEventRead = getStorage("latestEventRead")?.value || 0 useEffect(() => { if (pages.isSuccess) { if ( - new Date(pages.data.pages[0].list?.[0].date_created) > + new Date(pages.data.pages[0].list?.[0].createdAt) > new Date(latestEventRead) ) { setIsEventsAllRead(false) @@ -169,13 +168,15 @@ export function DashboardLayout({ hasPermission ? ( <> - {site?.data?.css && ( + {site?.data?.metadata?.content?.css && ( )} @@ -274,23 +275,25 @@ export function DashboardLayout({
    {isOpen && "xLog"} - {userSite.data?.[0]?.username && + {account?.character?.handle && subdomain && - userSite.data[0].username !== subdomain && ( + account?.character?.handle !== subdomain && (
    {isOpen && "You are operating"}
    {isOpen && ( - {site.data?.name} + + {site.data?.metadata?.content?.name} + - @{site.data?.username} + @{site.data?.handle} )} diff --git a/src/components/dashboard/PagesManager.tsx b/src/components/dashboard/PagesManager.tsx index cdd7854d..fc6a8591 100644 --- a/src/components/dashboard/PagesManager.tsx +++ b/src/components/dashboard/PagesManager.tsx @@ -11,9 +11,10 @@ import { useDate } from "~/hooks/useDate" import { getPageVisibility } from "~/lib/page-helpers" import { readFiles } from "~/lib/read-files" import { setStorage } from "~/lib/storage" -import { PageVisibilityEnum } from "~/lib/types" +import { ExpandedNote, PageVisibilityEnum } from "~/lib/types" import { cn } from "~/lib/utils" import { useGetPagesBySite } from "~/queries/page" +import { useGetSite } from "~/queries/site" import { Button } from "../ui/Button" import { EmptyState } from "../ui/EmptyState" @@ -29,6 +30,7 @@ export const PagesManager: React.FC<{ }> = ({ isPost }) => { const router = useRouter() const subdomain = router.query.subdomain as string + const site = useGetSite(subdomain) const visibility = useMemo( () => @@ -43,13 +45,13 @@ export const PagesManager: React.FC<{ const pages = useGetPagesBySite({ type: isPost ? "post" : "page", - site: subdomain!, - take: 100, + characterId: site.data?.characterId, + limit: 100, visibility, }) // Batch selections - const [batchSelected, setBatchSelected] = useState([]) + const [batchSelected, setBatchSelected] = useState<(string | number)[]>([]) const tabItems: TabItem[] = [ { @@ -68,10 +70,6 @@ export const PagesManager: React.FC<{ value: PageVisibilityEnum.Scheduled, text: "Scheduled", }, - { - value: PageVisibilityEnum.Crossbell, - text: "Others on Crossbell", - }, ].map((item) => ({ text: item.text, onClick: () => { @@ -90,10 +88,10 @@ export const PagesManager: React.FC<{ active: item.value === visibility, })) - const getPageEditLink = (page: { id: string }) => { - return `/dashboard/${subdomain}/editor?id=${page.id}&type=${ - isPost ? "post" : "page" - }` + const getPageEditLink = (page: ExpandedNote) => { + return `/dashboard/${subdomain}/editor?id=${ + page.noteId || page.draftKey + }&type=${isPost ? "post" : "page"}` } const queryClient = useQueryClient() @@ -106,7 +104,7 @@ export const PagesManager: React.FC<{ const file = (await readFiles(e.target?.files))?.[0] if (file) { const id = nanoid() - const key = `draft-${subdomain}-local-${id}` + const key = `draft-${site.data?.characterId}-local-${id}` setStorage(key, { date: +new Date(), values: { @@ -119,7 +117,10 @@ export const PagesManager: React.FC<{ }, isPost: isPost, }) - queryClient.invalidateQueries(["getPagesBySite", subdomain]) + queryClient.invalidateQueries([ + "getPagesBySite", + site.data?.characterId, + ]) router.push( `/dashboard/${subdomain}/editor?id=local-${id}&type=${ isPost ? "post" : "page" @@ -220,7 +221,7 @@ export const PagesManager: React.FC<{ !!tabItems.find((item) => item.text === "Others on Crossbell") // Not sure if there are better ways ?.active } - pages={pages} + pages={pages.data} batchSelected={batchSelected} setBatchSelected={setBatchSelected} /> @@ -229,7 +230,7 @@ export const PagesManager: React.FC<{ )}
    - {!pages.data?.pages?.[0].total && ( + {!pages.data?.pages?.[0].count && ( )} @@ -238,7 +239,7 @@ export const PagesManager: React.FC<{ currentLength++ return ( @@ -246,27 +247,39 @@ export const PagesManager: React.FC<{
    - {page.title ? ( + {page.metadata?.content?.title ? (
    - {page.title} + {page.metadata?.content?.title}
    ) : (
    - {page.summary?.content} + {page.metadata?.content?.summary}
    )}
    @@ -292,8 +305,10 @@ export const PagesManager: React.FC<{ ยท {getPageVisibility(page) === PageVisibilityEnum.Draft - ? date.formatDate(page.date_updated) - : date.formatDate(page.date_published)} + ? date.formatDate(page.updatedAt) + : date.formatDate( + page.metadata?.content?.date_published || "", + )}
    @@ -341,11 +356,11 @@ export const PagesManager: React.FC<{ isPost ? "post" : "page" + - ((pages.data?.pages?.[0].total || 0) - currentLength > 1 + ((pages.data?.pages?.[0].count || 0) - currentLength > 1 ? "s" : ""), ), - count: (pages.data?.pages?.[0].total || 0) - currentLength, + count: (pages.data?.pages?.[0].count || 0) - currentLength, ns: "site", })} diff --git a/src/components/dashboard/PagesManagerBatchSelectActionTab.tsx b/src/components/dashboard/PagesManagerBatchSelectActionTab.tsx index c78e09c7..4a10621c 100644 --- a/src/components/dashboard/PagesManagerBatchSelectActionTab.tsx +++ b/src/components/dashboard/PagesManagerBatchSelectActionTab.tsx @@ -2,14 +2,14 @@ import { useTranslation } from "next-i18next" import { useRouter } from "next/router" import React, { useState } from "react" import toast from "react-hot-toast" -import type { Note, Notes } from "unidata.js" -import type { UseInfiniteQueryResult } from "@tanstack/react-query" +import type { InfiniteData } from "@tanstack/react-query" import { useQueryClient } from "@tanstack/react-query" import { type TabItem, Tabs } from "~/components/ui/Tabs" import { APP_NAME } from "~/lib/env" import { delStorage, getStorage, setStorage } from "~/lib/storage" +import { ExpandedNote } from "~/lib/types" import { useCreateOrUpdatePage, useDeletePage } from "~/queries/page" import { DeleteConfirmationModal } from "./DeleteConfirmationModal" @@ -17,8 +17,10 @@ import { DeleteConfirmationModal } from "./DeleteConfirmationModal" export const PagesManagerBatchSelectActionTab: React.FC<{ isPost: boolean isNotxLogContent: boolean - pages: UseInfiniteQueryResult - batchSelected: string[] + pages?: InfiniteData<{ + list: ExpandedNote[] + }> + batchSelected: (string | number)[] setBatchSelected: (selected: string[]) => void }> = ({ isPost, isNotxLogContent, pages, batchSelected, setBatchSelected }) => { const { t } = useTranslation(["dashboard", "site"]) @@ -38,9 +40,9 @@ export const PagesManagerBatchSelectActionTab: React.FC<{ onClick: () => { // Get all page IDs const allIDs: string[] = [] - pages.data?.pages.map((page) => + pages?.pages.map((page) => page.list?.map((page) => { - allIDs.push(page.id) + allIDs.push(page.metadata?.content?.slug || "") }), ) setBatchSelected(allIDs) @@ -65,10 +67,10 @@ export const PagesManagerBatchSelectActionTab: React.FC<{ const toastId = toast.loading("Converting...") // Find all selected - const selectedPages: Note[] = [] - pages.data?.pages.map((page) => + const selectedPages: ExpandedNote[] = [] + pages?.pages.map((page) => page.list?.map((page) => { - if (batchSelected.includes(page.id)) { + if (batchSelected.includes(page.metadata?.content?.slug || "")) { selectedPages.push(page) } }), @@ -79,34 +81,38 @@ export const PagesManagerBatchSelectActionTab: React.FC<{ await Promise.all( selectedPages.map((page) => { // Check again to ensure it's not - const isNotxLogContent = !page.applications?.includes("xlog") + const isNotxLogContent = + !page.metadata?.content?.sources?.includes("xlog") const targetNoteBase = { published: true, - pageId: page.id, + pageId: `${page.characterId}-${page.noteId}`, siteId: subdomain, - tags: page.tags + tags: page.metadata?.content?.tags ?.filter((tag) => tag !== "post" && tag !== "page") ?.join(", "), - applications: page.applications, + applications: page.metadata?.content?.sources, } if (isNotxLogContent) { return createOrUpdatePage.mutateAsync({ ...targetNoteBase, isPost: isPost, // Convert to xLog content + characterId: page.characterId, }) } else { - if (!page.metadata) { + if (!page.noteId) { // Is draft - const data = getStorage(`draft-${subdomain}-${page.id}`) + const key = `draft-${page?.characterId}-${page.draftKey}` + const data = getStorage(key) data.isPost = !isPost - setStorage(`draft-${subdomain}-${page.id}`, data) + setStorage(key, data) } else { // IsNote return createOrUpdatePage.mutateAsync({ ...targetNoteBase, isPost: !isPost, // Change type + characterId: page.characterId, }) } } @@ -125,9 +131,12 @@ export const PagesManagerBatchSelectActionTab: React.FC<{ // Invalidate site data refresh await Promise.all([ - queryClient.invalidateQueries(["getPagesBySite", subdomain]), + queryClient.invalidateQueries([ + "getPagesBySite", + selectedPages[0]?.characterId, + ]), ...selectedPages.map((page) => - queryClient.invalidateQueries(["getPage", page.id]), + queryClient.invalidateQueries(["getPage", page?.characterId]), ), ]) @@ -150,10 +159,10 @@ export const PagesManagerBatchSelectActionTab: React.FC<{ const toastId = toast.loading("Deleting...") // Find all selected - const selectedPages: Note[] = [] - pages.data?.pages.map((page) => + const selectedPages: ExpandedNote[] = [] + pages?.pages.map((page) => page.list?.map((page) => { - if (batchSelected.includes(page.id)) { + if (batchSelected.includes(page.noteId || page.draftKey || 0)) { selectedPages.push(page) } }), @@ -163,14 +172,15 @@ export const PagesManagerBatchSelectActionTab: React.FC<{ try { await Promise.all( selectedPages.map((page) => { - if (!page.metadata) { + if (!page.noteId) { // Is draft - delStorage(`draft-${subdomain}-${page.id}`) + delStorage(`draft-${page?.characterId}-${page.draftKey}`) } else { // Is Note return deletePage.mutateAsync({ site: subdomain, - id: page.id, + id: `${page.characterId}-${page.noteId}`, + characterId: page.characterId, }) } }), @@ -188,9 +198,12 @@ export const PagesManagerBatchSelectActionTab: React.FC<{ // Refresh site data await Promise.all([ - queryClient.refetchQueries(["getPagesBySite", subdomain]), + queryClient.refetchQueries([ + "getPagesBySite", + selectedPages[0]?.characterId, + ]), ...selectedPages.map((page) => - queryClient.refetchQueries(["getPage", page.id]), + queryClient.refetchQueries(["getPage", page.characterId]), ), ]) diff --git a/src/components/dashboard/PagesManagerMenu.tsx b/src/components/dashboard/PagesManagerMenu.tsx index 4c0edf7a..9603d4d9 100644 --- a/src/components/dashboard/PagesManagerMenu.tsx +++ b/src/components/dashboard/PagesManagerMenu.tsx @@ -2,7 +2,6 @@ import { useTranslation } from "next-i18next" import { useRouter } from "next/router" import { FC, useEffect, useState } from "react" import toast from "react-hot-toast" -import type { Note } from "unidata.js" import { Menu } from "@headlessui/react" import { useQueryClient } from "@tanstack/react-query" @@ -11,16 +10,17 @@ import { useGetState } from "~/hooks/useGetState" import { APP_NAME } from "~/lib/env" import { getNoteSlugFromNote, getTwitterShareUrl } from "~/lib/helpers" import { delStorage, getStorage, setStorage } from "~/lib/storage" +import { ExpandedNote } from "~/lib/types" import { useCreateOrUpdatePage, useDeletePage } from "~/queries/page" import { useGetSite } from "~/queries/site" import { DeleteConfirmationModal } from "./DeleteConfirmationModal" -const usePageEditLink = (page: { id: string }, isPost: boolean) => { +const usePageEditLink = (page: ExpandedNote, isPost: boolean) => { const router = useRouter() const subdomain = router.query.subdomain as string - return `/dashboard/${subdomain}/editor?id=${page.id}&type=${ + return `/dashboard/${subdomain}/editor?id=${page.noteId}&type=${ isPost ? "post" : "page" }` } @@ -32,12 +32,12 @@ interface Item { } export const PagesManagerMenu: FC<{ isPost: boolean - page: Note + page: ExpandedNote onClick: () => void }> = ({ isPost, page, onClick: onClose }) => { const { t } = useTranslation(["dashboard", "site"]) - const isCrossbell = !page.applications?.includes("xlog") + const isCrossbell = !page.metadata?.content?.sources?.includes("xlog") const router = useRouter() const createOrUpdatePage = useCreateOrUpdatePage() @@ -110,21 +110,27 @@ export const PagesManagerMenu: FC<{ setConvertToastId(toastId) createOrUpdatePage.mutate({ published: true, - pageId: page.id, + pageId: `${page.characterId}-${page.noteId}`, siteId: subdomain, - tags: page.tags + tags: page.metadata?.content?.tags ?.filter((tag) => tag !== "post" && tag !== "page") ?.join(", "), isPost: isPost, - applications: page.applications, + applications: page.metadata?.content?.sources, + characterId: page.characterId, }) } else { - if (!page.metadata) { - const data = getStorage(`draft-${subdomain}-${page.id}`) + if (!page.noteId) { + const data = getStorage( + `draft-${site.data?.characterId}-${page.draftKey}`, + ) data.isPost = !isPost - setStorage(`draft-${subdomain}-${page.id}`, data) - queryClient.invalidateQueries(["getPagesBySite", subdomain]) - queryClient.invalidateQueries(["getPage", page.id]) + setStorage(`draft-${site.data?.characterId}-${page.draftKey}`, data) + queryClient.invalidateQueries([ + "getPagesBySite", + site.data?.characterId, + ]) + queryClient.invalidateQueries(["getPage", page.characterId]) toast.success("Converted!", { id: toastId, }) @@ -132,13 +138,14 @@ export const PagesManagerMenu: FC<{ setConvertToastId(toastId) createOrUpdatePage.mutate({ published: true, - pageId: page.id, + pageId: `${page.characterId}-${page.noteId}`, siteId: subdomain, - tags: page.tags + tags: page.metadata?.content?.tags ?.filter((tag) => tag !== "post" && tag !== "page") ?.join(", "), isPost: !isPost, - applications: page.applications, + applications: page.metadata?.content?.sources, + characterId: page.characterId, }) } } @@ -193,12 +200,12 @@ export const PagesManagerMenu: FC<{ const [deleteConfirmModalOpen, setDeleteConfirmModalOpen] = useState(false) const onDelete = () => { - if (!page.metadata) { + if (!page.noteId) { const toastId = toast.loading("Deleting...") - delStorage(`draft-${subdomain}-${page.id}`) + delStorage(`draft-${site.data?.characterId}-${page.draftKey}`) Promise.all([ - queryClient.refetchQueries(["getPagesBySite", subdomain]), - queryClient.refetchQueries(["getPage", page.id]), + queryClient.refetchQueries(["getPagesBySite", site.data?.characterId]), + queryClient.refetchQueries(["getPage", page.characterId]), ]).then(() => { toast.success("Deleted!", { id: toastId, @@ -208,7 +215,8 @@ export const PagesManagerMenu: FC<{ setDeleteToastId(toast.loading("Deleting...")) deletePage.mutate({ site: subdomain, - id: page.id, + id: `${page.characterId}-${page.noteId}`, + characterId: page.characterId, }) } } diff --git a/src/components/dashboard/SettingsLayout.tsx b/src/components/dashboard/SettingsLayout.tsx index 9da6e635..f4d11796 100644 --- a/src/components/dashboard/SettingsLayout.tsx +++ b/src/components/dashboard/SettingsLayout.tsx @@ -10,42 +10,37 @@ import { DashboardMain } from "./DashboardMain" export const SettingsLayout: React.FC<{ title: string children: React.ReactNode - type: "site" | "account" -}> = ({ title, children, type }) => { +}> = ({ title, children }) => { const router = useRouter() const { t } = useTranslation("dashboard") const xSettingsModal = useXSettingsModal() const subdomain = router.query.subdomain as string - const tabItems: TabItem[] = ( - type === "site" - ? [ - { text: "General", href: `/dashboard/${subdomain}/settings/general` }, - { - text: "Social Platforms", - href: `/dashboard/${subdomain}/settings/social-platforms`, - }, - { - text: "Navigation", - href: `/dashboard/${subdomain}/settings/navigation`, - }, - { text: "Domains", href: `/dashboard/${subdomain}/settings/domains` }, - { text: "Custom CSS", href: `/dashboard/${subdomain}/settings/css` }, - { - text: "Operators", - href: `/dashboard/${subdomain}/settings/operator`, - }, - { - text: "xSettings", - onClick: () => xSettingsModal.show(), - }, - { - text: "Export data", - href: `https://export.crossbell.io/?handle=${subdomain}`, - }, - ] - : [{ text: "Profile", href: `/dashboard/${subdomain}/account/profile` }] - ).map((item) => ({ ...item, active: router.asPath === item.href })) + const tabItems: TabItem[] = [ + { text: "General", href: `/dashboard/${subdomain}/settings/general` }, + { + text: "Social Platforms", + href: `/dashboard/${subdomain}/settings/social-platforms`, + }, + { + text: "Navigation", + href: `/dashboard/${subdomain}/settings/navigation`, + }, + { text: "Domains", href: `/dashboard/${subdomain}/settings/domains` }, + { text: "Custom CSS", href: `/dashboard/${subdomain}/settings/css` }, + { + text: "Operators", + href: `/dashboard/${subdomain}/settings/operator`, + }, + { + text: "xSettings", + onClick: () => xSettingsModal.show(), + }, + { + text: "Export data", + href: `https://export.crossbell.io/?handle=${subdomain}`, + }, + ].map((item) => ({ ...item, active: router.asPath === item.href })) return ( diff --git a/src/components/main/MainSidebar.tsx b/src/components/main/MainSidebar.tsx index 8434afba..8352b37a 100644 --- a/src/components/main/MainSidebar.tsx +++ b/src/components/main/MainSidebar.tsx @@ -65,7 +65,7 @@ export function MainSidebar({ hideSearch }: { hideSearch?: boolean }) { > {t("Show more")}
    - {showcaseSites.data?.map((site: any) => ( + {showcaseSites.data?.map((site) => (
  • - {site.metadata.content?.name} + {site?.metadata?.content?.name} - {site.metadata.content?.bio && ( + {site?.metadata?.content?.bio && ( {site.metadata.content?.bio} diff --git a/src/components/site/PostFooter.tsx b/src/components/site/PostFooter.tsx index 36831aa6..01da75f6 100644 --- a/src/components/site/PostFooter.tsx +++ b/src/components/site/PostFooter.tsx @@ -2,11 +2,11 @@ import { Comment } from "~/components/common/Comment" import { ReactionLike } from "~/components/common/ReactionLike" import { ReactionMint } from "~/components/common/ReactionMint" import { ReactionTip } from "~/components/common/ReactionTip" -import { Note, Profile } from "~/lib/types" +import { ExpandedCharacter, ExpandedNote } from "~/lib/types" export const PostFooter: React.FC<{ - page?: Note | null - site?: Profile | null + page?: ExpandedNote + site?: ExpandedCharacter }> = ({ page, site }) => { return ( <> @@ -14,9 +14,14 @@ export const PostFooter: React.FC<{ className="xlog-reactions flex fill-gray-400 text-gray-500 sm:items-center space-x-6 sm:space-x-10 mt-14 mb-12" data-hide-print > - - - + + + diff --git a/src/components/site/PostMeta.tsx b/src/components/site/PostMeta.tsx index 575dc95c..e569aed7 100644 --- a/src/components/site/PostMeta.tsx +++ b/src/components/site/PostMeta.tsx @@ -1,29 +1,25 @@ import { useTranslation } from "next-i18next" import { useEffect, useState } from "react" -import { CharacterFloatCard } from "~/components/common/CharacterFloatCard" import { BlockchainIcon } from "~/components/icons/BlockchainIcon" -import { Avatar } from "~/components/ui/Avatar" import { UniLink } from "~/components/ui/UniLink" import { useDate } from "~/hooks/useDate" import { useUserRole } from "~/hooks/useUserRole" import { CSB_SCAN, SITE_URL } from "~/lib/env" -import { getSiteLink } from "~/lib/helpers" import { toCid } from "~/lib/ipfs-parser" -import { Note, Profile } from "~/lib/types" +import { ExpandedCharacter, ExpandedNote } from "~/lib/types" import { useGetSummary } from "~/queries/page" export const PostMeta: React.FC<{ - page: Note - site?: Profile | null - author?: Profile | null -}> = ({ page, site, author }) => { + page: ExpandedNote + site?: ExpandedCharacter +}> = ({ page, site }) => { const { t } = useTranslation("common") const date = useDate() const [isMounted, setIsMounted] = useState(false) const { i18n } = useTranslation() const summary = useGetSummary({ - cid: toCid(page.related_urls?.[0] || ""), + cid: toCid(page.metadata?.uri || ""), lang: i18n.resolvedLanguage, }) @@ -32,7 +28,7 @@ export const PostMeta: React.FC<{ }, []) const [showEdit, setShowEdit] = useState(false) - const userRole = useUserRole(site?.username) + const userRole = useUserRole(site?.handle) useEffect(() => { if (userRole.isSuccess && userRole.data) { setShowEdit(true) @@ -43,19 +39,23 @@ export const PostMeta: React.FC<{
    - {page.tags?.filter((tag) => tag !== "post" && tag !== "page").length ? ( + {page.metadata?.content?.tags?.filter( + (tag) => tag !== "post" && tag !== "page", + ).length ? ( <> - {page.tags + {page.metadata?.content?.tags ?.filter((tag) => tag !== "post" && tag !== "page") .map((tag) => ( - {page.views} + {page.metadata?.content?.views} - {author?.username && site?.username !== author?.username && ( - <> - - - - - {author?.name} - - - - - )} - url.startsWith(CSB_SCAN + "/tx/"), - )?.[0] - } + href={`${CSB_SCAN}/tx/${page.updatedTransactionHash}`} > {showEdit && ( Edit diff --git a/src/components/site/SiteArchives.tsx b/src/components/site/SiteArchives.tsx index 34531852..78b3baae 100644 --- a/src/components/site/SiteArchives.tsx +++ b/src/components/site/SiteArchives.tsx @@ -2,9 +2,11 @@ import { useTranslation } from "next-i18next" import Link from "next/link" import { useMemo } from "react" +import type { InfiniteData } from "@tanstack/react-query" + import { Button } from "~/components/ui/Button" import { useDate } from "~/hooks/useDate" -import { Note, Notes } from "~/lib/types" +import { ExpandedNote } from "~/lib/types" import { EmptyState } from "../ui/EmptyState" import { UniLink } from "../ui/UniLink" @@ -12,14 +14,17 @@ import { UniLink } from "../ui/UniLink" export const SiteArchives: React.FC<{ title?: string showTags?: boolean - postPages?: Notes[] + posts?: InfiniteData<{ + list: ExpandedNote[] + count: number + }> fetchNextPage: () => void hasNextPage?: boolean isFetchingNextPage?: boolean }> = ({ title, showTags, - postPages, + posts, fetchNextPage, hasNextPage, isFetchingNextPage, @@ -28,13 +33,16 @@ export const SiteArchives: React.FC<{ const date = useDate() const { t } = useTranslation(["common", "site"]) - const groupedByYear = useMemo>(() => { + const groupedByYear = useMemo>(() => { const map = new Map() - if (postPages?.length) { - for (const posts of postPages) { - for (const post of posts.list) { - const year = date.formatDate(post.date_published, "YYYY") + if (posts?.pages?.length) { + for (const page of posts.pages) { + for (const post of page.list) { + const year = date.formatDate( + post.metadata?.content?.date_published || "", + "YYYY", + ) const items = map.get(year) || [] items.push(post) map.set(year, items) @@ -43,15 +51,15 @@ export const SiteArchives: React.FC<{ } return map - }, [postPages, date]) + }, [posts?.pages, date]) const tags = useMemo>(() => { const result = new Map() - if (postPages?.length) { - for (const posts of postPages) { - for (const post of posts.list) { - post.tags?.forEach((tag) => { + if (posts?.pages?.length) { + for (const page of posts.pages) { + for (const post of page.list) { + post.metadata?.content?.tags?.forEach((tag) => { if (tag !== "post" && tag !== "page") { if (result.has(tag)) { result.set(tag, result.get(tag) + 1) @@ -65,21 +73,21 @@ export const SiteArchives: React.FC<{ } return result - }, [postPages]) + }, [posts?.pages]) - if (!postPages?.length) return null + if (!posts?.pages?.length) return null return ( <>

    {title || t("Archives", { ns: "site" })}

    - {!postPages[0].total && ( + {!posts?.pages[0].count && (
    )} - {!!postPages[0].total && ( + {!!posts?.pages[0].count && ( <> {showTags && tags.size > 0 && (
    @@ -100,7 +108,6 @@ export const SiteArchives: React.FC<{ )}
    {[...groupedByYear.keys()].map((year) => { - currentLength++ const posts = groupedByYear.get(year)! return (
    @@ -108,16 +115,21 @@ export const SiteArchives: React.FC<{ {year} {posts.map((post) => { + currentLength++ return ( - {post.title} + + {post.metadata?.content?.title} + {t("intlDateTime", { - val: new Date(post.date_published), + val: new Date( + post.metadata?.content?.date_published || "", + ), formatParams: { val: { month: "short", @@ -140,8 +152,8 @@ export const SiteArchives: React.FC<{ isLoading={isFetchingNextPage} aria-label="load more" > - There are {postPages[0].total - currentLength} more post - {postPages[0].total - currentLength > 1 ? "s" : ""}, click to + There are {posts?.pages[0].count - currentLength} more post + {posts?.pages[0].count - currentLength > 1 ? "s" : ""}, click to load more )} diff --git a/src/components/site/SiteFooter.tsx b/src/components/site/SiteFooter.tsx index 99035841..137700de 100644 --- a/src/components/site/SiteFooter.tsx +++ b/src/components/site/SiteFooter.tsx @@ -5,15 +5,14 @@ import { useEffect, useState } from "react" import { Logo } from "~/components/common/Logo" import { Platform } from "~/components/site/Platform" import { SITE_URL } from "~/lib/env" -import { Note, Profile } from "~/lib/types" +import { ExpandedCharacter } from "~/lib/types" import { DarkModeSwitch } from "../common/DarkModeSwitch" import { UniLink } from "../ui/UniLink" export const SiteFooter: React.FC<{ - site?: Profile | null - page?: Note | null -}> = ({ site, page }) => { + site?: ExpandedCharacter +}> = ({ site }) => { const [logoType, setLogoType] = useState<"svg" | "png" | "lottie">("svg") useEffect(() => { @@ -38,7 +37,7 @@ export const SiteFooter: React.FC<{
    © - {site?.name} + {site?.metadata?.content?.name} ยท
    - {site?.connected_accounts && ( + {site?.metadata?.content?.connected_accounts && (
    - {site?.connected_accounts.map((account, index) => ( - - ))} + {site?.metadata?.content?.connected_accounts.map( + (account, index) => { + const match = account.match(/:\/\/account:(.*)@(.*)/) + if (match) { + return ( + + ) + } + }, + )}
    )}
    - {site?.ga && ( + {site?.metadata?.content?.ga && (
    diff --git a/src/components/site/SiteHeader.tsx b/src/components/site/SiteHeader.tsx index 8589565a..f51f21f5 100644 --- a/src/components/site/SiteHeader.tsx +++ b/src/components/site/SiteHeader.tsx @@ -18,7 +18,7 @@ import { Modal } from "~/components/ui/Modal" import { Tooltip } from "~/components/ui/Tooltip" import { useIsDark } from "~/hooks/useDarkMode" import { CSB_IO, CSB_SCAN, CSB_XCHAR } from "~/lib/env" -import { Profile } from "~/lib/types" +import { ExpandedCharacter } from "~/lib/types" import { getUserContentsUrl } from "~/lib/user-contents" import { cn } from "~/lib/utils" @@ -58,25 +58,28 @@ const HeaderLink: React.FC<{ link: HeaderLinkType }> = ({ link }) => { } export const SiteHeader: React.FC<{ - site?: Profile | undefined | null + site?: ExpandedCharacter }> = ({ site }) => { const { t } = useTranslation("site") - const leftLinks: HeaderLinkType[] = site?.navigation?.find( + const leftLinks: HeaderLinkType[] = site?.metadata?.content?.navigation?.find( (nav) => nav.url === "/", ) - ? site.navigation - : [{ label: "Home", url: "/" }, ...(site?.navigation || [])] + ? site.metadata?.content?.navigation + : [ + { label: "Home", url: "/" }, + ...(site?.metadata?.content?.navigation || []), + ] const moreMenuItems = [ { text: "View on xChar", icon: , - url: `${CSB_XCHAR}/${site?.username}`, + url: `${CSB_XCHAR}/${site?.handle}`, }, { text: "View on xFeed", icon: , - url: `${CSB_IO}/@${site?.username}`, + url: `${CSB_IO}/@${site?.handle}`, }, { text: "View on Hoot It", @@ -91,12 +94,12 @@ export const SiteHeader: React.FC<{ />
    ), - url: `https://hoot.it/search/${site?.username}.csb/activities`, + url: `https://hoot.it/search/${site?.handle}.csb/activities`, }, { text: "View on Crossbell Scan", icon: , - url: `${CSB_SCAN}/address/${site?.metadata?.owner}`, + url: `${CSB_SCAN}/address/${site?.owner}`, }, { text: "Subscribe to JSON Feed", @@ -196,12 +199,14 @@ export const SiteHeader: React.FC<{ }} > {(() => { - switch (site?.banners?.[0]?.mime_type?.split("/")[0]) { + switch ( + site?.metadata?.content?.banners?.[0]?.mime_type?.split("/")[0] + ) { case "image": return ( banner} @@ -211,7 +216,7 @@ export const SiteHeader: React.FC<{ return (