| @@ -3,11 +3,12 @@ import { match } from 'path-to-regexp' | |||||
| import { fetchPost, fetchPosts, fetchPostChanges } from '@/lib/posts' | import { fetchPost, fetchPosts, fetchPostChanges } from '@/lib/posts' | ||||
| import { postsKeys, wikiKeys } from '@/lib/queryKeys' | import { postsKeys, wikiKeys } from '@/lib/queryKeys' | ||||
| import { fetchWikiPages } from '@/lib/wiki' | |||||
| import { fetchWikiPageByTitle, fetchWikiPages } from '@/lib/wiki' | |||||
| type Prefetcher = (qc: QueryClient, url: URL) => Promise<void> | type Prefetcher = (qc: QueryClient, url: URL) => Promise<void> | ||||
| const mPost = match<{ id: string }> ('/posts/:id') | const mPost = match<{ id: string }> ('/posts/:id') | ||||
| const mWiki = match<{ title: string }> ('/wiki/:title') | |||||
| const prefetchWikiPagesIndex: Prefetcher = async (qc, url) => { | const prefetchWikiPagesIndex: Prefetcher = async (qc, url) => { | ||||
| @@ -18,6 +19,19 @@ const prefetchWikiPagesIndex: Prefetcher = async (qc, url) => { | |||||
| } | } | ||||
| const prefetchWikiPageShow: Prefetcher = async (qc, url) => { | |||||
| const m = mWiki (url.pathname) | |||||
| if (!(m)) | |||||
| return | |||||
| const version = url.searchParams.get ('version') | |||||
| const { title } = m.params | |||||
| await qc.prefetchQuery ({ | |||||
| queryKey: wikiKeys.show (title, version ? { version } : { }), | |||||
| queryFn: () => fetchWikiPageByTitle (title, version ? { version } : { }) }) | |||||
| } | |||||
| const prefetchPostsIndex: Prefetcher = async (qc, url) => { | const prefetchPostsIndex: Prefetcher = async (qc, url) => { | ||||
| const tags = url.searchParams.get ('tags') ?? '' | const tags = url.searchParams.get ('tags') ?? '' | ||||
| const m = url.searchParams.get ('match') === 'any' ? 'any' : 'all' | const m = url.searchParams.get ('match') === 'any' ? 'any' : 'all' | ||||
| @@ -53,11 +67,15 @@ const prefetchPostChanges: Prefetcher = async (qc, url) => { | |||||
| export const routePrefetchers: { test: (u: URL) => boolean; run: Prefetcher }[] = [ | export const routePrefetchers: { test: (u: URL) => boolean; run: Prefetcher }[] = [ | ||||
| { test: u => u.pathname === '/' || u.pathname === '/posts', run: prefetchPostsIndex }, | { test: u => u.pathname === '/' || u.pathname === '/posts', run: prefetchPostsIndex }, | ||||
| { test: u => (['/posts/new', '/posts/changes'].includes(u.pathname) | |||||
| { test: u => (['/posts/new', '/posts/changes'].includes (u.pathname) | |||||
| && Boolean (mPost (u.pathname))), | && Boolean (mPost (u.pathname))), | ||||
| run: prefetchPostShow }, | run: prefetchPostShow }, | ||||
| { test: u => u.pathname === '/posts/changes', run: prefetchPostChanges }, | { test: u => u.pathname === '/posts/changes', run: prefetchPostChanges }, | ||||
| { test: u => u.pathname === '/wiki', run: prefetchWikiPagesIndex }] | |||||
| { test: u => u.pathname === '/wiki', run: prefetchWikiPagesIndex }, | |||||
| { test: u => (['/wiki/new', '/wiki/changes'].includes (u.pathname) | |||||
| && Boolean (mWiki (u.pathname))), | |||||
| run: prefetchWikiPageShow }, | |||||
| ] | |||||
| export const prefetchForURL = async (qc: QueryClient, urlLike: string): Promise<void> => { | export const prefetchForURL = async (qc: QueryClient, urlLike: string): Promise<void> => { | ||||
| @@ -10,4 +10,4 @@ export const postsKeys = { | |||||
| export const wikiKeys = { | export const wikiKeys = { | ||||
| root: ['wiki'] as const, | root: ['wiki'] as const, | ||||
| index: (p: { title: string }) => ['wiki', 'index', p] as const, | index: (p: { title: string }) => ['wiki', 'index', p] as const, | ||||
| show: (title: string, p: { version: string }) => ['wiki', title, p] as const } | |||||
| show: (title: string, p: { version?: string }) => ['wiki', title, p] as const } | |||||
| @@ -1,3 +1,4 @@ | |||||
| import { useQuery } from '@tanstack/react-query' | |||||
| import { useEffect, useState } from 'react' | import { useEffect, useState } from 'react' | ||||
| import { Helmet } from 'react-helmet-async' | import { Helmet } from 'react-helmet-async' | ||||
| import { useLocation, useNavigate, useParams } from 'react-router-dom' | import { useLocation, useNavigate, useParams } from 'react-router-dom' | ||||
| @@ -12,10 +13,11 @@ import MainArea from '@/components/layout/MainArea' | |||||
| import { SITE_TITLE } from '@/config' | import { SITE_TITLE } from '@/config' | ||||
| import { WikiIdBus } from '@/lib/eventBus/WikiIdBus' | import { WikiIdBus } from '@/lib/eventBus/WikiIdBus' | ||||
| import { fetchPosts } from '@/lib/posts' | import { fetchPosts } from '@/lib/posts' | ||||
| import { wikiKeys } from '@/lib/queryKeys' | |||||
| import { fetchTagByName } from '@/lib/tags' | import { fetchTagByName } from '@/lib/tags' | ||||
| import { fetchWikiPage, fetchWikiPageByTitle } from '@/lib/wiki' | import { fetchWikiPage, fetchWikiPageByTitle } from '@/lib/wiki' | ||||
| import type { Post, Tag, WikiPage } from '@/types' | |||||
| import type { Post, Tag } from '@/types' | |||||
| export default () => { | export default () => { | ||||
| @@ -29,16 +31,25 @@ export default () => { | |||||
| const [posts, setPosts] = useState<Post[]> ([]) | const [posts, setPosts] = useState<Post[]> ([]) | ||||
| const [tag, setTag] = useState (defaultTag) | const [tag, setTag] = useState (defaultTag) | ||||
| const [wikiPage, setWikiPage] = useState<WikiPage | null | undefined> (undefined) | |||||
| const query = new URLSearchParams (location.search) | const query = new URLSearchParams (location.search) | ||||
| const version = query.get ('version') | const version = query.get ('version') | ||||
| const { data: wikiPage } = useQuery ({ | |||||
| enabled: Boolean (title) && !(/^\d+$/.test (title)), | |||||
| queryKey: wikiKeys.show (title ?? '', version ? { version } : { }), | |||||
| queryFn: () => fetchWikiPageByTitle (title ?? '', version ? { version } : { }) }) | |||||
| if (wikiPage) | |||||
| { | |||||
| if (wikiPage.title !== title) | |||||
| navigate (`/wiki/${ encodeURIComponent(wikiPage.title) }`, { replace: true }) | |||||
| WikiIdBus.set (wikiPage.id) | |||||
| } | |||||
| useEffect (() => { | useEffect (() => { | ||||
| if (/^\d+$/.test (title)) | if (/^\d+$/.test (title)) | ||||
| { | { | ||||
| void (async () => { | void (async () => { | ||||
| setWikiPage (undefined) | |||||
| try | try | ||||
| { | { | ||||
| const data = await fetchWikiPage (title, { }) | const data = await fetchWikiPage (title, { }) | ||||
| @@ -53,22 +64,6 @@ export default () => { | |||||
| return | return | ||||
| } | } | ||||
| void (async () => { | |||||
| setWikiPage (undefined) | |||||
| try | |||||
| { | |||||
| const data = await fetchWikiPageByTitle (title, version ? { version } : { }) | |||||
| if (data.title !== title) | |||||
| navigate (`/wiki/${ encodeURIComponent(data.title) }`, { replace: true }) | |||||
| setWikiPage (data) | |||||
| WikiIdBus.set (data.id) | |||||
| } | |||||
| catch | |||||
| { | |||||
| setWikiPage (null) | |||||
| } | |||||
| }) () | |||||
| setPosts ([]) | setPosts ([]) | ||||
| void (async () => { | void (async () => { | ||||
| try | try | ||||