aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Timeline/ClientApp/src/app/App.tsx10
-rw-r--r--Timeline/ClientApp/src/app/locales/en/translation.ts11
-rw-r--r--Timeline/ClientApp/src/app/locales/scheme.ts5
-rw-r--r--Timeline/ClientApp/src/app/locales/zh/translation.ts8
-rw-r--r--Timeline/ClientApp/src/app/service-worker.tsx63
5 files changed, 72 insertions, 25 deletions
diff --git a/Timeline/ClientApp/src/app/App.tsx b/Timeline/ClientApp/src/app/App.tsx
index befa2a9c..83ea4ea5 100644
--- a/Timeline/ClientApp/src/app/App.tsx
+++ b/Timeline/ClientApp/src/app/App.tsx
@@ -40,7 +40,7 @@ const App: React.FC = () => {
body = <LoadingPage />;
} else {
body = (
- <React.Suspense fallback={<LoadingPage />}>
+ <Router>
<Switch>
<Route exact path="/">
<Home />
@@ -69,15 +69,15 @@ const App: React.FC = () => {
<NoMatch />
</Route>
</Switch>
- </React.Suspense>
+ </Router>
);
}
return (
- <>
- <Router>{body}</Router>
+ <React.Suspense fallback={<LoadingPage />}>
+ {body}
<AlertHost />
- </>
+ </React.Suspense>
);
};
diff --git a/Timeline/ClientApp/src/app/locales/en/translation.ts b/Timeline/ClientApp/src/app/locales/en/translation.ts
index b9fa42c9..6bac41f9 100644
--- a/Timeline/ClientApp/src/app/locales/en/translation.ts
+++ b/Timeline/ClientApp/src/app/locales/en/translation.ts
@@ -5,9 +5,14 @@ const translation: TranslationResource = {
search: 'Search',
serviceWorker: {
availableOffline:
- 'This app will be cached in your computer and you can use it offline.',
- upgradeTitle: 'App is getting a new version!',
- upgradeNow: 'Upgrade Now',
+ 'Timeline is now cached in your computer and you can use it offline. 🎉🎉🎉',
+ upgradePrompt: 'App is getting a new version!',
+ upgradeNow: 'Update Now',
+ upgradeSuccess:
+ 'Congratulations! App update succeeded! Still you can use it offline. 🎉🎉🎉',
+ externalActivatedPrompt:
+ 'A new version of app is activated. Please refresh the page. Or it may be broken.',
+ reloadNow: 'Refresh Now',
},
nav: {
settings: 'Settings',
diff --git a/Timeline/ClientApp/src/app/locales/scheme.ts b/Timeline/ClientApp/src/app/locales/scheme.ts
index 0a8ce278..13d555d5 100644
--- a/Timeline/ClientApp/src/app/locales/scheme.ts
+++ b/Timeline/ClientApp/src/app/locales/scheme.ts
@@ -5,8 +5,11 @@ export default interface TranslationResource {
loadImageError: string;
serviceWorker: {
availableOffline: string;
- upgradeTitle: string;
+ upgradePrompt: string;
upgradeNow: string;
+ upgradeSuccess: string;
+ externalActivatedPrompt: string;
+ reloadNow: string;
};
nav: {
settings: string;
diff --git a/Timeline/ClientApp/src/app/locales/zh/translation.ts b/Timeline/ClientApp/src/app/locales/zh/translation.ts
index 03fb470a..fba06c7f 100644
--- a/Timeline/ClientApp/src/app/locales/zh/translation.ts
+++ b/Timeline/ClientApp/src/app/locales/zh/translation.ts
@@ -4,9 +4,13 @@ const translation: TranslationResource = {
welcome: '欢迎!',
search: '搜索',
serviceWorker: {
- availableOffline: '这个 App 将会缓存在本地,你将可以离线使用它。',
- upgradeTitle: 'App 有新版本!',
+ availableOffline: 'Timeline 已经缓存在本地,你可以离线使用它。🎉🎉🎉',
+ upgradePrompt: 'App 有新版本!',
upgradeNow: '现在升级',
+ upgradeSuccess: 'App 升级成功,当然,你仍可以离线使用它。 🎉🎉🎉',
+ externalActivatedPrompt:
+ '一个新的 App 版本已经激活,请刷新页面使用,否则页面可能会出现故障。',
+ reloadNow: '立刻刷新',
},
nav: {
settings: '设置',
diff --git a/Timeline/ClientApp/src/app/service-worker.tsx b/Timeline/ClientApp/src/app/service-worker.tsx
index ca59445e..0dbab480 100644
--- a/Timeline/ClientApp/src/app/service-worker.tsx
+++ b/Timeline/ClientApp/src/app/service-worker.tsx
@@ -1,16 +1,60 @@
import React from 'react';
-import { WorkboxLifecycleEvent } from 'workbox-window/utils/WorkboxEvent';
import { Button } from 'reactstrap';
import { useTranslation } from 'react-i18next';
import { pushAlert } from './common/alert-service';
if ('serviceWorker' in navigator) {
+ let isThisTriggerUpgrade = false;
+
+ const upgradeSuccessLocalStorageKey = 'TIMELINE_UPGRADE_SUCCESS';
+
+ if (window.localStorage.getItem(upgradeSuccessLocalStorageKey)) {
+ pushAlert({
+ message: {
+ type: 'i18n',
+ key: 'serviceWorker.upgradeSuccess',
+ },
+ type: 'success',
+ });
+ window.localStorage.removeItem(upgradeSuccessLocalStorageKey);
+ }
+
void import('workbox-window').then(({ Workbox, messageSW }) => {
const wb = new Workbox('/sw.js');
let registration: ServiceWorkerRegistration | undefined;
- const showFirstPrompt = (event: WorkboxLifecycleEvent): void => {
+ // externalactivated is not usable but I still use its name.
+ wb.addEventListener('controlling', () => {
+ const upgradeReload = (): void => {
+ window.localStorage.setItem(upgradeSuccessLocalStorageKey, 'true');
+ window.location.reload();
+ };
+
+ if (isThisTriggerUpgrade) {
+ upgradeReload();
+ } else {
+ const Message: React.FC = () => {
+ const { t } = useTranslation();
+ return (
+ <>
+ {t('serviceWorker.externalActivatedPrompt')}
+ <Button color="success" size="sm" onClick={upgradeReload} outline>
+ {t('serviceWorker.reloadNow')}
+ </Button>
+ </>
+ );
+ };
+
+ pushAlert({
+ message: Message,
+ dismissTime: 'never',
+ type: 'warning',
+ });
+ }
+ });
+
+ wb.addEventListener('activated', (event) => {
if (!event.isUpdate) {
pushAlert({
message: {
@@ -20,20 +64,11 @@ if ('serviceWorker' in navigator) {
type: 'success',
});
}
- };
-
- wb.addEventListener('activated', showFirstPrompt);
- wb.addEventListener('externalactivated', showFirstPrompt);
+ });
const showSkipWaitingPrompt = (): void => {
const upgrade = (): void => {
- // Assuming the user accepted the update, set up a listener
- // that will reload the page as soon as the previously waiting
- // service worker has taken control.
- wb.addEventListener('controlling', () => {
- window.location.reload();
- });
-
+ isThisTriggerUpgrade = true;
if (registration && registration.waiting) {
// Send a message to the waiting service worker,
// instructing it to activate.
@@ -47,7 +82,7 @@ if ('serviceWorker' in navigator) {
const { t } = useTranslation();
return (
<>
- {t('serviceWorker.upgradeTitle')}
+ {t('serviceWorker.upgradePrompt')}
<Button color="success" size="sm" onClick={upgrade} outline>
{t('serviceWorker.upgradeNow')}
</Button>