このコミットが含まれているのは:
@@ -14,11 +14,63 @@ import { fetchWikiPage } from '@/lib/wiki'
|
||||
|
||||
import type { FC, MouseEvent } from 'react'
|
||||
|
||||
import type { Menu, User } from '@/types'
|
||||
import type { Menu, Tag, User } from '@/types'
|
||||
|
||||
type Props = { user: User | null }
|
||||
|
||||
|
||||
export const menuOutline = ({ tag, wikiId, user }: { tag?: Tag | null
|
||||
wikiId: number | null
|
||||
user: User | null }): Menu => {
|
||||
const postCount = tag?.postCount ?? 0
|
||||
|
||||
const wikiPageFlg = Boolean (/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId)
|
||||
const wikiTitle = location.pathname.split ('/')[2] ?? ''
|
||||
|
||||
return [
|
||||
{ name: '広場', to: '/posts', subMenu: [
|
||||
{ name: '一覧', to: '/posts' },
|
||||
{ name: '検索', to: '/posts/search' },
|
||||
{ name: '追加', to: '/posts/new' },
|
||||
{ name: '履歴', to: '/posts/changes' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:広場' }] },
|
||||
{ name: 'タグ', to: '/tags', subMenu: [
|
||||
{ name: 'マスタ', to: '/tags' },
|
||||
{ name: '別名タグ', to: '/tags/aliases', visible: false },
|
||||
{ name: '上位タグ', to: '/tags/implications', visible: false },
|
||||
{ name: 'ニコニコ連携', to: '/tags/nico' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:タグ' }] },
|
||||
{ name: '素材', to: '/materials', visible: false, subMenu: [
|
||||
{ name: '一覧', to: '/materials' },
|
||||
{ name: '検索', to: '/materials/search', visible: false },
|
||||
{ name: '追加', to: '/materials/new' },
|
||||
{ name: '履歴', to: '/materials/changes', visible: false },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:素材集' }] },
|
||||
{ name: '上映会', to: '/theatres/1', base: '/theatres', subMenu: [
|
||||
{ name: <>第 1 会場</>, to: '/theatres/1' },
|
||||
{ name: 'CyTube', to: '//cytube.mm428.net/r/deernijika' },
|
||||
{ name: <>ニジカ放送局第 1 チャンネル</>,
|
||||
to: '//www.youtube.com/watch?v=DCU3hL4Uu6A' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:上映会' }] },
|
||||
{ name: 'Wiki', to: '/wiki/ヘルプ:ホーム', base: '/wiki', subMenu: [
|
||||
{ name: '検索', to: '/wiki' },
|
||||
{ name: '新規', to: '/wiki/new' },
|
||||
{ name: '全体履歴', to: '/wiki/changes' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:Wiki' },
|
||||
{ component: <Separator/>, visible: wikiPageFlg },
|
||||
{ name: `広場 (${ postCount || 0 })`, to: `/posts?tags=${ wikiTitle }`,
|
||||
visible: wikiPageFlg },
|
||||
{ name: '履歴', to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg },
|
||||
{ name: '編輯', to: `/wiki/${ wikiId || wikiTitle }/edit`, visible: wikiPageFlg }] },
|
||||
{ name: 'ユーザ', to: '/users/settings', visible: false, subMenu: [
|
||||
{ name: '一覧', to: '/users', visible: false },
|
||||
{ name: 'お前', to: `/users/${ user?.id }`, visible: false },
|
||||
{ name: '設定', to: '/users/settings', visible: Boolean (user) }] },
|
||||
{ name: '法規', visible: false, subMenu: [
|
||||
{ name: '利用規約', to: '/tos' }] }]
|
||||
}
|
||||
|
||||
|
||||
export default (({ user }: Props) => {
|
||||
const location = useLocation ()
|
||||
|
||||
@@ -66,51 +118,10 @@ export default (({ user }: Props) => {
|
||||
queryKey: tagsKeys.show (effectiveTitle),
|
||||
queryFn: () => fetchTagByName (effectiveTitle) })
|
||||
|
||||
const postCount = tag?.postCount ?? 0
|
||||
|
||||
const wikiPageFlg = Boolean (/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId)
|
||||
const wikiTitle = location.pathname.split ('/')[2] ?? ''
|
||||
const menu: Menu = [
|
||||
{ name: '広場', to: '/posts', subMenu: [
|
||||
{ name: '一覧', to: '/posts' },
|
||||
{ name: '検索', to: '/posts/search' },
|
||||
{ name: '追加', to: '/posts/new' },
|
||||
{ name: '履歴', to: '/posts/changes' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:広場' }] },
|
||||
{ name: 'タグ', to: '/tags', subMenu: [
|
||||
{ name: 'マスタ', to: '/tags' },
|
||||
{ name: '別名タグ', to: '/tags/aliases', visible: false },
|
||||
{ name: '上位タグ', to: '/tags/implications', visible: false },
|
||||
{ name: 'ニコニコ連携', to: '/tags/nico' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:タグ' }] },
|
||||
// { name: '素材', to: '/materials', subMenu: [
|
||||
// { name: '一覧', to: '/materials' },
|
||||
// { name: '検索', to: '/materials/search', visible: false },
|
||||
// { name: '追加', to: '/materials/new' },
|
||||
// { name: '履歴', to: '/materials/changes', visible: false },
|
||||
// { name: 'ヘルプ', to: '/wiki/ヘルプ:素材集' }] },
|
||||
{ name: '上映会', to: '/theatres/1', base: '/theatres', subMenu: [
|
||||
{ name: <>第 1 会場</>, to: '/theatres/1' },
|
||||
{ name: 'CyTube', to: '//cytube.mm428.net/r/deernijika' },
|
||||
{ name: <>ニジカ放送局第 1 チャンネル</>,
|
||||
to: '//www.youtube.com/watch?v=DCU3hL4Uu6A' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:上映会' }] },
|
||||
{ name: 'Wiki', to: '/wiki/ヘルプ:ホーム', base: '/wiki', subMenu: [
|
||||
{ name: '検索', to: '/wiki' },
|
||||
{ name: '新規', to: '/wiki/new' },
|
||||
{ name: '全体履歴', to: '/wiki/changes' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:Wiki' },
|
||||
{ component: <Separator/>, visible: wikiPageFlg },
|
||||
{ name: `広場 (${ postCount || 0 })`, to: `/posts?tags=${ wikiTitle }`,
|
||||
visible: wikiPageFlg },
|
||||
{ name: '履歴', to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg },
|
||||
{ name: '編輯', to: `/wiki/${ wikiId || wikiTitle }/edit`, visible: wikiPageFlg }] },
|
||||
{ name: 'ユーザ', to: '/users/settings', subMenu: [
|
||||
{ name: '一覧', to: '/users', visible: false },
|
||||
{ name: 'お前', to: `/users/${ user?.id }`, visible: false },
|
||||
{ name: '設定', to: '/users/settings', visible: Boolean (user) }] }]
|
||||
|
||||
const activeIdx = menu.findIndex (item => location.pathname.startsWith (item.base || item.to))
|
||||
const menu = menuOutline ({ tag, wikiId, user })
|
||||
const activeIdx = (menu
|
||||
.filter (item => item.visible ?? true)
|
||||
.findIndex (item => location.pathname.startsWith (item.base || item.to!)))
|
||||
|
||||
const prevActiveIdxRef = useRef<number> (activeIdx)
|
||||
|
||||
@@ -140,8 +151,8 @@ export default (({ user }: Props) => {
|
||||
|
||||
useEffect (() => {
|
||||
setMenuOpen (false)
|
||||
setOpenItemIdx (menu.findIndex (item => (
|
||||
location.pathname.startsWith (item.base || item.to))))
|
||||
setOpenItemIdx (menu.filter (item => item.visible ?? true).findIndex (item => (
|
||||
location.pathname.startsWith (item.base || item.to!))))
|
||||
}, [location])
|
||||
|
||||
return (
|
||||
@@ -168,10 +179,10 @@ export default (({ user }: Props) => {
|
||||
transform: `translateX(${ hl.left }px)`,
|
||||
opacity: hl.visible ? 1 : 0 }}/>
|
||||
|
||||
{menu.map ((item, i) => (
|
||||
{menu.filter (item => item.visible ?? true).map ((item, i) => (
|
||||
<PrefetchLink
|
||||
key={i}
|
||||
to={item.to}
|
||||
to={item.to!}
|
||||
ref={(el: (HTMLAnchorElement | null)) => {
|
||||
itemsRef.current[i] = el
|
||||
}}
|
||||
@@ -180,7 +191,7 @@ export default (({ user }: Props) => {
|
||||
{item.name}
|
||||
</PrefetchLink>))}
|
||||
<PrefetchLink
|
||||
to="#"
|
||||
to="/more"
|
||||
ref={(el: (HTMLAnchorElement | null)) => {
|
||||
itemsRef.current[menu.length] = el
|
||||
}}
|
||||
@@ -262,10 +273,10 @@ export default (({ user }: Props) => {
|
||||
exit="closed"
|
||||
transition={{ duration: .2, ease: 'easeOut' }}>
|
||||
<Separator/>
|
||||
{menu.map ((item, i) => (
|
||||
{menu.filter (item => item.visible ?? true).map ((item, i) => (
|
||||
<Fragment key={i}>
|
||||
<PrefetchLink
|
||||
to={i === openItemIdx ? item.to : '#'}
|
||||
to={i === openItemIdx ? item.to! : '#'}
|
||||
className={cn ('w-full min-h-[40px] flex items-center pl-8',
|
||||
((i === openItemIdx)
|
||||
&& 'font-bold bg-yellow-50 dark:bg-red-950'))}
|
||||
@@ -315,6 +326,14 @@ export default (({ user }: Props) => {
|
||||
</motion.div>)}
|
||||
</AnimatePresence>
|
||||
</Fragment>))}
|
||||
<PrefetchLink
|
||||
to="/more"
|
||||
ref={(el: (HTMLAnchorElement | null)) => {
|
||||
itemsRef.current[menu.length] = el
|
||||
}}
|
||||
className="w-full min-h-[40px] flex items-center pl-8">
|
||||
その他 »
|
||||
</PrefetchLink>
|
||||
<TopNavUser user={user} sp/>
|
||||
<Separator/>
|
||||
</motion.div>)}
|
||||
|
||||
@@ -4,8 +4,6 @@ import ReactMarkdown from 'react-markdown'
|
||||
import remarkGFM from 'remark-gfm'
|
||||
|
||||
import PrefetchLink from '@/components/PrefetchLink'
|
||||
import SectionTitle from '@/components/common/SectionTitle'
|
||||
import SubsectionTitle from '@/components/common/SubsectionTitle'
|
||||
import { wikiKeys } from '@/lib/queryKeys'
|
||||
import remarkWikiAutoLink from '@/lib/remark-wiki-autolink'
|
||||
import { fetchWikiPages } from '@/lib/wiki'
|
||||
@@ -16,19 +14,15 @@ import type { Components } from 'react-markdown'
|
||||
type Props = { title: string
|
||||
body?: string }
|
||||
|
||||
const mdComponents = { h1: ({ children }) => <SectionTitle>{children}</SectionTitle>,
|
||||
h2: ({ children }) => <SubsectionTitle>{children}</SubsectionTitle>,
|
||||
ol: ({ children }) => <ol className="list-decimal pl-6">{children}</ol>,
|
||||
ul: ({ children }) => <ul className="list-disc pl-6">{children}</ul>,
|
||||
a: (({ href, children }) => (
|
||||
['/', '.'].some (e => href?.startsWith (e))
|
||||
? <PrefetchLink to={href!}>{children}</PrefetchLink>
|
||||
: (
|
||||
<a href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
{children}
|
||||
</a>))) } as const satisfies Components
|
||||
const mdComponents = { a: (({ href, children }) => (
|
||||
['/', '.'].some (e => href?.startsWith (e))
|
||||
? <PrefetchLink to={href!}>{children}</PrefetchLink>
|
||||
: (
|
||||
<a href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
{children}
|
||||
</a>))) } as const satisfies Components
|
||||
|
||||
|
||||
export default (({ title, body }: Props) => {
|
||||
|
||||
新しい課題から参照
ユーザをブロックする