feat: use nextjs image
This commit is contained in:
parent
ca40896de8
commit
d6d7993234
|
|
@ -44,5 +44,10 @@ module.exports = withBundleAnalyzer(
|
|||
ipfsGateway: {
|
||||
gatewayPath: "/_ipfs/:cid/:pathToResource*",
|
||||
},
|
||||
|
||||
images: {
|
||||
dangerouslyAllowSVG: true,
|
||||
domains: ["4everland.xyz"],
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
"refractor": "^4.8.0",
|
||||
"rehype-prism-plus": "^1.5.0",
|
||||
"rehype-raw": "^6.1.1",
|
||||
"rehype-react": "^7.1.1",
|
||||
"rehype-sanitize": "^5.0.1",
|
||||
"rehype-stringify": "^9.0.3",
|
||||
"remark-frontmatter": "^4.0.1",
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ specifiers:
|
|||
refractor: ^4.8.0
|
||||
rehype-prism-plus: ^1.5.0
|
||||
rehype-raw: ^6.1.1
|
||||
rehype-react: ^7.1.1
|
||||
rehype-sanitize: ^5.0.1
|
||||
rehype-stringify: ^9.0.3
|
||||
remark-frontmatter: ^4.0.1
|
||||
|
|
@ -176,6 +177,7 @@ dependencies:
|
|||
refractor: 4.8.0
|
||||
rehype-prism-plus: 1.5.0
|
||||
rehype-raw: 6.1.1
|
||||
rehype-react: 7.1.1_@types+react@18.0.21
|
||||
rehype-sanitize: 5.0.1
|
||||
rehype-stringify: 9.0.3
|
||||
remark-frontmatter: 4.0.1
|
||||
|
|
@ -1563,6 +1565,13 @@ packages:
|
|||
'@lezer/highlight': 1.1.0
|
||||
dev: false
|
||||
|
||||
/@mapbox/hast-util-table-cell-style/0.2.0:
|
||||
resolution: {integrity: sha512-gqaTIGC8My3LVSnU38IwjHVKJC94HSonjvFHDk8/aSrApL8v4uWgm8zJkK7MJIIbHuNOr/+Mv2KkQKcxs6LEZA==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
unist-util-visit: 1.4.1
|
||||
dev: false
|
||||
|
||||
/@metamask/safe-event-emitter/2.0.0:
|
||||
resolution: {integrity: sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==}
|
||||
dev: false
|
||||
|
|
@ -8669,6 +8678,19 @@ packages:
|
|||
unified: 10.1.2
|
||||
dev: false
|
||||
|
||||
/rehype-react/7.1.1_@types+react@18.0.21:
|
||||
resolution: {integrity: sha512-6yaitxM95JFsuTA74OH54OyvTAeRqR4/A6f45S2sEk2FEG04iGgsObcmEIFQRsjK9pfAhc74lR4iGf/W2G/sBw==}
|
||||
peerDependencies:
|
||||
'@types/react': '>=17'
|
||||
dependencies:
|
||||
'@mapbox/hast-util-table-cell-style': 0.2.0
|
||||
'@types/hast': 2.3.4
|
||||
'@types/react': 18.0.21
|
||||
hast-to-hyperscript: 10.0.1
|
||||
hast-util-whitespace: 2.0.0
|
||||
unified: 10.1.2
|
||||
dev: false
|
||||
|
||||
/rehype-sanitize/5.0.1:
|
||||
resolution: {integrity: sha512-da/jIOjq8eYt/1r9GN6GwxIR3gde7OZ+WV8pheu1tL8K0D9KxM2AyMh+UEfke+FfdM3PvGHeYJU0Td5OWa7L5A==}
|
||||
dependencies:
|
||||
|
|
@ -9692,6 +9714,10 @@ packages:
|
|||
resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==}
|
||||
dev: false
|
||||
|
||||
/unist-util-is/3.0.0:
|
||||
resolution: {integrity: sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==}
|
||||
dev: false
|
||||
|
||||
/unist-util-is/5.1.1:
|
||||
resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==}
|
||||
dev: false
|
||||
|
|
@ -9708,6 +9734,12 @@ packages:
|
|||
'@types/unist': 2.0.6
|
||||
dev: false
|
||||
|
||||
/unist-util-visit-parents/2.1.2:
|
||||
resolution: {integrity: sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==}
|
||||
dependencies:
|
||||
unist-util-is: 3.0.0
|
||||
dev: false
|
||||
|
||||
/unist-util-visit-parents/5.1.0:
|
||||
resolution: {integrity: sha512-y+QVLcY5eR/YVpqDsLf/xh9R3Q2Y4HxkZTp7ViLDU6WtJCEcPmRzW1gpdWDCDIqIlhuPDXOgttqPlykrHYDekg==}
|
||||
dependencies:
|
||||
|
|
@ -9722,6 +9754,12 @@ packages:
|
|||
unist-util-is: 5.1.1
|
||||
dev: false
|
||||
|
||||
/unist-util-visit/1.4.1:
|
||||
resolution: {integrity: sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==}
|
||||
dependencies:
|
||||
unist-util-visit-parents: 2.1.2
|
||||
dev: false
|
||||
|
||||
/unist-util-visit/4.1.1:
|
||||
resolution: {integrity: sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==}
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -1,16 +1,27 @@
|
|||
import clsx from "clsx"
|
||||
import { useCodeCopy } from "~/hooks/useCodeCopy"
|
||||
import { renderPageContent } from "~/markdown"
|
||||
|
||||
export const PageContent: React.FC<{
|
||||
contentHTML: string
|
||||
content?: string
|
||||
className?: string
|
||||
}> = ({ contentHTML, className }) => {
|
||||
}> = ({ className, content }) => {
|
||||
useCodeCopy()
|
||||
|
||||
// TODO
|
||||
// const [element, setElement] = useState<ReactElement>()
|
||||
// const renderMarkdown = useCallback((doc: string) => {
|
||||
// setElement(renderPageContent(doc).element)
|
||||
// }, [])
|
||||
// useEffect(() => {
|
||||
// if (content) {
|
||||
// renderMarkdown(content)
|
||||
// }
|
||||
// }, [content, renderMarkdown])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("xlog-post-content", `prose`, className)}
|
||||
dangerouslySetInnerHTML={{ __html: contentHTML }}
|
||||
></div>
|
||||
<div className={clsx("xlog-post-content", `prose`, className)}>
|
||||
{content && renderPageContent(content).element}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,9 +279,9 @@ export const PagesManager: React.FC<{
|
|||
const file = e.target?.files?.[0]
|
||||
const reader = new FileReader()
|
||||
reader.readAsText(file, "UTF-8")
|
||||
reader.onload = async (evt) => {
|
||||
reader.onload = (evt) => {
|
||||
if (evt.target?.result) {
|
||||
const pageContent = await renderPageContent(
|
||||
const pageContent = renderPageContent(
|
||||
evt.target.result as string,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import type { Link } from "unidata.js"
|
|||
import { getSiteSubscriptions } from "~/models/site.model"
|
||||
import { CharacterList } from "~/components/common/CharacterList"
|
||||
import type { Links } from "unidata.js"
|
||||
import { Image } from "~/components/ui/Image"
|
||||
|
||||
export type HeaderLinkType = {
|
||||
icon?: React.ReactNode
|
||||
|
|
@ -184,8 +185,7 @@ export const SiteHeader: React.FC<{
|
|||
<header className="xlog-header border-b relative">
|
||||
<div className="xlog-banner absolute top-0 bottom-0 left-0 right-0 -z-10 overflow-hidden">
|
||||
{site?.banners?.[0]?.mime_type.split("/")[0] === "image" && (
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
<img
|
||||
<Image
|
||||
className="max-w-screen-md mx-auto object-cover h-full w-full"
|
||||
src={site?.banners?.[0]?.address}
|
||||
alt="banner"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { formatDate } from "~/lib/date"
|
|||
import { Paginated, type PostOnSiteHome, Notes } from "~/lib/types"
|
||||
import { EmptyState } from "../ui/EmptyState"
|
||||
import { useRouter } from "next/router"
|
||||
import { Image } from "~/components/ui/Image"
|
||||
|
||||
export const SiteHome: React.FC<{
|
||||
posts?: Notes
|
||||
|
|
@ -20,7 +21,7 @@ export const SiteHome: React.FC<{
|
|||
const excerpt = post.summary?.content
|
||||
return (
|
||||
<Link key={post.id} href={`/${post.slug || post.id}`}>
|
||||
<a className="xlog-post hover:bg-zinc-100 transition-colors p-5 -mx-5 first:-mt-5 md:rounded-xl flex">
|
||||
<a className="xlog-post hover:bg-zinc-100 transition-colors p-5 -mx-5 first:-mt-5 md:rounded-xl flex items-center">
|
||||
<div className="flex-1 flex justify-center flex-col">
|
||||
<h3 className="xlog-post-title text-2xl font-bold">
|
||||
{post.title}
|
||||
|
|
@ -56,16 +57,16 @@ export const SiteHome: React.FC<{
|
|||
{excerpt && "..."}
|
||||
</div>
|
||||
</div>
|
||||
<div className="xlog-post-cover flex items-center">
|
||||
{post.cover && (
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
<img
|
||||
className="object-cover w-24 h-24 rounded ml-4"
|
||||
{post.cover && (
|
||||
<div className="xlog-post-cover flex items-center relative w-24 h-24 ml-4">
|
||||
<Image
|
||||
className="object-cover rounded w-24 h-24"
|
||||
alt="cover"
|
||||
layout="fill"
|
||||
src={post.cover}
|
||||
></img>
|
||||
)}
|
||||
</div>
|
||||
></Image>
|
||||
</div>
|
||||
)}
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export const SiteLayout: React.FC<SiteLayoutProps> = ({ children, title }) => {
|
|||
title={title || tag || page.data?.title || ""}
|
||||
siteName={site.data?.name || ""}
|
||||
description={
|
||||
(page.data?.summary?.content || page.data?.body?.content) ??
|
||||
page.data?.summary?.content ??
|
||||
site.data?.description?.replace(/<[^>]*>/g, "")
|
||||
}
|
||||
image={page.data?.cover || getUserContentsUrl(site.data?.avatars?.[0])}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ export const SitePage: React.FC<{
|
|||
)}
|
||||
{page?.tags?.includes("post") && <PostMeta page={page} />}
|
||||
</div>
|
||||
<PageContent contentHTML={page?.body?.content || ""} className="mt-10" />
|
||||
<PageContent
|
||||
className="mt-10"
|
||||
content={page?.body?.content}
|
||||
></PageContent>
|
||||
<PostFooter page={page} />
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import clsx from "clsx"
|
||||
import React, { useMemo } from "react"
|
||||
import { toGateway } from "~/lib/ipfs-parser"
|
||||
import { Image } from "~/components/ui/Image"
|
||||
|
||||
export const Avatar: React.FC<
|
||||
{
|
||||
|
|
@ -61,8 +62,7 @@ export const Avatar: React.FC<
|
|||
height: `${size}px`,
|
||||
}}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
<Image
|
||||
className="overflow-hidden"
|
||||
src={image}
|
||||
width={size}
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
import { FC, useCallback, useEffect, useState } from "react"
|
||||
import { renderPageContent } from "~/markdown"
|
||||
import { PageContent } from "../common/PageContent"
|
||||
|
||||
export interface EditorPreviewProps {
|
||||
className?: string
|
||||
content: string
|
||||
}
|
||||
|
||||
export const EditorPreview: FC<EditorPreviewProps> = ({
|
||||
className,
|
||||
content,
|
||||
}) => {
|
||||
const [html, setHtml] = useState("")
|
||||
const renderMarkdown = useCallback(async (doc: string) => {
|
||||
const pageContent = await renderPageContent(doc)
|
||||
setHtml(pageContent.contentHTML)
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
renderMarkdown(content)
|
||||
}, [content, renderMarkdown])
|
||||
return <PageContent className={className} contentHTML={html ?? ""} />
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import React from "react"
|
||||
import { default as NextImage, ImageProps } from "next/image"
|
||||
import { toGateway, toIPFS } from "~/lib/ipfs-parser"
|
||||
import { isIpfsUrl } from "@crossbell/ipfs-gateway"
|
||||
import clsx from "clsx"
|
||||
|
||||
export const Image: React.FC<
|
||||
{
|
||||
className?: string
|
||||
src?: string
|
||||
width?: number | string
|
||||
height?: number | string
|
||||
} & React.HTMLAttributes<HTMLImageElement> &
|
||||
ImageProps
|
||||
> = ({ layout, className, alt, src, width, height, ...props }) => {
|
||||
src = toIPFS(src)
|
||||
const [paddingTop, setPaddingTop] = React.useState("0")
|
||||
|
||||
return (
|
||||
<>
|
||||
{isIpfsUrl(src) ? (
|
||||
<span
|
||||
className={clsx(
|
||||
"relative inline-flex justify-center",
|
||||
!width && !width && !layout ? "w-full h-full" : "",
|
||||
)}
|
||||
style={{ paddingTop }}
|
||||
>
|
||||
<NextImage
|
||||
{...props}
|
||||
src={toGateway(src, {
|
||||
forceFallback: true,
|
||||
})}
|
||||
className={className}
|
||||
alt={alt}
|
||||
width={width}
|
||||
height={height}
|
||||
layout={!width && !height ? "fill" : layout}
|
||||
onLoad={({ target }) => {
|
||||
if (!width && !width && !layout) {
|
||||
const { naturalWidth, naturalHeight } =
|
||||
target as HTMLImageElement
|
||||
setPaddingTop(
|
||||
`calc(100% / (${naturalWidth} / ${naturalHeight})`,
|
||||
)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
) : (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img
|
||||
{...props}
|
||||
src={toGateway(src, {
|
||||
forceFallback: true,
|
||||
})}
|
||||
className={className}
|
||||
alt={alt}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -7,13 +7,17 @@ const IPFS_PREFIX = "ipfs://"
|
|||
|
||||
export type ToGatewayConfig = {
|
||||
needRequestAtServerSide?: boolean
|
||||
forceFallback?: boolean
|
||||
}
|
||||
|
||||
export const toGateway = (url: string, config?: ToGatewayConfig) => {
|
||||
const ipfsUrl = toIPFS(url)
|
||||
|
||||
if (isIpfsUrl(ipfsUrl)) {
|
||||
if (config?.needRequestAtServerSide && typeof window === "undefined") {
|
||||
if (
|
||||
(config?.needRequestAtServerSide && typeof window === "undefined") ||
|
||||
config?.forceFallback
|
||||
) {
|
||||
return ipfsGateway.getFallbackWeb2Url(ipfsUrl)
|
||||
} else {
|
||||
return ipfsGateway.getSwWeb2Url(ipfsUrl)
|
||||
|
|
@ -31,4 +35,5 @@ export const toIPFS = (url: string) => {
|
|||
.replace("https://ipfs.io/ipfs/", IPFS_PREFIX)
|
||||
.replace("https://cf-ipfs.com/ipfs/", IPFS_PREFIX)
|
||||
.replace("https://ipfs.4everland.xyz/ipfs/", IPFS_PREFIX)
|
||||
.replace("https://rss3.mypinata.cloud/ipfs/", IPFS_PREFIX)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { Note as UniNote, Profile as UniProfile } from "unidata.js"
|
||||
import { ReactElement } from "react"
|
||||
|
||||
export type Site = {
|
||||
id: string
|
||||
|
|
@ -75,6 +76,12 @@ export type Note = UniNote & {
|
|||
slug?: string
|
||||
character?: Profile
|
||||
cover?: string
|
||||
body?: {
|
||||
content?: string
|
||||
address?: string
|
||||
mime_type?: string
|
||||
element?: ReactElement
|
||||
}
|
||||
}
|
||||
|
||||
export type Notes = {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ import { allowedBlockquoteAttrs, remarkCallout } from "./remark-callout"
|
|||
import { rehypeExternalLink } from "./rehyper-external-link"
|
||||
import { rehypeWrapCode } from "./rehype-wrap-code"
|
||||
import jsYaml from "js-yaml"
|
||||
import rehypeReact from "rehype-react"
|
||||
import { createElement, ReactElement } from "react"
|
||||
import { Image } from "~/components/ui/Image"
|
||||
|
||||
export type MarkdownEnv = {
|
||||
excerpt: string
|
||||
|
|
@ -25,6 +28,7 @@ export type MarkdownEnv = {
|
|||
|
||||
export type Rendered = {
|
||||
contentHTML: string
|
||||
element?: ReactElement
|
||||
excerpt: string
|
||||
frontMatter: Record<string, any>
|
||||
cover: string
|
||||
|
|
@ -34,7 +38,10 @@ refractor.alias("html", ["svelte", "vue"])
|
|||
|
||||
const rehypePrism = rehypePrismGenerator(refractor)
|
||||
|
||||
export const renderPageContent = async (content: string): Promise<Rendered> => {
|
||||
export const renderPageContent = (
|
||||
content: string,
|
||||
html?: boolean,
|
||||
): Rendered => {
|
||||
const env: MarkdownEnv = {
|
||||
excerpt: "",
|
||||
__internal: {},
|
||||
|
|
@ -42,7 +49,7 @@ export const renderPageContent = async (content: string): Promise<Rendered> => {
|
|||
cover: "",
|
||||
}
|
||||
|
||||
const result = await unified()
|
||||
const result = unified()
|
||||
.use(remarkParse)
|
||||
.use(rehypeStringify)
|
||||
.use(remarkFrontmatter, ["yaml"])
|
||||
|
|
@ -98,12 +105,19 @@ export const renderPageContent = async (content: string): Promise<Rendered> => {
|
|||
.use(rehypeTable)
|
||||
.use(rehypeExternalLink)
|
||||
.use(rehypeWrapCode)
|
||||
.process(content)
|
||||
.use(html ? () => (tree: any) => {} : rehypeReact, {
|
||||
createElement: createElement,
|
||||
components: {
|
||||
img: Image as any,
|
||||
},
|
||||
})
|
||||
.processSync(content)
|
||||
|
||||
const contentHTML = result.toString()
|
||||
|
||||
return {
|
||||
contentHTML,
|
||||
element: result.result,
|
||||
excerpt: env.excerpt,
|
||||
frontMatter: env.frontMatter,
|
||||
cover: env.cover,
|
||||
|
|
|
|||
|
|
@ -91,16 +91,16 @@ export async function createOrUpdatePage(input: {
|
|||
)
|
||||
}
|
||||
|
||||
const expandPage = async (page: Note, render: boolean) => {
|
||||
const expandPage = (page: Note, render: boolean) => {
|
||||
if (
|
||||
page.body?.content &&
|
||||
page.body?.mime_type === "text/markdown" &&
|
||||
render
|
||||
) {
|
||||
const rendered = await renderPageContent(page.body.content)
|
||||
const rendered = renderPageContent(page.body.content, true)
|
||||
page.body = {
|
||||
content: rendered.contentHTML,
|
||||
mime_type: "text/html",
|
||||
content: page.body.content,
|
||||
mime_type: "text/markdown",
|
||||
}
|
||||
if (!page.summary) {
|
||||
page.summary = {
|
||||
|
|
@ -237,12 +237,10 @@ export async function getPagesBySite(input: {
|
|||
.sort((a, b) => +new Date(b.date_published) - +new Date(a.date_published))
|
||||
pages.total = pages.list.length
|
||||
|
||||
pages.list = await Promise.all(
|
||||
pages?.list.map(async (page) => {
|
||||
await expandPage(page, input.render || false)
|
||||
return page
|
||||
}),
|
||||
)
|
||||
pages?.list.map((page) => {
|
||||
expandPage(page, input.render || false)
|
||||
return page
|
||||
})
|
||||
}
|
||||
|
||||
return pages
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ const expandSite = async (site: Profile) => {
|
|||
(a: any) => a.trait_type === "xlog_custom_domain",
|
||||
)?.value || ""
|
||||
site.name = site.name || site.username
|
||||
site.description = (await renderPageContent(site.bio || "")).contentHTML
|
||||
site.description = renderPageContent(site.bio || "", true).contentHTML
|
||||
|
||||
if (site.avatars) {
|
||||
site.avatars = site.avatars.map((avatar) => toGateway(avatar))
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { fetchGetPagesBySite } from "~/queries/page.server"
|
|||
import { PageVisibilityEnum } from "~/lib/types"
|
||||
import { getSiteLink } from "~/lib/helpers"
|
||||
import { QueryClient } from "@tanstack/react-query"
|
||||
import { renderPageContent } from "~/markdown"
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||
const queryClient = new QueryClient()
|
||||
|
|
@ -36,7 +37,9 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
|||
items: pages.list?.map((page) => ({
|
||||
id: page.id,
|
||||
title: page.title,
|
||||
content_html: page.body?.content,
|
||||
content_html:
|
||||
page.body?.content &&
|
||||
renderPageContent(page.body?.content, true).contentHTML,
|
||||
summary: page.summary?.content,
|
||||
url: `${link}/${page.slug || page.id}`,
|
||||
image: page.cover,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import { DashboardLayout } from "~/components/dashboard/DashboardLayout"
|
|||
import { DashboardMain } from "~/components/dashboard/DashboardMain"
|
||||
import { PublishButton } from "~/components/dashboard/PublishButton"
|
||||
import { useEditor } from "~/components/ui/Editor"
|
||||
import { EditorPreview } from "~/components/ui/EditorPreview"
|
||||
import { EditorToolbar } from "~/components/ui/EditorToolbar"
|
||||
import { Input } from "~/components/ui/Input"
|
||||
import { UniLink } from "~/components/ui/UniLink"
|
||||
|
|
@ -23,6 +22,7 @@ import { useGetSite } from "~/queries/site"
|
|||
import { getStorage, setStorage, delStorage } from "~/lib/storage"
|
||||
import { nanoid } from "nanoid"
|
||||
import { useQueryClient } from "@tanstack/react-query"
|
||||
import { PageContent } from "~/components/common/PageContent"
|
||||
|
||||
const getInputDatetimeValue = (date: Date | string) => {
|
||||
const str = dayjs(date).format()
|
||||
|
|
@ -265,10 +265,10 @@ export default function SubdomainEditor() {
|
|||
className="px-5 h-full border-r w-1/2 overflow-scroll"
|
||||
ref={editorRef}
|
||||
></div>
|
||||
<EditorPreview
|
||||
<PageContent
|
||||
className="px-5 w-1/2 overflow-scroll pb-[200px]"
|
||||
content={content}
|
||||
></EditorPreview>
|
||||
></PageContent>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { MainLayout } from "~/components/main/MainLayout"
|
|||
import { UniLink } from "~/components/ui/UniLink"
|
||||
import { FLY_REGION } from "~/lib/env.server"
|
||||
import { useAccount } from "wagmi"
|
||||
import Image from "next/image"
|
||||
import { EllipsisHorizontalIcon } from "@heroicons/react/20/solid"
|
||||
import { LoveIcon } from "~/components/icons/LoveIcon"
|
||||
import { BlockchainIcon } from "~/components/icons/BlockchainIcon"
|
||||
|
|
@ -15,6 +14,7 @@ import { useRouter } from "next/router"
|
|||
import { GITHUB_LINK, APP_NAME, CSB_SCAN } from "~/lib/env"
|
||||
import { getSiteLink } from "~/lib/helpers"
|
||||
import { Link, Element } from "react-scroll"
|
||||
import { Image } from "~/components/ui/Image"
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||
return {
|
||||
|
|
@ -234,12 +234,13 @@ export default function Home({ region }: { region: string | null }) {
|
|||
subdomain: item.username,
|
||||
})}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
className="rounded-full w-14 h-14"
|
||||
<Image
|
||||
className="rounded-full"
|
||||
src={`/_ipfs/${item.avartar}`}
|
||||
alt={item.username}
|
||||
></img>
|
||||
width="56"
|
||||
height="56"
|
||||
></Image>
|
||||
</UniLink>
|
||||
</li>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Reference in New Issue