このコミットが含まれているのは:
@@ -5,9 +5,11 @@ import { Fragment, useEffect, useLayoutEffect, useRef, useState } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
|
||||
import { useLocale, useLocaleNavigate } from '@/lib/useLocale'
|
||||
import LocalisedText, { formatUIString } from '@/components/LocalisedText'
|
||||
import Separator from '@/components/MenuSeparator'
|
||||
import PrefetchLink from '@/components/PrefetchLink'
|
||||
import TopNavUser from '@/components/TopNavUser'
|
||||
import TranslatedText from '@/components/TranslatedText'
|
||||
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
|
||||
import { isLocaleCode,
|
||||
localeFromPath,
|
||||
@@ -41,7 +43,13 @@ export const menuOutline = (
|
||||
): Menu => {
|
||||
const pathName = unlocalisedPath (fullPathname)
|
||||
const locale = localeFromPath (fullPathname) ?? 'ja'
|
||||
const message = (key: Parameters<typeof uiMessage>[1]) => uiMessage (locale, key)
|
||||
|
||||
const message = (
|
||||
key: Parameters<typeof uiMessage>[1],
|
||||
values?: Record<string, string | number>,
|
||||
) => ({ name: uiMessage (locale, key, values),
|
||||
nameLanguage: uiMessageLanguage (locale, key) })
|
||||
|
||||
const postCount = tag?.postCount ?? material?.tag?.postCount ?? 0
|
||||
const editable = canEditContent (user)
|
||||
|
||||
@@ -56,63 +64,63 @@ export const menuOutline = (
|
||||
const helpIdentifier = pathName.split ('/')[2] ?? ''
|
||||
|
||||
return [
|
||||
{ name: message ('square'), to: '/posts', subMenu: [
|
||||
{ name: message ('list'), to: '/posts' },
|
||||
{ name: message ('search'), to: '/posts/search' },
|
||||
{ name: message ('add'), to: '/posts/new', visible: editable },
|
||||
{ name: message ('allHistory'), to: '/posts/changes' },
|
||||
{ name: message ('help'), to: '/wiki/ヘルプ:広場' }] },
|
||||
{ name: message ('tags'), to: '/tags', subMenu: [
|
||||
{ name: message ('master'), to: '/tags' },
|
||||
{ name: message ('nicoLinks'), to: '/tags/nico' },
|
||||
{ name: message ('allHistory'), to: '/tags/changes' },
|
||||
{ name: message ('help'), to: '/wiki/ヘルプ:タグ' },
|
||||
{ ...message ('posts'), to: '/posts', subMenu: [
|
||||
{ ...message ('list'), to: '/posts' },
|
||||
{ ...message ('search'), to: '/posts/search' },
|
||||
{ ...message ('add'), to: '/posts/new', visible: editable },
|
||||
{ ...message ('allHistory'), to: '/posts/changes' },
|
||||
{ ...message ('help'), to: '/wiki/ヘルプ:広場' }] },
|
||||
{ ...message ('tags'), to: '/tags', subMenu: [
|
||||
{ ...message ('master'), to: '/tags' },
|
||||
{ ...message ('nicoLinks'), to: '/tags/nico' },
|
||||
{ ...message ('allHistory'), to: '/tags/changes' },
|
||||
{ ...message ('help'), to: '/wiki/ヘルプ:タグ' },
|
||||
{ component: <Separator/>, visible: tagFlg },
|
||||
{ name: `広場 (${ postCount || 0 })`,
|
||||
{ ...message ('postsWithCount', { count: postCount }),
|
||||
to: `/posts?tags=${ encodeURIComponent (tag?.name ?? '') }`,
|
||||
visible: tagFlg },
|
||||
{ name: message ('history'), to: `/tags/changes?id=${ tag?.id }`,
|
||||
{ ...message ('history'), to: `/tags/changes?id=${ tag?.id }`,
|
||||
visible: tagFlg && tag?.category !== 'nico' }] },
|
||||
{ name: message ('materials'), to: '/materials', visible: true, subMenu: [
|
||||
{ name: message ('list'), to: '/materials' },
|
||||
{ name: message ('add'), to: '/materials/new', visible: editable },
|
||||
{ name: message ('suppressions'), to: '/materials/suppressions',
|
||||
{ ...message ('materials'), to: '/materials', visible: true, subMenu: [
|
||||
{ ...message ('list'), to: '/materials' },
|
||||
{ ...message ('add'), to: '/materials/new', visible: editable },
|
||||
{ ...message ('suppressions'), to: '/materials/suppressions',
|
||||
visible: user?.role === 'admin' },
|
||||
{ name: message ('allHistory'), to: '/materials/changes' },
|
||||
{ name: message ('help'), to: '/wiki/ヘルプ:素材管理' },
|
||||
{ ...message ('allHistory'), to: '/materials/changes' },
|
||||
{ ...message ('help'), to: '/wiki/ヘルプ:素材管理' },
|
||||
{ component: <Separator/>, visible: materialFlg },
|
||||
{ name: `広場 (${ postCount || 0 })`,
|
||||
{ ...message ('postsWithCount', { count: postCount }),
|
||||
to: `/posts?tags=${ encodeURIComponent (material?.tag?.name ?? '') }`,
|
||||
visible: materialFlg && Boolean (material?.tag) },
|
||||
{ name: message ('history'), to: `/materials/changes?material_id=${ material?.id }`,
|
||||
{ ...message ('history'), to: `/materials/changes?material_id=${ material?.id }`,
|
||||
visible: materialFlg }] },
|
||||
{ name: message ('wiki'), to: '/wiki', subMenu: [
|
||||
{ name: message ('search'), to: '/wiki' },
|
||||
{ name: message ('create'), to: '/wiki/new', visible: editable },
|
||||
{ name: message ('allHistory'), to: '/wiki/changes' },
|
||||
{ name: message ('help'), to: '/wiki/ヘルプ:Wiki' },
|
||||
{ ...message ('wiki'), to: '/wiki', subMenu: [
|
||||
{ ...message ('search'), to: '/wiki' },
|
||||
{ ...message ('create'), to: '/wiki/new', visible: editable },
|
||||
{ ...message ('allHistory'), to: '/wiki/changes' },
|
||||
{ ...message ('help'), to: '/wiki/ヘルプ:Wiki' },
|
||||
{ component: <Separator/>, visible: wikiPageFlg },
|
||||
{ name: `広場 (${ postCount || 0 })`, to: `/posts?tags=${ wikiTitle }`,
|
||||
{ ...message ('postsWithCount', { count: postCount }), to: `/posts?tags=${ wikiTitle }`,
|
||||
visible: wikiPageFlg },
|
||||
{ name: message ('history'), to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg },
|
||||
{ name: message ('edit'), to: `/wiki/${ wikiId || wikiTitle }/edit`,
|
||||
{ ...message ('history'), to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg },
|
||||
{ ...message ('edit'), to: `/wiki/${ wikiId || wikiTitle }/edit`,
|
||||
visible: wikiPageFlg && editable }] },
|
||||
{ name: message ('help'), to: '/help/home', base: '/help', subMenu: [
|
||||
{ name: message ('search'), to: '/help' },
|
||||
{ name: message ('allHistory'), to: '/help/changes' },
|
||||
{ ...message ('help'), to: '/help/home', base: '/help', subMenu: [
|
||||
{ ...message ('search'), to: '/help' },
|
||||
{ ...message ('allHistory'), to: '/help/changes' },
|
||||
{ component: <Separator/>, visible: helpVsbl },
|
||||
{ name: message ('history'),
|
||||
{ ...message ('history'),
|
||||
to: `/help/changes?identifier=${ helpIdentifier }`,
|
||||
visible: helpVsbl }] },
|
||||
{ name: message ('entertainment'), visible: false, subMenu: [
|
||||
{ name: message ('theatre'), to: '/theatres/1' },
|
||||
{ name: message ('gekanator'), to: '/gekanator' }] },
|
||||
{ name: message ('users'), to: '/users/settings', visible: false, subMenu: [
|
||||
{ name: message ('list'), to: '/users', visible: false },
|
||||
{ name: message ('currentUser'), to: `/users/${ user?.id }`, visible: false },
|
||||
{ name: message ('settings'), to: '/users/settings', visible: Boolean (user) }] },
|
||||
{ name: message ('legal'), visible: false, subMenu: [
|
||||
{ name: message ('terms'), to: '/tos' }] }]
|
||||
{ ...message ('entertainment'), visible: false, subMenu: [
|
||||
{ ...message ('theatre'), to: '/theatres/1' },
|
||||
{ ...message ('gekanator'), to: '/gekanator' }] },
|
||||
{ ...message ('users'), to: '/users/settings', visible: false, subMenu: [
|
||||
{ ...message ('list'), to: '/users', visible: false },
|
||||
{ ...message ('currentUser'), to: `/users/${ user?.id }`, visible: false },
|
||||
{ ...message ('settings'), to: '/users/settings', visible: Boolean (user) }] },
|
||||
{ ...message ('legal'), visible: false, subMenu: [
|
||||
{ ...message ('terms'), to: '/tos' }] }]
|
||||
}
|
||||
|
||||
|
||||
@@ -315,10 +323,10 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
rounded px-1 focus-within:ring-2">
|
||||
<Globe aria-hidden="true" size={16}/>
|
||||
<span className="top-nav-locale-name whitespace-nowrap text-sm">
|
||||
{localeName}
|
||||
<LocalisedText language={locale}>{localeName}</LocalisedText>
|
||||
</span>
|
||||
<select
|
||||
aria-label={localeName}
|
||||
aria-label={formatUIString (localeName ?? '', locale)}
|
||||
value={locale}
|
||||
className="absolute inset-0 h-full w-full cursor-pointer opacity-0"
|
||||
onChange={event => {
|
||||
@@ -331,7 +339,7 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
}}>
|
||||
{locales.map (entry => isLocaleCode (entry.code) && (
|
||||
<option key={entry.code} value={entry.code}>
|
||||
{entry.name}
|
||||
{formatUIString (entry.name, entry.code)}
|
||||
</option>))}
|
||||
</select>
|
||||
</label>)
|
||||
@@ -339,7 +347,7 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
return (
|
||||
<div ref={layoutRef} className="top-nav-layout w-full min-w-0 shrink-0"
|
||||
data-desktop={desktop} data-density={density}>
|
||||
<nav ref={barRef} lang={uiMessageLanguage (locale, 'square')}
|
||||
<nav ref={barRef} lang={uiMessageLanguage (locale, 'posts')}
|
||||
className="top-nav-root top-nav-bar flex justify-between items-center w-full">
|
||||
<div className="top-nav-primary flex shrink-0 items-center h-12">
|
||||
<PrefetchLink
|
||||
@@ -348,6 +356,7 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
onClick={() => {
|
||||
scroll (0, 0)
|
||||
}}>
|
||||
{/* TODO: ここも外出ししろ. */}
|
||||
ぼざクリ タグ広場
|
||||
</PrefetchLink>
|
||||
|
||||
@@ -380,7 +389,9 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
}}
|
||||
className={cn ('top-nav-menu-link relative z-10 flex h-full items-center',
|
||||
(i === openItemIdx) && 'font-bold')}>
|
||||
{item.name}
|
||||
<LocalisedText language={item.nameLanguage ?? 'ja'}>
|
||||
{item.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>
|
||||
</motion.div>))}
|
||||
<PrefetchLink
|
||||
@@ -396,7 +407,7 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
className={cn ('top-nav-menu-link relative z-10 flex h-full items-center',
|
||||
'shrink-0 whitespace-nowrap',
|
||||
(openItemIdx < 0 || moreVsbl) && 'font-bold')}>
|
||||
その他 »
|
||||
<TranslatedText messageKey="more"/>
|
||||
</PrefetchLink>
|
||||
</div>
|
||||
</div>
|
||||
@@ -452,7 +463,11 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
animate: { x: 0, y: 0, opacity: 1 },
|
||||
exit: { x: 40, y: -40, opacity: 0 } }))}
|
||||
className="z-10 h-full flex shrink-0 items-center px-3 font-bold w-28">
|
||||
<h2>{item.name}</h2>
|
||||
<h2>
|
||||
<LocalisedText language={item.nameLanguage ?? 'ja'}>
|
||||
{item.name}
|
||||
</LocalisedText>
|
||||
</h2>
|
||||
</motion.div>
|
||||
{item.subMenu
|
||||
.filter (subItem => subItem.visible ?? true)
|
||||
@@ -489,7 +504,9 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
target={subItem.to.slice (0, 2) === '//' ? '_blank' : undefined}
|
||||
onClick={() => setMoreVsbl (false)}
|
||||
className="top-nav-menu-link h-full flex items-center px-3">
|
||||
{subItem.name}
|
||||
<LocalisedText language={subItem.nameLanguage ?? 'ja'}>
|
||||
{subItem.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>
|
||||
</motion.div>)))}
|
||||
</div>
|
||||
@@ -517,7 +534,9 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
? '_blank'
|
||||
: undefined}
|
||||
className="top-nav-menu-link h-full flex items-center px-3">
|
||||
{item.name}
|
||||
<LocalisedText language={item.nameLanguage ?? 'ja'}>
|
||||
{item.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>
|
||||
</div>)))}
|
||||
</div>)
|
||||
@@ -557,7 +576,9 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
? '_blank'
|
||||
: undefined}
|
||||
className="top-nav-menu-link h-full flex items-center px-3">
|
||||
{item.name}
|
||||
<LocalisedText language={item.nameLanguage ?? 'ja'}>
|
||||
{item.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>
|
||||
</motion.div>)))}
|
||||
</motion.div>
|
||||
@@ -587,7 +608,9 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
setOpenItemIdx (i)
|
||||
}
|
||||
}}>
|
||||
{item.name}
|
||||
<LocalisedText language={item.nameLanguage ?? 'ja'}>
|
||||
{item.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>
|
||||
|
||||
{i === openItemIdx && (
|
||||
@@ -608,7 +631,9 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
? '_blank'
|
||||
: undefined}
|
||||
className="top-nav-mobile-row w-full min-h-[36px] flex items-center pl-12">
|
||||
{subItem.name}
|
||||
<LocalisedText language={subItem.nameLanguage ?? 'ja'}>
|
||||
{subItem.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>)))}
|
||||
</div>)}
|
||||
</Fragment>))}
|
||||
@@ -617,7 +642,7 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
className={cn ('top-nav-mobile-row w-full min-h-[40px] flex items-center pl-8',
|
||||
((openItemIdx < 0)
|
||||
&& 'top-nav-mobile-active font-bold'))}>
|
||||
その他 »
|
||||
<TranslatedText messageKey="more"/>
|
||||
</PrefetchLink>
|
||||
<TopNavUser user={user} sp/>
|
||||
<Separator/>
|
||||
@@ -652,7 +677,9 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
setOpenItemIdx (i)
|
||||
}
|
||||
}}>
|
||||
{item.name}
|
||||
<LocalisedText language={item.nameLanguage ?? 'ja'}>
|
||||
{item.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>
|
||||
|
||||
<AnimatePresence initial={false}>
|
||||
@@ -686,7 +713,10 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
? '_blank'
|
||||
: undefined}
|
||||
className="top-nav-mobile-row w-full min-h-[36px] flex items-center pl-12">
|
||||
{subItem.name}
|
||||
<LocalisedText
|
||||
language={subItem.nameLanguage ?? 'ja'}>
|
||||
{subItem.name}
|
||||
</LocalisedText>
|
||||
</PrefetchLink>)))}
|
||||
</motion.div>)}
|
||||
</AnimatePresence>
|
||||
@@ -696,7 +726,7 @@ const TopNav: FC<Props> = ({ user, locales }) => {
|
||||
className={cn ('top-nav-mobile-row w-full min-h-[40px] flex items-center pl-8',
|
||||
((openItemIdx < 0)
|
||||
&& 'top-nav-mobile-active font-bold'))}>
|
||||
その他 »
|
||||
<TranslatedText messageKey="more"/>
|
||||
</PrefetchLink>
|
||||
<TopNavUser user={user} sp/>
|
||||
<Separator/>
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする