diff --git a/package-lock.json b/package-lock.json index 2d6a5a3..d9e9cef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "redux-persist": "^6.0.0", "typescript": "^5.3.2", "use-debounce": "^10.0.0", + "usehooks-ts": "^2.14.0", "web-vitals": "^2.1.4", "workbox-background-sync": "^6.6.0", "workbox-broadcast-update": "^6.6.0", @@ -17214,6 +17215,20 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/usehooks-ts": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.14.0.tgz", + "integrity": "sha512-jnhrjTRJoJS7cFxz63tRYc5mzTKf/h+Ii8P0PDHymT9qDe4ZA2/gzDRmDR4WGausg5X8wMIdghwi3BBCN9JKow==", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/utf-8-validate": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", @@ -30591,6 +30606,14 @@ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", "requires": {} }, + "usehooks-ts": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.14.0.tgz", + "integrity": "sha512-jnhrjTRJoJS7cFxz63tRYc5mzTKf/h+Ii8P0PDHymT9qDe4ZA2/gzDRmDR4WGausg5X8wMIdghwi3BBCN9JKow==", + "requires": { + "lodash.debounce": "^4.0.8" + } + }, "utf-8-validate": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", diff --git a/package.json b/package.json index 9ef2a32..ca4c717 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "redux-persist": "^6.0.0", "typescript": "^5.3.2", "use-debounce": "^10.0.0", + "usehooks-ts": "^2.14.0", "web-vitals": "^2.1.4", "workbox-background-sync": "^6.6.0", "workbox-broadcast-update": "^6.6.0", diff --git a/src/App.tsx b/src/App.tsx index ad3a79a..1eefbf0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,12 +9,15 @@ import { ModalInitial } from './components/Modal/ModalInitial/ModalInitial' import { ModalImportKeys } from './components/Modal/ModalImportKeys/ModalImportKeys' import { ModalSignUp } from './components/Modal/ModalSignUp/ModalSignUp' import { ModalLogin } from './components/Modal/ModalLogin/ModalLogin' -import { useSearchParams } from 'react-router-dom' +import { useSessionStorage } from 'usehooks-ts' +import { RELOAD_STORAGE_KEY } from './utils/consts' function App() { const [render, setRender] = useState(0) const dispatch = useAppDispatch() - const [searchParams, setSearchParams] = useSearchParams() + + // eslint-disable-next-line + const [_, setNeedReload] = useSessionStorage(RELOAD_STORAGE_KEY, false) const [isConnected, setIsConnected] = useState(false) @@ -80,14 +83,24 @@ function App() { // subscribe to service worker updates swicOnReload(() => { console.log('reload') - searchParams.set('reload', 'true') - setSearchParams(searchParams) + setNeedReload(true) }) + useEffect(() => { + const handleBeforeUnload = () => { + setNeedReload(false) + } + + window.addEventListener('beforeunload', handleBeforeUnload) + return () => { + window.removeEventListener('beforeunload', handleBeforeUnload) + } + // eslint-disable-next-line + }, []) + return ( <> - diff --git a/src/components/ReloadBadge/ReloadBadge.tsx b/src/components/ReloadBadge/ReloadBadge.tsx index 4096c73..549f3b0 100644 --- a/src/components/ReloadBadge/ReloadBadge.tsx +++ b/src/components/ReloadBadge/ReloadBadge.tsx @@ -1,16 +1,14 @@ -import { FC } from 'react' +import { FC, memo, useCallback } from 'react' import { Collapse, Stack, Typography } from '@mui/material' -import { useSearchParams } from 'react-router-dom' import { StyledAlert, StyledReloadButton } from './styled' +import { useSessionStorage } from 'usehooks-ts' +import { RELOAD_STORAGE_KEY } from '@/utils/consts' -const ReloadBadgeContent: FC = () => { - const [searchParams, setSearchParams] = useSearchParams() +type ReloadBadgeContentProps = { + onReload: () => void +} - const handleReload = () => { - searchParams.delete('reload') - setSearchParams(searchParams) - window.location.reload() - } +const ReloadBadgeContent: FC = memo(({ onReload }) => { return ( @@ -18,16 +16,20 @@ const ReloadBadgeContent: FC = () => { New version available! - Reload + Reload ) -} +}) export const ReloadBadge = () => { - const [searchParams] = useSearchParams() - const open = searchParams.get('reload') === 'true' + const [needReload, setNeedReload] = useSessionStorage(RELOAD_STORAGE_KEY, false) - return <>{open && } + const handleReload = useCallback(() => { + setNeedReload(false) + window.location.reload() + }, [setNeedReload]) + + return <>{needReload && } } diff --git a/src/layout/Header/Header.tsx b/src/layout/Header/Header.tsx index cd500d4..c5b4a85 100644 --- a/src/layout/Header/Header.tsx +++ b/src/layout/Header/Header.tsx @@ -1,20 +1,21 @@ import { Avatar, Stack, Toolbar, Typography, Divider, DividerProps, styled } from '@mui/material' import { StyledAppBar, StyledAppLogo, StyledAppName, StyledProfileContainer, StyledThemeButton } from './styled' import { Menu } from './components/Menu' -import { useNavigate, useParams, useSearchParams } from 'react-router-dom' +import { useNavigate, useParams } from 'react-router-dom' import { ProfileMenu } from './components/ProfileMenu' import { useProfile } from '@/hooks/useProfile' import DarkModeIcon from '@mui/icons-material/DarkMode' import LightModeIcon from '@mui/icons-material/LightMode' import { useAppDispatch, useAppSelector } from '@/store/hooks/redux' import { setThemeMode } from '@/store/reducers/ui.slice' +import { useSessionStorage } from 'usehooks-ts' +import { RELOAD_STORAGE_KEY } from '@/utils/consts' export const Header = () => { const themeMode = useAppSelector((state) => state.ui.themeMode) const navigate = useNavigate() const dispatch = useAppDispatch() - const [searchParams] = useSearchParams() - const needReload = searchParams.get('reload') === 'true' + const [needReload] = useSessionStorage(RELOAD_STORAGE_KEY, false) const { npub = '' } = useParams<{ npub: string }>() const { userName, userAvatar, avatarTitle } = useProfile(npub) diff --git a/src/layout/Layout.tsx b/src/layout/Layout.tsx index 3410d0c..ab15bb4 100644 --- a/src/layout/Layout.tsx +++ b/src/layout/Layout.tsx @@ -1,15 +1,17 @@ import { FC } from 'react' -import { Outlet, useSearchParams } from 'react-router-dom' +import { Outlet } from 'react-router-dom' import { Header } from './Header/Header' import { Container, ContainerProps, styled } from '@mui/material' import { ReloadBadge } from '@/components/ReloadBadge/ReloadBadge' +import { useSessionStorage } from 'usehooks-ts' +import { RELOAD_STORAGE_KEY } from '@/utils/consts' export const Layout: FC = () => { - const [searchParams] = useSearchParams() - const needReload = searchParams.get('reload') === 'true' + const [needReload] = useSessionStorage(RELOAD_STORAGE_KEY, false) + const containerClassName = needReload ? 'reload' : '' return ( - +
diff --git a/src/utils/consts.ts b/src/utils/consts.ts index 0af612f..96e6abb 100644 --- a/src/utils/consts.ts +++ b/src/utils/consts.ts @@ -9,6 +9,8 @@ export const MAX_POW = 19 export const KIND_RPC = 24133 +export const RELOAD_STORAGE_KEY = 'reload' + export enum ACTION_TYPE { BASIC = 'basic', ADVANCED = 'advanced',