add reload badge on sw update
This commit is contained in:
parent
adbc7d455d
commit
59c03d16eb
@ -9,16 +9,17 @@ 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'
|
||||
|
||||
function App() {
|
||||
const [render, setRender] = useState(0)
|
||||
const dispatch = useAppDispatch()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
|
||||
const [isConnected, setIsConnected] = useState(false)
|
||||
|
||||
const load = useCallback(async () => {
|
||||
const keys: DbKey[] = await dbi.listKeys()
|
||||
// console.log(keys, 'keys')
|
||||
|
||||
dispatch(setKeys({ keys }))
|
||||
const loadProfiles = async () => {
|
||||
@ -55,7 +56,6 @@ function App() {
|
||||
// rerender
|
||||
// setRender((r) => r + 1)
|
||||
|
||||
// if (!keys.length) handleOpen(MODAL_PARAMS_KEYS.INITIAL)
|
||||
// eslint-disable-next-line
|
||||
}, [dispatch])
|
||||
|
||||
@ -80,12 +80,14 @@ function App() {
|
||||
// subscribe to service worker updates
|
||||
swicOnReload(() => {
|
||||
console.log('reload')
|
||||
// FIXME show 'Please reload' badge at page top
|
||||
searchParams.set('reload', 'true')
|
||||
setSearchParams(searchParams)
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppRoutes />
|
||||
|
||||
<ModalInitial />
|
||||
<ModalImportKeys />
|
||||
<ModalSignUp />
|
||||
|
@ -13,7 +13,7 @@ import { DOMAIN } from '@/utils/consts'
|
||||
import { fetchNip05 } from '@/utils/helpers/helpers'
|
||||
import { Stack, Typography, useTheme } from '@mui/material'
|
||||
import { ChangeEvent, Fragment, useCallback, useEffect, useState } from 'react'
|
||||
import { useParams, useSearchParams } from 'react-router-dom'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useDebounce } from 'use-debounce'
|
||||
import { StyledSettingContainer } from './styled'
|
||||
import { SectionTitle } from '@/shared/SectionTitle/SectionTitle'
|
||||
@ -55,7 +55,7 @@ export const ModalEditName = () => {
|
||||
setIsAvailable(true)
|
||||
setIsChecking(false)
|
||||
}
|
||||
}, [debouncedName])
|
||||
}, [debouncedName, npub])
|
||||
|
||||
useEffect(() => {
|
||||
checkIsUsernameAvailable()
|
||||
|
33
src/components/ReloadBadge/ReloadBadge.tsx
Normal file
33
src/components/ReloadBadge/ReloadBadge.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { FC } from 'react'
|
||||
import { Collapse, Stack, Typography } from '@mui/material'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
import { StyledAlert, StyledReloadButton } from './styled'
|
||||
|
||||
const ReloadBadgeContent: FC = () => {
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
|
||||
const handleReload = () => {
|
||||
searchParams.delete('reload')
|
||||
setSearchParams(searchParams)
|
||||
window.location.reload()
|
||||
}
|
||||
return (
|
||||
<Collapse in>
|
||||
<StyledAlert>
|
||||
<Stack direction={'row'} className="content">
|
||||
<Typography flex={1} className="title">
|
||||
New version available, please reload the page!
|
||||
</Typography>
|
||||
<StyledReloadButton onClick={handleReload}>Reload</StyledReloadButton>
|
||||
</Stack>
|
||||
</StyledAlert>
|
||||
</Collapse>
|
||||
)
|
||||
}
|
||||
|
||||
export const ReloadBadge = () => {
|
||||
const [searchParams] = useSearchParams()
|
||||
const open = searchParams.get('reload') === 'true'
|
||||
|
||||
return <>{open && <ReloadBadgeContent />}</>
|
||||
}
|
50
src/components/ReloadBadge/styled.tsx
Normal file
50
src/components/ReloadBadge/styled.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import { AppButtonProps, Button } from '@/shared/Button/Button'
|
||||
import { Alert, AlertProps, styled } from '@mui/material'
|
||||
import RefreshIcon from '@mui/icons-material/Refresh'
|
||||
|
||||
export const StyledAlert = styled((props: AlertProps) => (
|
||||
<Alert {...props} variant="outlined" severity="info" classes={{ message: 'message' }} />
|
||||
))(() => {
|
||||
return {
|
||||
height: 'auto',
|
||||
marginTop: '0.5rem',
|
||||
alignItems: 'center',
|
||||
'& .message': {
|
||||
flex: 1,
|
||||
overflow: 'initial',
|
||||
},
|
||||
'& .content': {
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
gap: '1rem',
|
||||
},
|
||||
'& .title': {
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: 3,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
'@media screen and (max-width: 320px)': {
|
||||
'& .title': {
|
||||
fontSize: '14px',
|
||||
WebkitLineClamp: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
export const StyledReloadButton = styled((props: AppButtonProps) => <Button startIcon={<RefreshIcon />} {...props} />)(
|
||||
({ theme }) => {
|
||||
const isDarkTheme = theme.palette.mode === 'dark'
|
||||
return {
|
||||
padding: '0.25rem 1rem',
|
||||
'&.button:is(:hover, :active, &)': {
|
||||
background: isDarkTheme ? '#b8e7fb' : '#014361',
|
||||
},
|
||||
'@media screen and (max-width: 320px)': {
|
||||
padding: '0.25rem 0.5rem',
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
@ -1,7 +1,7 @@
|
||||
import { Avatar, Stack, Toolbar, Typography } from '@mui/material'
|
||||
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 } from 'react-router-dom'
|
||||
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
|
||||
import { ProfileMenu } from './components/ProfileMenu'
|
||||
import { useProfile } from '@/hooks/useProfile'
|
||||
import DarkModeIcon from '@mui/icons-material/DarkMode'
|
||||
@ -13,6 +13,8 @@ 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 { npub = '' } = useParams<{ npub: string }>()
|
||||
const { userName, userAvatar, avatarTitle } = useProfile(npub)
|
||||
@ -30,7 +32,7 @@ export const Header = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledAppBar position="fixed">
|
||||
<StyledAppBar position={needReload ? 'relative' : 'fixed'}>
|
||||
<Toolbar sx={{ padding: '12px' }}>
|
||||
<Stack direction={'row'} justifyContent={'space-between'} alignItems={'center'} width={'100%'}>
|
||||
{showProfile && (
|
||||
@ -56,6 +58,15 @@ export const Header = () => {
|
||||
{showProfile ? <ProfileMenu /> : <Menu />}
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
<StyledDivider />
|
||||
</StyledAppBar>
|
||||
)
|
||||
}
|
||||
|
||||
const StyledDivider = styled((props: DividerProps) => <Divider {...props} />)({
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
left: 0,
|
||||
height: '2px',
|
||||
})
|
||||
|
@ -1,13 +1,17 @@
|
||||
import { FC } from 'react'
|
||||
import { Outlet } from 'react-router-dom'
|
||||
import { Outlet, useSearchParams } from 'react-router-dom'
|
||||
import { Header } from './Header/Header'
|
||||
import { Container, ContainerProps, Divider, DividerProps, styled } from '@mui/material'
|
||||
import { Container, ContainerProps, styled } from '@mui/material'
|
||||
import { ReloadBadge } from '@/components/ReloadBadge/ReloadBadge'
|
||||
|
||||
export const Layout: FC = () => {
|
||||
const [searchParams] = useSearchParams()
|
||||
const needReload = searchParams.get('reload') === 'true'
|
||||
|
||||
return (
|
||||
<StyledContainer maxWidth="md">
|
||||
<StyledContainer maxWidth="md" className={needReload ? 'reload' : ''}>
|
||||
<ReloadBadge />
|
||||
<Header />
|
||||
<StyledDivider />
|
||||
<main>
|
||||
<Outlet />
|
||||
</main>
|
||||
@ -21,17 +25,11 @@ const StyledContainer = styled((props: ContainerProps) => <Container maxWidth="s
|
||||
flexDirection: 'column',
|
||||
paddingBottom: '1rem',
|
||||
position: 'relative',
|
||||
'& > main': {
|
||||
'&': {
|
||||
flex: 1,
|
||||
maxHeight: '100%',
|
||||
},
|
||||
'&:not(.reload) > main': {
|
||||
paddingTop: 'calc(66px + 1rem)',
|
||||
},
|
||||
})
|
||||
|
||||
const StyledDivider = styled((props: DividerProps) => <Divider {...props} />)({
|
||||
position: 'absolute',
|
||||
top: '66px',
|
||||
width: '100%',
|
||||
left: 0,
|
||||
height: '2px',
|
||||
})
|
||||
|
@ -21,7 +21,6 @@ const AppRoutes = () => {
|
||||
<Routes>
|
||||
<Route path="/" element={<Layout />}>
|
||||
<Route path="/" element={<Navigate to={'/home'} />} />
|
||||
{/* <Route path='/welcome' element={<WelcomePage />} /> */}
|
||||
<Route path="/home" element={<HomePage />} />
|
||||
<Route path="/key/:npub" element={<KeyPage />} />
|
||||
<Route path="/key/:npub/app/:appNpub" element={<AppPage />} />
|
||||
|
@ -2,16 +2,7 @@ import { combineReducers, configureStore } from '@reduxjs/toolkit'
|
||||
import { contentSlice } from './reducers/content.slice'
|
||||
import { uiSlice } from './reducers/ui.slice'
|
||||
|
||||
import {
|
||||
persistStore,
|
||||
persistReducer,
|
||||
// FLUSH,
|
||||
// REGISTER,
|
||||
// REHYDRATE,
|
||||
// PAUSE,
|
||||
// PERSIST,
|
||||
// PURGE,
|
||||
} from 'redux-persist'
|
||||
import { persistStore, persistReducer } from 'redux-persist'
|
||||
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web
|
||||
import memoizeOne from 'memoize-one'
|
||||
import isDeepEqual from 'lodash.isequal'
|
||||
|
Loading…
x
Reference in New Issue
Block a user