From 47dd4d2fe031f9149a946ab8c1c67081e3323f73 Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Thu, 17 Jun 2021 00:20:46 +1000 Subject: [PATCH] Update dialog --- crabfit-frontend/public/i18n/en/common.json | 8 +++++ crabfit-frontend/src/App.tsx | 26 +++++++++++++- .../components/UpdateDialog/UpdateDialog.tsx | 24 +++++++++++++ .../UpdateDialog/updateDialogStyle.ts | 34 +++++++++++++++++++ crabfit-frontend/src/components/index.ts | 1 + crabfit-frontend/src/index.tsx | 15 -------- 6 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 crabfit-frontend/src/components/UpdateDialog/UpdateDialog.tsx create mode 100644 crabfit-frontend/src/components/UpdateDialog/updateDialogStyle.ts diff --git a/crabfit-frontend/public/i18n/en/common.json b/crabfit-frontend/public/i18n/en/common.json index 27bfa42..4012234 100644 --- a/crabfit-frontend/public/i18n/en/common.json +++ b/crabfit-frontend/public/i18n/en/common.json @@ -54,5 +54,13 @@ "language": { "label": "Language" } + }, + "update": { + "heading": "Crab Fit has been updated", + "body": "A new version of Crab Fit is available, which includes updates, fixes, and new features.", + "buttons": { + "close": "Close", + "reload": "Reload" + } } } diff --git a/crabfit-frontend/src/App.tsx b/crabfit-frontend/src/App.tsx index dd97904..7a4b0aa 100644 --- a/crabfit-frontend/src/App.tsx +++ b/crabfit-frontend/src/App.tsx @@ -1,8 +1,9 @@ import { useState, useEffect, useCallback, Suspense, lazy } from 'react'; import { BrowserRouter, Switch, Route } from 'react-router-dom'; import { ThemeProvider, Global } from '@emotion/react'; +import { Workbox } from 'workbox-window'; -import { Settings, Loading, Egg } from 'components'; +import { Settings, Loading, Egg, UpdateDialog } from 'components'; import { useSettingsStore } from 'stores'; import theme from 'theme'; @@ -15,6 +16,8 @@ const Create = lazy(() => import('pages/Create/Create')); const Help = lazy(() => import('pages/Help/Help')); const Privacy = lazy(() => import('pages/Privacy/Privacy')); +const wb = new Workbox('sw.js'); + const App = () => { const colortheme = useSettingsStore(state => state.theme); const darkQuery = window.matchMedia('(prefers-color-scheme: dark)'); @@ -25,6 +28,8 @@ const App = () => { const [eggVisible, setEggVisible] = useState(false); const [eggKey, setEggKey] = useState(0); + const [updateAvailable, setUpdateAvailable] = useState(false); + const eggHandler = useCallback( event => { if (EGG_PATTERN.indexOf(event.key) < 0 || event.key !== EGG_PATTERN[eggCount]) { @@ -56,6 +61,19 @@ const App = () => { }; }, []); + useEffect(() => { + // Register service worker + if ('serviceWorker' in navigator && process.env.NODE_ENV === 'production') { + wb.addEventListener('installed', event => { + if (event.isUpdate) { + setUpdateAvailable(true); + } + }); + + wb.register(); + } + }, []); + useEffect(() => { document.addEventListener('keyup', eggHandler, false); @@ -140,6 +158,12 @@ const App = () => { )} /> + {updateAvailable && ( + }> + setUpdateAvailable(false)} /> + + )} + {eggVisible && setEggVisible(false)} />} diff --git a/crabfit-frontend/src/components/UpdateDialog/UpdateDialog.tsx b/crabfit-frontend/src/components/UpdateDialog/UpdateDialog.tsx new file mode 100644 index 0000000..f087183 --- /dev/null +++ b/crabfit-frontend/src/components/UpdateDialog/UpdateDialog.tsx @@ -0,0 +1,24 @@ +import { Button } from 'components'; +import { useTranslation } from 'react-i18next'; + +import { + Wrapper, + ButtonWrapper, +} from './updateDialogStyle'; + +const UpdateDialog = ({ onClose }) => { + const { t } = useTranslation('common'); + + return ( + +

{t('common:update.heading')}

+

{t('common:update.body')}

+ + + + +
+ ); +} + +export default UpdateDialog; diff --git a/crabfit-frontend/src/components/UpdateDialog/updateDialogStyle.ts b/crabfit-frontend/src/components/UpdateDialog/updateDialogStyle.ts new file mode 100644 index 0000000..139f211 --- /dev/null +++ b/crabfit-frontend/src/components/UpdateDialog/updateDialogStyle.ts @@ -0,0 +1,34 @@ +import styled from '@emotion/styled'; + +export const Wrapper = styled.div` + position: fixed; + bottom: 20px; + right: 20px; + background-color: ${props => props.theme.background}; + ${props => props.theme.mode === 'dark' && ` + border: 1px solid ${props.theme.primaryBackground}; + `} + z-index: 900; + padding: 20px 26px; + border-radius: 3px; + width: 400px; + box-sizing: border-box; + max-width: calc(100% - 20px); + box-shadow: 0 3px 6px 0 rgba(0,0,0,.3); + + & h2 { + margin: 0; + font-size: 1.3rem; + } + & p { + margin: 16px 0 24px; + font-size: 1rem; + } +`; + +export const ButtonWrapper = styled.div` + display: flex; + align-items: center; + justify-content: flex-end; + gap: 16px; +`; diff --git a/crabfit-frontend/src/components/index.ts b/crabfit-frontend/src/components/index.ts index de04478..1b73344 100644 --- a/crabfit-frontend/src/components/index.ts +++ b/crabfit-frontend/src/components/index.ts @@ -18,6 +18,7 @@ export { default as Egg } from './Egg/Egg'; export { default as Footer } from './Footer/Footer'; export { default as Recents } from './Recents/Recents'; export { default as Logo } from './Logo/Logo'; +export { default as UpdateDialog } from './UpdateDialog/UpdateDialog'; export const _GoogleCalendar = () => import('./GoogleCalendar/GoogleCalendar'); export const _OutlookCalendar = () => import('./OutlookCalendar/OutlookCalendar'); diff --git a/crabfit-frontend/src/index.tsx b/crabfit-frontend/src/index.tsx index 7ea3f12..ed39b03 100644 --- a/crabfit-frontend/src/index.tsx +++ b/crabfit-frontend/src/index.tsx @@ -1,7 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; -import { Workbox } from 'workbox-window'; import 'i18n'; ReactDOM.render( @@ -10,17 +9,3 @@ ReactDOM.render( , document.getElementById('root') ); - -if ('serviceWorker' in navigator) { - const wb = new Workbox('sw.js'); - - wb.addEventListener('installed', event => { - if (event.isUpdate) { - if (window.confirm(`New content is available!. Click OK to refresh`)) { - window.location.reload(); - } - } - }); - - wb.register(); -}