広場投稿追加画面の刷新 (#399) #413

マージ済み
みてるぞ が 103 個のコミットを feature/399 から main へマージ 2026-07-19 00:03:11 +09:00
2個のファイルの変更59行の追加58行の削除
コミット 8f66ee8059 の変更だけを表示してゐます - すべてのコミットを表示
+37 -37
ファイルの表示
@@ -155,7 +155,7 @@ const PostDetailRoute = ({ user }: { user: User | null }) => {
}
const App: FC = () => {
const RoutedApp: FC = () => {
const [user, setUser] = useState<User | null> (null)
const [status, setStatus] = useState (200)
const behaviourSettings = useClientBehaviourSettings ()
@@ -172,41 +172,6 @@ const App: FC = () => {
),
[animationMode],
)
const router = useMemo (
() => createBrowserRouter ([{
path: '*',
element: (
<DialogueProvider>
<UnsavedChangesGuardProvider>
<KeyboardShortcutsProvider>
<MotionConfig
reducedMotion={
animationMode === 'normal'
? 'never'
: animationMode === 'reduced'
? 'user'
: 'always'
}>
<LayoutWrapper>
<motion.div
layout={animationMode === 'off' ? false : 'position'}
transition={{ layout: appLayoutTransition }}
className="relative flex h-dvh w-full flex-col overflow-y-hidden">
<TopNav user={user}/>
<RouteTransitionWrapper
animationMode={animationMode}
user={user}
setUser={setUser}/>
</motion.div>
</LayoutWrapper>
</MotionConfig>
<Toaster/>
</KeyboardShortcutsProvider>
</UnsavedChangesGuardProvider>
</DialogueProvider>) }]),
[LayoutWrapper, animationMode, appLayoutTransition, setUser, user],
)
useEffect (() => {
applyClientAppearance ()
@@ -289,11 +254,46 @@ const App: FC = () => {
}
return (
<DialogueProvider>
<UnsavedChangesGuardProvider>
<KeyboardShortcutsProvider>
<MotionConfig
reducedMotion={
animationMode === 'normal'
? 'never'
: animationMode === 'reduced'
? 'user'
: 'always'
}>
<LayoutWrapper>
<motion.div
layout={animationMode === 'off' ? false : 'position'}
transition={{ layout: appLayoutTransition }}
className="relative flex h-dvh w-full flex-col overflow-y-hidden">
<TopNav user={user}/>
<RouteTransitionWrapper
animationMode={animationMode}
user={user}
setUser={setUser}/>
</motion.div>
</LayoutWrapper>
</MotionConfig>
<Toaster/>
</KeyboardShortcutsProvider>
</UnsavedChangesGuardProvider>
</DialogueProvider>)
}
const router = createBrowserRouter ([{
path: '*',
element: <RoutedApp/> }])
const App: FC = () => (
<>
<RouteBlockerOverlay/>
{import.meta.env.DEV && <DevModeWatermark/>}
<RouterProvider router={router}/>
</>)
}
export default App
+18 -17
ファイルの表示
@@ -7,7 +7,7 @@ import {
useRef,
useState,
} from 'react'
import { useBlocker, useLocation } from 'react-router-dom'
import { useBlocker } from 'react-router-dom'
import { useDialogue } from '@/lib/dialogues/useDialogue'
@@ -34,7 +34,6 @@ const UnsavedChangesGuardContext =
export const UnsavedChangesGuardProvider: FC<PropsWithChildren> = ({ children }) => {
const dialogue = useDialogue ()
const location = useLocation ()
const sourcesRef = useRef (new Map<symbol, UnsavedChangesSource> ())
const bypassNextNavigationRef = useRef (false)
const [revision, setRevision] = useState (0)
@@ -68,12 +67,19 @@ export const UnsavedChangesGuardProvider: FC<PropsWithChildren> = ({ children })
[sources],
)
const hasUnsavedChanges = dirtySources.length > 0
const blocker = useBlocker (
useCallback (
() => hasUnsavedChanges && !(bypassNextNavigationRef.current),
[hasUnsavedChanges],
),
)
const shouldBlock = useCallback (() => {
if (!(hasUnsavedChanges))
return false
if (bypassNextNavigationRef.current)
{
bypassNextNavigationRef.current = false
return false
}
return true
}, [hasUnsavedChanges])
const blocker = useBlocker (shouldBlock)
const discardDirtyChanges = useCallback (async (): Promise<boolean> => {
if (!(hasUnsavedChanges))
@@ -93,8 +99,6 @@ export const UnsavedChangesGuardProvider: FC<PropsWithChildren> = ({ children })
if (!(confirmed))
return false
bypassNextNavigationRef.current = true
try
{
for (const source of dirtySources)
@@ -102,7 +106,6 @@ export const UnsavedChangesGuardProvider: FC<PropsWithChildren> = ({ children })
}
catch
{
bypassNextNavigationRef.current = false
return false
}
@@ -139,10 +142,6 @@ export const UnsavedChangesGuardProvider: FC<PropsWithChildren> = ({ children })
}
}, [blocker, discardDirtyChanges])
useEffect (() => {
bypassNextNavigationRef.current = false
}, [location.hash, location.pathname, location.search])
useEffect (() => {
if (!(hasUnsavedChanges))
return
@@ -183,14 +182,16 @@ export const useUnsavedChangesGuard = (
if (context == null)
throw new Error ('UnsavedChangesGuardProvider が必要です.')
const { registerUnsavedChangesSource } = context
useEffect (() => {
if (options == null)
return
return context.registerUnsavedChangesSource ({
return registerUnsavedChangesSource ({
dirty: options.dirty,
discard: options.onDiscard ?? (() => undefined) })
}, [context, options?.dirty, options?.onDiscard])
}, [options?.dirty, options?.onDiscard, registerUnsavedChangesSource])
return context
}