diff --git a/src/app/(with-header)/header-sidebar.tsx b/src/app/(with-header)/header-sidebar.tsx index 0e5e417..8468901 100644 --- a/src/app/(with-header)/header-sidebar.tsx +++ b/src/app/(with-header)/header-sidebar.tsx @@ -19,6 +19,7 @@ import { FriendRequest, acceptFriendRequest, getFriendRequests, rejectFriendRequ import { useWindowListener } from '@/helpers/use-window-listener'; import { useErrorModal } from '@/components/error-modal'; import { useSwipeable } from 'react-swipeable'; +import { useReloaded } from '@/components/client-providers'; export type HeaderSidebarProps = { children?: React.ReactNode, @@ -44,6 +45,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { const [userDropdownOpen, setUserDropdownOpen] = useState(false); const [menuTranslate, setMenuTranslate] = useState(null); const [notificationsTranslate, setNotificationsTranslate] = useState(null); + const reloaded = useReloaded(); + const menusOpened = useRef(false); const path = pathname === '/' ? (user?.homepage ?? '/dashboard') : pathname; @@ -54,6 +57,13 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { const setError = useErrorModal(); + const back = useCallback(() => { + if (document.referrer.includes(location.origin) || reloaded || menusOpened.current) + router.back(); + else + router.replace('', { scroll: false }); + }, [router, reloaded]); + const { ref } = useSwipeable({ touchEventOptions: { passive: false }, onSwiped: e => { @@ -63,11 +73,11 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { if (menuTranslate && ((Math.abs(menuTranslate) > 384 * 0.5) || fastSwipe)) { if (isMenuOpen && window.location.hash === '#sidebar') - router.back(); + back(); setMenuOpen(!isMenuOpen); } else if (notificationsTranslate && ((Math.abs(notificationsTranslate) > window.innerWidth * 0.4 || fastSwipe))) { if (isNotificationsOpen && window.location.hash === '#notifications') - router.back(); + back(); setNotificationsOpen(!isNotificationsOpen); } @@ -87,11 +97,6 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { return; parent = parent.parentElement; } - - const data = (e.event.target as HTMLElement)?.dataset; - if (data?.slot === 'thumb' || data?.dragging) - return; - const allMenusClosed = !isMenuOpen && !isNotificationsOpen; const xPercent = e.initial[0] / window.innerWidth; @@ -126,16 +131,22 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { getFriendRequests().then(setFriendRequests); }, [pathname, user]); - const setNotificationsOpen = (open: boolean) => { + const setNotificationsOpen = (open: boolean, updateRef = true) => { _setNotificationsOpen(open); - if (open) + if (open) { router.push('#notifications', { scroll: false }); + if (updateRef) + menusOpened.current = true; + } }; - const setMenuOpen = (open: boolean) => { + const setMenuOpen = (open: boolean, updateRef = true) => { _setMenuOpen(open); - if (open) + if (open) { router.push('#sidebar', { scroll: false }); + if (updateRef) + menusOpened.current = true; + } }; useWindowListener('hashchange', () => { @@ -144,8 +155,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { }); useEffect(() => { - setMenuOpen(window.location.hash === '#sidebar'); - setNotificationsOpen(window.location.hash === '#notifications'); + setMenuOpen(window.location.hash === '#sidebar', false); + setNotificationsOpen(window.location.hash === '#notifications', false); }, []); const renderHeaderLink = useCallback((route: Subroute) => { @@ -310,7 +321,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
{ setMenuOpen(false); if (window.location.hash === '#sidebar') - router.back(); + back(); }} />
{ onClick={() => { setMenuOpen(false); if (window.location.hash === '#sidebar') - router.back(); + back(); }}> {routeGroup.title} @@ -329,7 +340,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { @@ -384,7 +395,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
); - }, [isMenuOpen, router, menuTranslate, routeGroup, user, path, cookies]); + }, [isMenuOpen, router, menuTranslate, routeGroup, user, path, cookies, back]); const rightSidebar = useMemo(() => { return (
@@ -407,7 +418,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { @@ -444,7 +455,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
); - }, [isNotificationsOpen, notificationsTranslate, user, friendRequests, notifications, router]); + }, [isNotificationsOpen, notificationsTranslate, user, friendRequests, notifications, router, back]); return (<> { leftSidebar } diff --git a/src/components/client-providers.tsx b/src/components/client-providers.tsx index 2fae51a..0be7cc9 100644 --- a/src/components/client-providers.tsx +++ b/src/components/client-providers.tsx @@ -1,22 +1,50 @@ 'use client'; -import { ReactNode } from 'react'; +import { ReactNode, createContext, useContext, useEffect, useRef, useState } from 'react'; import { NextUIProvider } from '@nextui-org/react'; import { ThemeProvider as NextThemesProvider } from 'next-themes'; import { ErrorProvider } from '@/components/error-modal'; import { ConfirmProvider } from '@/components/confirm-modal'; import { PromptProvider } from '@/components/prompt-modal'; +import { useWindowListener } from '@/helpers/use-window-listener'; +import { usePathname } from 'next/navigation'; -export function ClientProviders({ children }: { children: ReactNode }) { - return ( - - - - - {children} - - - - - ); +const ReloadContext = createContext(false); + +export const useReloaded = () => useContext(ReloadContext); + +export function ClientProviders({ children }: { children: ReactNode; }) { + const [isReloaded, setReloaded] = useState(false); + const pathname = usePathname(); + const lastPathname = useRef(null); + + useEffect(() => { + const reloaded = sessionStorage.getItem('reload'); + if (reloaded && Date.now() - +reloaded < 1000) + setReloaded(true); + sessionStorage.removeItem('reload'); + }, []); + useWindowListener('beforeunload', () => sessionStorage.setItem('reload', Date.now().toString())); + useEffect(() => { + if (lastPathname.current !== null) { + if (lastPathname.current !== pathname) + setReloaded(false); + } + + lastPathname.current = pathname; + }, [pathname]); + + return ( + + + + + + {children} + + + + + + ); } diff --git a/src/components/select-modal.tsx b/src/components/select-modal.tsx index 4f10ce5..3821ea2 100644 --- a/src/components/select-modal.tsx +++ b/src/components/select-modal.tsx @@ -9,6 +9,7 @@ import { useDebounceCallback } from 'usehooks-ts'; import { CellMeasurerChildProps } from 'react-virtualized/dist/es/CellMeasurer'; import { useRouter } from 'next/navigation'; import { useWindowListener } from '@/helpers/use-window-listener'; +import { useReloaded } from './client-providers'; @@ -205,6 +206,8 @@ export const SelectModalButton = { if (window.location.hash !== `#modal-${modalId}` && isOpen) { @@ -224,11 +227,16 @@ export const SelectModalButton = { setOpen(false); onSelected(item); - router.back(); + if (document.referrer.includes(location.origin) || historyPushed.current || reloaded) { + router.back(); + } else { + router.replace('', { scroll: false }); + } }} />