From 146c10874ab478eae7dd079215d488dde6338f9f Mon Sep 17 00:00:00 2001 From: Innei Date: Fri, 28 Jul 2023 01:02:06 +0800 Subject: [PATCH] feat: preview page base on postMessage --- src/app/preview/page.tsx | 190 +++++++++++++++++- src/atoms/preview.ts | 4 + src/components/ui/link-card/LinkCard.tsx | 2 +- src/components/widgets/peek/NotePreview.tsx | 2 +- src/components/widgets/peek/PostPreview.tsx | 2 +- src/lib/url-builder.ts | 6 +- .../article/MarkdownImageRecordProvider.tsx | 4 +- 7 files changed, 198 insertions(+), 12 deletions(-) create mode 100644 src/atoms/preview.ts diff --git a/src/app/preview/page.tsx b/src/app/preview/page.tsx index df9b9b257d..390398e3ae 100644 --- a/src/app/preview/page.tsx +++ b/src/app/preview/page.tsx @@ -1,6 +1,188 @@ -import { NormalContainer } from '~/components/layout/container/Normal' +'use client' -// TODO -export default () => { - return TODO +import { useEffect, useMemo } from 'react' +import Balancer from 'react-wrap-balancer' +import { atom, useAtomValue } from 'jotai' +import type { + NoteModel, + NoteWrappedPayload, + PostModel, +} from '@mx-space/api-client' + +import { simpleCamelcaseKeys } from '@mx-space/api-client' + +import { previewDataAtom } from '~/atoms/preview' +import { ErrorBoundary } from '~/components/common/ErrorBoundary' +import { Paper } from '~/components/layout/container/Paper' +import { NoteBanner, NoteMetaBar } from '~/components/widgets/note' +import { PostActionAside } from '~/components/widgets/post' +import { ArticleRightAside } from '~/components/widgets/shared/ArticleRightAside' +import { debounce } from '~/lib/_' +import { jotaiStore } from '~/lib/store' +import { isNoteModel, isPageModel, isPostModel } from '~/lib/url-builder' +import { + CurrentNoteDataAtomProvider, + CurrentNoteDataProvider, +} from '~/providers/note/CurrentNoteDataProvider' +import { + CurrentPostDataAtomProvider, + CurrentPostDataProvider, +} from '~/providers/post/CurrentPostDataProvider' +import { + LayoutRightSidePortal, + LayoutRightSideProvider, +} from '~/providers/shared/LayoutRightSideProvider' +import { WrappedElementProvider } from '~/providers/shared/WrappedElementProvider' + +import { + IndentArticleContainer, + NoteHeaderDate, + NoteMarkdown, + NoteMarkdownImageRecordProvider, + NoteTitle, +} from '../notes/[id]/pageExtra' +import { + PostMarkdown, + PostMarkdownImageRecordProvider, + PostMetaBarInternal, +} from '../posts/(post-detail)/[category]/[slug]/pageExtra' + +export default function PreviewPage() { + useEffect(() => { + const search = location.search + const searchParams = new URLSearchParams(search) + + let targinOrigin = searchParams.get('origin') + + if (!targinOrigin) { + return + } + targinOrigin = decodeURIComponent(targinOrigin) + window.opener.postMessage('Preview Page Ready', targinOrigin) + + window.addEventListener( + 'message', + debounce((e) => { + if (e.origin !== targinOrigin) { + return + } + + const parsedData = JSON.parse(e.data) + + if (parsedData.type === 'preview') { + jotaiStore.set(previewDataAtom, simpleCamelcaseKeys(parsedData.data)) + } + }, 100), + ) + }, []) + + const previewData = useAtomValue(previewDataAtom) + + // console.log(previewData) + if (!previewData) { + return null + } + + switch (true) { + case isNoteModel(previewData): + return + case isPostModel(previewData): + return + + case isPageModel(previewData): + return
TODO
+ } + + return null +} + +const PostPreview = () => { + const data = useAtomValue(previewDataAtom) as PostModel + const overrideAtom = useMemo(() => atom(null as null | PostModel), []) + return ( +
+ + +
+
+
+

+ {data.title} +

+ + +
+ + + + + + + + + + + + + +
+ + +
+
+
+ ) +} + +const NotePreview = () => { + const data = useAtomValue(previewDataAtom) as NoteModel + + const overrideAtom = useMemo( + () => atom(null as null | NoteWrappedPayload), + [], + ) + return ( +
+ + { + return { + prev: undefined, + next: undefined, + data: { + ...data, + images: data.images ?? [], + count: data.count ?? { + read: 0, + like: 0, + }, + }, + } as NoteWrappedPayload + }, [data])} + /> + + +
+ + + + + +
+ +
+
+ + + + + + + + +
+
+
+
+ ) } diff --git a/src/atoms/preview.ts b/src/atoms/preview.ts new file mode 100644 index 0000000000..05893814b8 --- /dev/null +++ b/src/atoms/preview.ts @@ -0,0 +1,4 @@ +import { atom } from 'jotai' +import type { NoteModel, PostModel } from '@mx-space/api-client' + +export const previewDataAtom = atom(null) diff --git a/src/components/ui/link-card/LinkCard.tsx b/src/components/ui/link-card/LinkCard.tsx index c9d2168fca..e3acabe099 100644 --- a/src/components/ui/link-card/LinkCard.tsx +++ b/src/components/ui/link-card/LinkCard.tsx @@ -37,7 +37,7 @@ export const LinkCard = (props: LinkCardProps) => { ) } const LinkCardImpl: FC = (props) => { - const { id, source = 'self', className } = props + const { id = '', source = 'self', className } = props const [loading, setLoading] = useState(true) const [isError, setIsError] = useState(false) diff --git a/src/components/widgets/peek/NotePreview.tsx b/src/components/widgets/peek/NotePreview.tsx index c7dfcf3119..c59c53c6c1 100644 --- a/src/components/widgets/peek/NotePreview.tsx +++ b/src/components/widgets/peek/NotePreview.tsx @@ -34,7 +34,7 @@ export const NotePreview: FC = (props) => { }) const overrideAtom = useMemo( () => atom(null as null | NoteWrappedPayload), - [data], + [], ) if (isLoading) return if (!data) return null diff --git a/src/components/widgets/peek/PostPreview.tsx b/src/components/widgets/peek/PostPreview.tsx index 176798a143..6356992b02 100644 --- a/src/components/widgets/peek/PostPreview.tsx +++ b/src/components/widgets/peek/PostPreview.tsx @@ -31,7 +31,7 @@ export const PostPreview: FC = (props) => { const { data, isLoading } = useQuery({ ...queries.post.bySlug(category, slug), }) - const overrideAtom = useMemo(() => atom(null as null | PostModel), [data]) + const overrideAtom = useMemo(() => atom(null as null | PostModel), []) if (isLoading) return if (!data) return null return ( diff --git a/src/lib/url-builder.ts b/src/lib/url-builder.ts index 442f97bbb4..152f503a6b 100644 --- a/src/lib/url-builder.ts +++ b/src/lib/url-builder.ts @@ -13,19 +13,19 @@ export function urlBuilder(path = '') { return new URL(path, getAggregationData()?.url.webUrl) } -function isPostModel(model: any): model is PostModel { +export function isPostModel(model: any): model is PostModel { return ( isDefined(model.title) && isDefined(model.slug) && !isDefined(model.order) ) } -function isPageModel(model: any): model is PageModel { +export function isPageModel(model: any): model is PageModel { return ( isDefined(model.title) && isDefined(model.slug) && isDefined(model.order) ) } -function isNoteModel(model: any): model is NoteModel { +export function isNoteModel(model: any): model is NoteModel { return isDefined(model.title) && isDefined(model.nid) } diff --git a/src/providers/article/MarkdownImageRecordProvider.tsx b/src/providers/article/MarkdownImageRecordProvider.tsx index ae768dcf4d..272c81f3f4 100644 --- a/src/providers/article/MarkdownImageRecordProvider.tsx +++ b/src/providers/article/MarkdownImageRecordProvider.tsx @@ -11,10 +11,10 @@ const MarkdownImageRecordProviderInternal = createContext(atom([] as Image[])) export const MarkdownImageRecordProvider: Component<{ images: Image[] }> = ({ children, images }) => { - const atomRef = useRefValue(() => atom([...images] as Image[])) + const atomRef = useRefValue(() => atom(images as Image[])) useEffect(() => { - jotaiStore.set(atomRef, [...images]) + jotaiStore.set(atomRef, images) }, [images]) return (