feat: home optimization - reuse layout

This commit is contained in:
DIYgod 2022-09-22 02:03:05 +01:00
parent a14d04edbe
commit 051690f764
No known key found for this signature in database
GPG Key ID: D159328F47A80DCA
7 changed files with 141 additions and 132 deletions

View File

@ -1,38 +1,90 @@
import clsx from "clsx"
import React, { useEffect } from "react"
import { getUserContentsUrl } from "~/lib/user-contents"
import { SEOHead } from "../common/SEOHead"
import { SiteNavigationItem, Viewer, Profile, Note } from "~/lib/types"
import { SiteFooter } from "./SiteFooter"
import { SiteHeader } from "./SiteHeader"
import { useRouter } from "next/router"
import { useStore } from "~/lib/store"
import { BlockchainInfo } from "~/components/common/BlockchainInfo"
import type { Links } from "unidata.js"
import { GetServerSideProps } from "next"
import {
prefetchGetSite,
prefetchGetSiteSubscriptions,
} from "~/queries/site.server"
import { prefetchGetPagesBySite } from "~/queries/page.server"
import { PageVisibilityEnum } from "~/lib/types"
import { useGetSiteSubscriptions } from "~/queries/site"
import { dehydrate } from "@tanstack/react-query"
import { queryClientServer } from "~/lib/query-client.server"
import { useGetSite } from "~/queries/site"
import { fetchGetPage } from "~/queries/page.server"
import { notFound } from "~/lib/server-side-props"
import { useGetPage } from "~/queries/page"
export type SiteLayoutProps = {
site?: Profile
viewer?: Profile | null
children: React.ReactNode
title?: string | null
ogDescription?: string | null
page?: Note
subscriptions?: Links | null
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const domainOrSubdomain = ctx.params!.site as string
const pageSlug = ctx.params!.page as string
const tag = ctx.params!.tag as string
await prefetchGetSite(domainOrSubdomain)
await prefetchGetSiteSubscriptions({
siteId: domainOrSubdomain,
})
if (pageSlug) {
const page = await fetchGetPage({
site: domainOrSubdomain,
page: pageSlug,
render: true,
includeAuthors: true,
})
if (new Date(page!.date_published) > new Date()) {
throw notFound()
}
} else {
await prefetchGetPagesBySite({
site: domainOrSubdomain,
take: 1000,
type: "post",
visibility: PageVisibilityEnum.Published,
render: true,
...(tag && { tags: [tag] }),
})
}
return {
props: {
dehydratedState: dehydrate(queryClientServer),
},
}
}
export const SiteLayout: React.FC<SiteLayoutProps> = ({
site,
viewer,
children,
title,
ogDescription,
page,
subscriptions,
}) => {
export type SiteLayoutProps = {
children: React.ReactNode
title?: string | null
}
export const SiteLayout: React.FC<SiteLayoutProps> = ({ children, title }) => {
const router = useRouter()
const domainOrSubdomain = router.query.site as string
const pageSlug = router.query.page as string
const tag = router.query.tag as string
const page = useGetPage({
site: domainOrSubdomain,
page: pageSlug,
render: true,
includeAuthors: true,
})
const setSubscribeModalOpened = useStore(
(store) => store.setSubscribeModalOpened,
)
const site = useGetSite(domainOrSubdomain)
const subscriptions = useGetSiteSubscriptions({
siteId: domainOrSubdomain,
})
useEffect(() => {
if ("subscription" in router.query) {
@ -43,25 +95,26 @@ export const SiteLayout: React.FC<SiteLayoutProps> = ({
return (
<>
<SEOHead
title={title || page?.title || ""}
siteName={site?.name || ""}
title={title || tag || page.data?.title || ""}
siteName={site.data?.name || ""}
description={
ogDescription ?? site?.description?.replace(/<[^>]*>/g, "")
(page.data?.summary?.content || page.data?.body?.content) ??
site.data?.description?.replace(/<[^>]*>/g, "")
}
image={page?.cover || getUserContentsUrl(site?.avatars?.[0])}
icon={getUserContentsUrl(site?.avatars?.[0])}
image={page.data?.cover || getUserContentsUrl(site.data?.avatars?.[0])}
icon={getUserContentsUrl(site.data?.avatars?.[0])}
/>
<SiteHeader site={site} subscriptions={subscriptions} />
<style>{site?.css}</style>
<SiteHeader site={site.data} subscriptions={subscriptions.data} />
<style>{site.data?.css}</style>
<div
className={`xlog-post-id-${page?.id} max-w-screen-md mx-auto px-5 pt-12`}
className={`xlog-post-id-${page.data?.id} max-w-screen-md mx-auto px-5 pt-12`}
>
{children}
</div>
<div className="max-w-screen-md mx-auto pt-12 pb-10">
<BlockchainInfo site={site} page={page} />
<BlockchainInfo site={site.data} page={page.data} />
</div>
<SiteFooter site={site} page={page} />
<SiteFooter site={site.data} page={page.data} />
</>
)
}

View File

@ -1,14 +1,11 @@
import type { PageType } from "~/lib/db.server"
import { Rendered } from "~/markdown"
import { PageContent } from "../common/PageContent"
import { PostMeta } from "./PostMeta"
import { PostFooter } from "./PostFooter"
import { Profile, Note } from "~/lib/types"
import { Note } from "~/lib/types"
export const SitePage: React.FC<{
site?: Profile
page?: Note
}> = ({ site, page }) => {
}> = ({ page }) => {
return (
<>
<div className="">

View File

@ -71,6 +71,8 @@ const queryClient = new QueryClient({
const persister = createIDBPersister()
function MyApp({ Component, pageProps }: any) {
const getLayout = Component.getLayout ?? ((page: any) => page)
return (
<WagmiConfig client={wagmiClient}>
<RainbowKitProvider chains={chains}>
@ -82,7 +84,7 @@ function MyApp({ Component, pageProps }: any) {
<Hydrate state={pageProps.dehydratedState}>
<ReactQueryDevtools />
<IpfsGatewayContext.Provider value={ipfsGateway}>
<Component {...pageProps} />
{getLayout(<Component {...pageProps} />)}
</IpfsGatewayContext.Provider>
<Toaster />
</Hydrate>

View File

@ -1,31 +1,21 @@
import { GetServerSideProps } from "next"
import { SiteLayout } from "~/components/site/SiteLayout"
import {
SiteLayout,
getServerSideProps as getLayoutServerSideProps,
} from "~/components/site/SiteLayout"
import { SitePage } from "~/components/site/SitePage"
import { serverSidePropsHandler } from "~/lib/server-side-props"
import { queryClientServer } from "~/lib/query-client.server"
import { prefetchGetSite } from "~/queries/site.server"
import { useGetSite } from "~/queries/site"
import { dehydrate, QueryClient } from "@tanstack/react-query"
import { fetchGetPage } from "~/queries/page.server"
import { dehydrate } from "@tanstack/react-query"
import { useGetPage } from "~/queries/page"
import { notFound } from "~/lib/server-side-props"
import type { ReactElement } from "react"
export const getServerSideProps: GetServerSideProps = serverSidePropsHandler(
async (ctx) => {
const domainOrSubdomain = ctx.params!.site as string
const pageSlug = ctx.params!.page as string
await prefetchGetSite(domainOrSubdomain)
const page = await fetchGetPage({
site: domainOrSubdomain,
page: pageSlug,
render: true,
includeAuthors: true,
})
if (new Date(page!.date_published) > new Date()) {
throw notFound()
}
await getLayoutServerSideProps(ctx)
return {
props: {
@ -50,15 +40,12 @@ function SitePagePage({
render: true,
includeAuthors: true,
})
const ogDescription = page.data?.summary?.content || page.data?.body?.content
const site = useGetSite(domainOrSubdomain)
return <SitePage page={page.data} />
}
return (
<SiteLayout site={site.data} ogDescription={ogDescription} page={page.data}>
<SitePage site={site.data} page={page.data} />
</SiteLayout>
)
SitePagePage.getLayout = (page: ReactElement) => {
return <SiteLayout>{page}</SiteLayout>
}
export default SitePagePage

View File

@ -1,27 +1,21 @@
import { GetServerSideProps } from "next"
import { SiteLayout } from "~/components/site/SiteLayout"
import {
SiteLayout,
getServerSideProps as getLayoutServerSideProps,
} from "~/components/site/SiteLayout"
import { serverSidePropsHandler } from "~/lib/server-side-props"
import { SiteArchives } from "~/components/site/SiteArchives"
import { Viewer, Profile, Notes } from "~/lib/types"
import { Profile, Notes } from "~/lib/types"
import { queryClientServer } from "~/lib/query-client.server"
import { prefetchGetSite } from "~/queries/site.server"
import { useGetSite } from "~/queries/site"
import { dehydrate, QueryClient } from "@tanstack/react-query"
import { dehydrate } from "@tanstack/react-query"
import { useGetPagesBySite } from "~/queries/page"
import { prefetchGetPagesBySite } from "~/queries/page.server"
import { PageVisibilityEnum } from "~/lib/types"
import type { ReactElement } from "react"
export const getServerSideProps: GetServerSideProps = serverSidePropsHandler(
async (ctx) => {
const domainOrSubdomain = ctx.params!.site as string
await prefetchGetSite(domainOrSubdomain)
await prefetchGetPagesBySite({
site: domainOrSubdomain,
take: 1000,
type: "post",
visibility: PageVisibilityEnum.Published,
})
await getLayoutServerSideProps(ctx)
return {
props: {
@ -39,19 +33,19 @@ function SiteArchivesPage({
posts: Notes
domainOrSubdomain: string
}) {
const site = useGetSite(domainOrSubdomain)
const posts = useGetPagesBySite({
site: domainOrSubdomain,
take: 1000,
type: "post",
visibility: PageVisibilityEnum.Published,
render: true,
})
return (
<SiteLayout site={site.data} title="Archives">
<SiteArchives posts={posts.data} />
</SiteLayout>
)
return <SiteArchives posts={posts.data} />
}
SiteArchivesPage.getLayout = (page: ReactElement) => {
return <SiteLayout title="Archives">{page}</SiteLayout>
}
export default SiteArchivesPage

View File

@ -1,32 +1,18 @@
import { GetServerSideProps } from "next"
import { SiteHome } from "~/components/site/SiteHome"
import { SiteLayout } from "~/components/site/SiteLayout"
import { queryClientServer } from "~/lib/query-client.server"
import {
prefetchGetSite,
prefetchGetSiteSubscriptions,
} from "~/queries/site.server"
import { useGetSite } from "~/queries/site"
import { dehydrate, QueryClient } from "@tanstack/react-query"
SiteLayout,
getServerSideProps as getLayoutServerSideProps,
} from "~/components/site/SiteLayout"
import { queryClientServer } from "~/lib/query-client.server"
import { dehydrate } from "@tanstack/react-query"
import { useGetPagesBySite } from "~/queries/page"
import { prefetchGetPagesBySite } from "~/queries/page.server"
import { PageVisibilityEnum } from "~/lib/types"
import { useGetSiteSubscriptions } from "~/queries/site"
import type { ReactElement } from "react"
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const domainOrSubdomain = ctx.params!.site as string
await prefetchGetSite(domainOrSubdomain)
await prefetchGetPagesBySite({
site: domainOrSubdomain,
take: 1000,
type: "post",
visibility: PageVisibilityEnum.Published,
render: true,
})
await prefetchGetSiteSubscriptions({
siteId: domainOrSubdomain,
})
await getLayoutServerSideProps(ctx)
return {
props: {
@ -37,7 +23,6 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
}
function SiteIndexPage({ domainOrSubdomain }: { domainOrSubdomain: string }) {
const site = useGetSite(domainOrSubdomain)
const posts = useGetPagesBySite({
site: domainOrSubdomain,
take: 1000,
@ -45,15 +30,12 @@ function SiteIndexPage({ domainOrSubdomain }: { domainOrSubdomain: string }) {
visibility: PageVisibilityEnum.Published,
render: true,
})
const subscriptions = useGetSiteSubscriptions({
siteId: domainOrSubdomain,
})
return (
<SiteLayout site={site.data} subscriptions={subscriptions.data}>
<SiteHome posts={posts.data} />
</SiteLayout>
)
return <SiteHome posts={posts.data} />
}
SiteIndexPage.getLayout = (page: ReactElement) => {
return <SiteLayout>{page}</SiteLayout>
}
export default SiteIndexPage

View File

@ -1,29 +1,23 @@
import { GetServerSideProps } from "next"
import { SiteLayout } from "~/components/site/SiteLayout"
import {
SiteLayout,
getServerSideProps as getLayoutServerSideProps,
} from "~/components/site/SiteLayout"
import { serverSidePropsHandler } from "~/lib/server-side-props"
import { SiteArchives } from "~/components/site/SiteArchives"
import { Viewer, Profile, Notes } from "~/lib/types"
import { Profile, Notes } from "~/lib/types"
import { queryClientServer } from "~/lib/query-client.server"
import { prefetchGetSite } from "~/queries/site.server"
import { useGetSite } from "~/queries/site"
import { dehydrate, QueryClient } from "@tanstack/react-query"
import { dehydrate } from "@tanstack/react-query"
import { useGetPagesBySite } from "~/queries/page"
import { prefetchGetPagesBySite } from "~/queries/page.server"
import { PageVisibilityEnum } from "~/lib/types"
import type { ReactElement } from "react"
export const getServerSideProps: GetServerSideProps = serverSidePropsHandler(
async (ctx) => {
const domainOrSubdomain = ctx.params!.site as string
const tag = ctx.params!.tag as string
await prefetchGetSite(domainOrSubdomain)
await prefetchGetPagesBySite({
site: domainOrSubdomain,
take: 1000,
type: "post",
visibility: PageVisibilityEnum.Published,
tags: [tag],
})
await getLayoutServerSideProps(ctx)
return {
props: {
@ -35,7 +29,7 @@ export const getServerSideProps: GetServerSideProps = serverSidePropsHandler(
},
)
function SiteArchivesPage({
function SiteTagPage({
domainOrSubdomain,
tag,
}: {
@ -44,20 +38,20 @@ function SiteArchivesPage({
domainOrSubdomain: string
tag: string
}) {
const site = useGetSite(domainOrSubdomain)
const posts = useGetPagesBySite({
site: domainOrSubdomain,
take: 1000,
type: "post",
visibility: PageVisibilityEnum.Published,
render: true,
tags: [tag],
})
return (
<SiteLayout site={site.data} title={tag}>
<SiteArchives posts={posts.data} title={tag} />
</SiteLayout>
)
return <SiteArchives posts={posts.data} title={tag} />
}
export default SiteArchivesPage
SiteTagPage.getLayout = (page: ReactElement) => {
return <SiteLayout>{page}</SiteLayout>
}
export default SiteTagPage