Skip to content

Commit

Permalink
refactor: use jotai to holder data
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei committed Jun 23, 2023
1 parent e3dac55 commit 561c2e9
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 220 deletions.
5 changes: 2 additions & 3 deletions src/app/notes/[id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { headers } from 'next/dist/client/components/headers'
import type { Metadata } from 'next'

import { QueryHydration } from '~/components/common/QueryHydration'
import { BottomToUpTransitionView } from '~/components/ui/transition/BottomToUpTransitionView'
import { REQUEST_QUERY } from '~/constants/system'
import { attachUA } from '~/lib/attach-ua'
import { getSummaryFromMd } from '~/lib/markdown'
import { CurrentNoteDataProvider } from '~/providers/note/CurrentNodeDataProvider'
import { CurrentNoteIdProvider } from '~/providers/note/CurrentNoteIdProvider'
import { queries } from '~/queries/definition'
import { getQueryClient } from '~/utils/query-client.server'
Expand Down Expand Up @@ -71,9 +71,8 @@ export default async (
return (
<>
<CurrentNoteIdProvider noteId={id} />
{/* <CurrentNoteDataProvider data={data} /> */}
<CurrentNoteDataProvider data={data} />

<QueryHydration queryKey={query.queryKey} data={data} />
<BottomToUpTransitionView className="min-w-0">
<Paper>{props.children}</Paper>
</BottomToUpTransitionView>
Expand Down
120 changes: 73 additions & 47 deletions src/app/notes/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ import { Balancer } from 'react-wrap-balancer'
import clsx from 'clsx'
import dayjs from 'dayjs'
import dynamic from 'next/dynamic'
import type { Image, NoteModel } from '@mx-space/api-client'
import type { Image } from '@mx-space/api-client'
import type { MarkdownToJSX } from '~/components/ui/markdown'
import type { PropsWithChildren } from 'react'

import { BanCopyWrapper } from '~/components/common/BanCopyWrapper'
import { ClientOnly } from '~/components/common/ClientOnly'
import { MdiClockOutline } from '~/components/icons/clock'
import { useSetHeaderMetaInfo } from '~/components/layout/header/hooks'
import { FloatPopover } from '~/components/ui/float-popover'
import { Loading } from '~/components/ui/loading'
import { Markdown } from '~/components/ui/markdown'
import { XLogInfoForNote, XLogSummaryForNote } from '~/components/widgets/xlog'
import { useCurrentNoteData } from '~/hooks/data/use-note'
import { noopArr } from '~/lib/noop'
import { MarkdownImageRecordProvider } from '~/providers/article/MarkdownImageRecordProvider'
import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider'
import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider'
import { LayoutRightSidePortal } from '~/providers/shared/LayoutRightSideProvider'
import { WrappedElementProvider } from '~/providers/shared/WrappedElementProvider'
import { parseDate } from '~/utils/datetime'
Expand Down Expand Up @@ -59,33 +60,76 @@ const TocAutoScroll = dynamic(() =>
)

const PageImpl = () => {
const note = useCurrentNoteData()
return (
<>
<NotePage />
<NoteHeaderMetaInfoSetting />
</>
)
}

const NoteHeaderMetaInfoSetting = () => {
const setHeaderMetaInfo = useSetHeaderMetaInfo()
useEffect(() => {
if (!note?.title) return
setHeaderMetaInfo({
const meta = useCurrentNoteDataSelector((data) => {
if (!data) return null
const note = data.data

return {
title: note?.title,
description: `手记${note.topic?.name ? ` / ${note.topic?.name}` : ''}`,
slug: note?.nid.toString(),
})
}, [note?.nid, note?.title, note?.topic?.name])
}
})

if (!note) {
return <Loading useDefaultLoadingText />
}
useEffect(() => {
if (meta) setHeaderMetaInfo(meta)
}, [meta])

// return null
return <NotePage note={note} />
return null
}

const NotePage = memo(({ note }: { note: NoteModel }) => {
const tips = `创建于 ${parseDate(note.created, 'YYYY 年 M 月 D 日 dddd')}${
note.modified
? `,修改于 ${parseDate(note.modified, 'YYYY 年 M 月 D 日 dddd')}`
const NoteHeaderDate = () => {
const date = useCurrentNoteDataSelector((data) => ({
created: data?.data.created,
modified: data?.data.modified,
}))
if (!date?.created) return null

const tips = `创建于 ${parseDate(date.created, 'YYYY 年 M 月 D 日 dddd')}${
date.modified
? `,修改于 ${parseDate(date.modified, 'YYYY 年 M 月 D 日 dddd')}`
: ''
}`

return (
<FloatPopover as="span" TriggerComponent={NoteDateMeta}>
{tips}
</FloatPopover>
)
}

const NoteMarkdown = () => {
const text = useCurrentNoteDataSelector((data) => data?.data.text)
if (!text) return null

return <Markdown as="main" renderers={MarkdownRenderers} value={text} />
}
const NoteMarkdownImageRecordProvider = (props: PropsWithChildren) => {
const images = useCurrentNoteDataSelector(
(data) => data?.data.images || (noopArr as Image[]),
)
if (!images) return null

return (
<MarkdownImageRecordProvider images={images}>
{props.children}
</MarkdownImageRecordProvider>
)
}
const NotePage = memo(() => {
const noteId = useCurrentNoteId()
if (!noteId) return null

return (
<Suspense>
<article
Expand All @@ -98,9 +142,7 @@ const NotePage = memo(({ note }: { note: NoteModel }) => {
<header>
<NoteTitle />
<span className="flex flex-wrap items-center text-[13px] text-neutral-content/60">
<FloatPopover as="span" TriggerComponent={NoteDateMeta}>
{tips}
</FloatPopover>
<NoteHeaderDate />

<ClientOnly>
<NoteMetaBar />
Expand All @@ -111,17 +153,11 @@ const NotePage = memo(({ note }: { note: NoteModel }) => {
<NoteHideIfSecret>
<XLogSummaryForNote />
<WrappedElementProvider>
<MarkdownImageRecordProvider
images={note.images || (noopArr as Image[])}
>
<NoteMarkdownImageRecordProvider>
<BanCopyWrapper>
<Markdown
as="main"
renderers={MarkdownRenderers}
value={note.text}
/>
<NoteMarkdown />
</BanCopyWrapper>
</MarkdownImageRecordProvider>
</NoteMarkdownImageRecordProvider>

<LayoutRightSidePortal>
<TocAside
Expand All @@ -138,17 +174,16 @@ const NotePage = memo(({ note }: { note: NoteModel }) => {
</article>

<SubscribeBell defaultType="note_c" />
<NoteTopic topic={note.topic} />
<NoteTopic />
<XLogInfoForNote />
<NoteFooterNavigationBarForMobile noteId={note.nid.toString()} />
<NoteFooterNavigationBarForMobile noteId={noteId} />
</Suspense>
)
})

const NoteTitle = () => {
const note = useCurrentNoteData()
if (!note) return null
const title = note.title
const title = useCurrentNoteDataSelector((data) => data?.data.title)
if (!title) return null
return (
<h1 className="mt-8 text-left font-bold text-base-content/95">
<Balancer>{title}</Balancer>
Expand All @@ -157,10 +192,9 @@ const NoteTitle = () => {
}

const NoteDateMeta = () => {
const note = useCurrentNoteData()
if (!note) return null

const dateFormat = dayjs(note.created)
const created = useCurrentNoteDataSelector((data) => data?.data.created)
if (!created) return null
const dateFormat = dayjs(created)
.locale('zh-cn')
.format('YYYY 年 M 月 D 日 dddd')

Expand All @@ -187,11 +221,3 @@ const MarkdownRenderers: { [name: string]: Partial<MarkdownToJSX.Rule> } = {
}

export default PageImpl
// export default PageDataHolder(PageImpl, () => {
// const { id } = useParams() as { id: string }

// useEffect(() => {
// springScrollToTop()
// }, [id])
// return useNoteByNidQuery(id)
// })
64 changes: 19 additions & 45 deletions src/components/widgets/note/NoteActionAside.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
'use client'

import { useQueryClient } from '@tanstack/react-query'
import { motion, useAnimationControls, useForceUpdate } from 'framer-motion'
import { produce } from 'immer'
import type { NoteWrappedPayload } from '@mx-space/api-client'

import { MotionButtonBase } from '~/components/ui/button'
import { useIsClient } from '~/hooks/common/use-is-client'
import { useCurrentNoteData } from '~/hooks/data/use-note'
import { routeBuilder, Routes } from '~/lib/route-builder'
import { toast } from '~/lib/toast'
import { urlBuilder } from '~/lib/url-builder'
import {
getCurrentNoteData,
setCurrentNoteData,
useCurrentNoteDataSelector,
} from '~/providers/note/CurrentNodeDataProvider'
import { useCurrentNoteId } from '~/providers/note/CurrentNoteIdProvider'
import { useAggregationData } from '~/providers/root/aggregation-data-provider'
import { queries } from '~/queries/definition'
import { isLikedBefore, setLikeId } from '~/utils/cookie'
import { clsxm } from '~/utils/helper'
import { apiClient } from '~/utils/request'
Expand All @@ -35,50 +36,20 @@ export const NoteActionAside: Component = ({ className }) => {
}

const LikeButton = () => {
const note = useCurrentNoteData()

const queryClient = useQueryClient()
const control = useAnimationControls()
const [update] = useForceUpdate()
if (!note) return null
const id = note.id
const handleLike = () => {
// queryClient.setQueriesData(
// queries.note.byNid(note.nid.toString()),
// (old: any) => {
// // return produce(old as NoteWrappedPayload, (draft) => {
// // draft.data.count.like += 1
// // draft
// // })
// // old.data.count.like += 1
// // old.data.count = { ...old.data.count }
// // old.data = { ...old.data }
// return {
// ...old,
// data: {
// ...old.data,
// text: `1${Math.random()}`,
// // count: {
// // ...old.data.count,
// // like: old.data.count.like + 1,
// // },
// },
// }
// },
// )

// return
const id = useCurrentNoteDataSelector((data) => data?.data.id)
const nid = useCurrentNoteId()
if (!id) return null
const handleLike = () => {
if (isLikedBefore(id)) return
if (!nid) return
apiClient.note.likeIt(id).then(() => {
setLikeId(id)
queryClient.setQueriesData(
queries.note.byNid(note.nid.toString()),
(old: any) => {
return produce(old as NoteWrappedPayload, (draft) => {
draft.data.count.like += 1
})
},
)
setCurrentNoteData((draft) => {
draft.data.count.like += 1
})
update()
})
}
Expand Down Expand Up @@ -138,10 +109,9 @@ const LikeButton = () => {
const ShareButton = () => {
const hasShare = 'share' in navigator
const isClient = useIsClient()
const note = useCurrentNoteData()

const aggregation = useAggregationData()
if (!isClient) return null
if (!note) return null

if (!hasShare) {
return null
Expand All @@ -152,6 +122,10 @@ const ShareButton = () => {
aria-label="Share This Note Button"
className="flex flex-col space-y-2"
onClick={() => {
const note = getCurrentNoteData()?.data

if (!note) return

navigator.share({
title: note.title,
text: note.text,
Expand Down
14 changes: 9 additions & 5 deletions src/components/widgets/note/NoteFooterNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ import type { FC } from 'react'
import { MdiClockTimeThreeOutline } from '~/components/icons/clock'
import { Divider } from '~/components/ui/divider'
import { OnlyMobile } from '~/components/ui/viewport/OnlyMobile'
import { useNoteByNidQuery } from '~/hooks/data/use-note'
import { routeBuilder, Routes } from '~/lib/route-builder'
import { useCurrentNoteDataSelector } from '~/providers/note/CurrentNodeDataProvider'
import { springScrollToTop } from '~/utils/scroller'

export const NoteFooterNavigation: FC<{ noteId: string }> = ({
noteId: id,
}) => {
const { data } = useNoteByNidQuery(id, (data) => ({
nextNid: data.next?.nid,
prevNid: data.prev?.nid,
}))
const data = useCurrentNoteDataSelector((data) =>
!data
? null
: {
nextNid: data?.next?.nid,
prevNid: data?.prev?.nid,
},
)

const router = useRouter()

Expand Down
Loading

0 comments on commit 561c2e9

Please sign in to comment.