diff --git a/src/App.tsx b/src/App.tsx index 57108ea0..d8ac9b2a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,7 @@ import { ServersMap } from './servers/data'; import { Settings } from './settings/reducers/settings'; import { changeThemeInMarkup } from './utils/theme'; import { AppUpdateBanner } from './common/AppUpdateBanner'; +import { forceUpdate } from './utils/helpers/sw'; import './App.scss'; interface AppProps { @@ -54,7 +55,7 @@ const App = ( - + ); }; diff --git a/src/common/AppUpdateBanner.tsx b/src/common/AppUpdateBanner.tsx index be6b05cd..c114dd3d 100644 --- a/src/common/AppUpdateBanner.tsx +++ b/src/common/AppUpdateBanner.tsx @@ -1,16 +1,34 @@ import { FC, MouseEventHandler } from 'react'; -import { Alert } from 'reactstrap'; +import { Alert, Button } from 'reactstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faSyncAlt as reloadIcon } from '@fortawesome/free-solid-svg-icons'; import { SimpleCard } from '../utils/SimpleCard'; +import { useToggle } from '../utils/helpers/hooks'; import './AppUpdateBanner.scss'; interface AppUpdateBannerProps { isOpen: boolean; toggle: MouseEventHandler; + forceUpdate: Function; } -export const AppUpdateBanner: FC = (props) => ( - -

This app has just been updated!

-

Restart it to enjoy the new features.

-
-); +export const AppUpdateBanner: FC = ({ isOpen, toggle, forceUpdate }) => { + const [ isUpdating,, setUpdating ] = useToggle(); + const update = () => { + setUpdating(); + forceUpdate(); + }; + + return ( + +

This app has just been updated!

+

+ Restart it to enjoy the new features. + +

+
+ ); +}; diff --git a/src/utils/helpers/sw.ts b/src/utils/helpers/sw.ts new file mode 100644 index 00000000..a318047b --- /dev/null +++ b/src/utils/helpers/sw.ts @@ -0,0 +1,16 @@ +export const forceUpdate = async () => { + const registrations = await navigator.serviceWorker?.getRegistrations() ?? []; + + for (const registration of registrations) { + const { waiting } = registration; + + waiting?.addEventListener('statechange', (event) => { + if ((event.target as any)?.state === 'activated') { + window.location.reload(); + } + }); + + // The logic that makes skipWaiting to be called when this message is posted is in service-worker.ts + waiting?.postMessage({ type: 'SKIP_WAITING' }); + } +};