From 22a7603c210f8dc3941d8d11da36c8c035e0aac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Zed=C3=A9n=20Yver=C3=A5s?= Date: Fri, 12 Jul 2024 22:44:34 +0200 Subject: [PATCH] fix: minor PWA fixes and implement offline support Minor fixes such as setting the start_url to `/editor`. Also add complete offline support by updating configuration. This is especially nice for mobile users. I've had some slight issues running this via `npm run dev`. However, `npm run build && npm run preview` seems to work fine. --- .gitignore | 1 + package-lock.json | 3 +- package.json | 3 +- src/App.jsx | 2 + src/components/EditorHeader/ControlPanel.jsx | 24 ++++-- src/components/PwaUpdatePrompt.jsx | 34 ++++++++ src/i18n/locales/en.js | 4 + vite.config.js | 90 +++++++++++--------- 8 files changed, 113 insertions(+), 48 deletions(-) create mode 100644 src/components/PwaUpdatePrompt.jsx diff --git a/.gitignore b/.gitignore index 7ceb59f..5bf9e0c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ lerna-debug.log* node_modules dist dist-ssr +dev-dist *.local # Editor directories and files diff --git a/package-lock.json b/package-lock.json index adf9eab..612dd74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,8 @@ "prettier": "3.2.5", "tailwindcss": "^3.3.6", "vite": "^5.0.11", - "vite-plugin-pwa": "^0.20.0" + "vite-plugin-pwa": "^0.20.0", + "workbox-window": "^7.1.0" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/package.json b/package.json index f1b1221..d156450 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "prettier": "3.2.5", "tailwindcss": "^3.3.6", "vite": "^5.0.11", - "vite-plugin-pwa": "^0.20.0" + "vite-plugin-pwa": "^0.20.0", + "workbox-window": "^7.1.0" }, "overrides": { "follow-redirects": "^1.15.4" diff --git a/src/App.jsx b/src/App.jsx index 7268dce..5681664 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -9,6 +9,7 @@ import LandingPage from "./pages/LandingPage"; import SettingsContextProvider from "./context/SettingsContext"; import useSettings from "./hooks/useSettings"; import NotFound from "./pages/NotFound"; +import { PwaUpdatePrompt } from "./components/PwaUpdatePrompt"; export default function App() { return ( @@ -53,6 +54,7 @@ export default function App() { } /> + ); } diff --git a/src/components/EditorHeader/ControlPanel.jsx b/src/components/EditorHeader/ControlPanel.jsx index 089167f..828db29 100644 --- a/src/components/EditorHeader/ControlPanel.jsx +++ b/src/components/EditorHeader/ControlPanel.jsx @@ -1,6 +1,8 @@ import { useState } from "react"; +import { useRegisterSW } from "virtual:pwa-register/react"; import { IconCaretdown, + IconCloud, IconChevronRight, IconChevronUp, IconChevronDown, @@ -18,6 +20,7 @@ import { InputNumber, Tooltip, Spin, + Tag, Toast, Popconfirm, } from "@douyinfe/semi-ui"; @@ -1287,9 +1290,13 @@ export default function ControlPanel({ }); useHotkeys("ctrl+alt+w, meta+alt+w", fitWindow, { preventDefault: true }); + const { + offlineReady: [isOfflineReady], + } = useRegisterSW(); + return ( <> - {layout.header && header()} + {layout.header && header(isOfflineReady)} {layout.toolbar && toolbar()} -
+
-
+
{databases[database].image && ( {(showEditName || modal === MODAL.RENAME) && }
-
+
{Object.keys(menu).map((category) => ( {getState()} + {isOfflineReady && ( + + } size="large"> + {t("available_offline")} + + + )}
diff --git a/src/components/PwaUpdatePrompt.jsx b/src/components/PwaUpdatePrompt.jsx new file mode 100644 index 0000000..c0a32a3 --- /dev/null +++ b/src/components/PwaUpdatePrompt.jsx @@ -0,0 +1,34 @@ +import { useRegisterSW } from "virtual:pwa-register/react"; +import { Typography, Toast } from "@douyinfe/semi-ui"; +import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +const { Text } = Typography; + +export function PwaUpdatePrompt() { + const { t } = useTranslation(); + const { + needRefresh: [isRefreshNeeded], + updateServiceWorker, + } = useRegisterSW(); + + useEffect(() => { + if (!isRefreshNeeded) return; + + Toast.info({ + duration: 0, // indefinite + content: ( +
+
{t("update_available")}
+

{t("reload_page_to_update")}

+
+ + {t("reload_now")} + +
+
+ ), + }); + }, [isRefreshNeeded, updateServiceWorker, t]); + + return <>; +} diff --git a/src/i18n/locales/en.js b/src/i18n/locales/en.js index 813f5a1..4dcfc5c 100644 --- a/src/i18n/locales/en.js +++ b/src/i18n/locales/en.js @@ -6,6 +6,10 @@ const english = { const en = { translation: { + available_offline: "Available offline", + update_available: "An updated version of drawDB is available!", + reload_page_to_update: "Reload the page to update", + reload_now: "Reload now", report_bug: "Report a bug", import: "Import", file: "File", diff --git a/vite.config.js b/vite.config.js index d593648..68d11e5 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,47 +1,55 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import { VitePWA } from "vite-plugin-pwa"; -const manifestForPlugIn = { - registerType: "prompt", - includeAssests: ["favicon.ico", "apple-touc-icon.png"], - manifest: { - name: "DrawDB", - short_name: "DrawDB", - icons: [ - { - src: "/pwa-192x192.png", - sizes: "192x192", - type: "image/png", - purpose: "any", - }, - { - src: "/pwa-512x512.png", - sizes: "512x512", - type: "image/png", - purpose: "any", - }, - { - src: "/pwa-maskable-192x192.png", - sizes: "192x192", - type: "image/png", - purpose: "maskable", - }, - { - src: "/pwa-maskable-512x512.png", - sizes: "512x512", - type: "image/png", - purpose: "maskable", - }, - ], - start_url: "/editor", - display: "standalone", - background_color: "#14475b", - theme_color: "#14475b", - description: - "Free, simple, and intuitive database design tool and SQL generator.", - }, -}; + // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react(), VitePWA(manifestForPlugIn)], + plugins: [ + react(), + VitePWA({ + workbox: { + globPatterns: ["**/*"], + maximumFileSizeToCacheInBytes: 15_000_000, + }, + includeAssets: ["**/*"], + registerType: "prompt", + manifest: { + name: "DrawDB", + short_name: "DrawDB", + icons: [ + { + src: "/pwa-192x192.png", + sizes: "192x192", + type: "image/png", + purpose: "any", + }, + { + src: "/pwa-512x512.png", + sizes: "512x512", + type: "image/png", + purpose: "any", + }, + { + src: "/pwa-maskable-192x192.png", + sizes: "192x192", + type: "image/png", + purpose: "maskable", + }, + { + src: "/pwa-maskable-512x512.png", + sizes: "512x512", + type: "image/png", + purpose: "maskable", + }, + ], + scope: "/", + start_url: "/editor", + display: "standalone", + background_color: "#14475b", + theme_color: "#14475b", + description: + "Free, simple, and intuitive database design tool and SQL generator.", + }, + }), + ], });