add PWA support

This commit is contained in:
mrjvs 2023-02-24 19:23:00 +01:00
parent e68fe0e115
commit 3a1c3ad260
10 changed files with 1510 additions and 1354 deletions

View File

@ -43,6 +43,7 @@ module.exports = {
"no-shadow": "off", "no-shadow": "off",
"@typescript-eslint/no-shadow": ["error"], "@typescript-eslint/no-shadow": ["error"],
"no-restricted-syntax": "off", "no-restricted-syntax": "off",
"import/no-unresolved": ["error", { ignore: ["^virtual:"] }],
"react/jsx-props-no-spreading": "off", "react/jsx-props-no-spreading": "off",
"consistent-return": "off", "consistent-return": "off",
"no-continue": "off", "no-continue": "off",

1
.gitignore vendored
View File

@ -10,6 +10,7 @@ node_modules
# production # production
/dist /dist
dev-dist
# misc # misc
.DS_Store .DS_Store

View File

@ -1,5 +1,8 @@
{ {
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint", "editor.defaultFormatter": "dbaeumer.vscode-eslint",
"eslint.format.enable": true "eslint.format.enable": true,
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
} }

View File

@ -6,16 +6,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta <meta
name="description" name="description"
content="Because watching movies legally is boring" content="The place for your favourite movies & shows"
/> />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" /> <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#120f1d" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#E880C5" /> <meta name="msapplication-TileColor" content="#120f1d" />
<meta name="msapplication-TileColor" content="#E880C5" /> <meta name="theme-color" content="#120f1d" />
<meta name="theme-color" content="#E880C5" />
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />

View File

@ -86,6 +86,7 @@
"vite": "^4.0.1", "vite": "^4.0.1",
"vite-plugin-checker": "^0.5.6", "vite-plugin-checker": "^0.5.6",
"vite-plugin-package-version": "^1.0.2", "vite-plugin-package-version": "^1.0.2",
"vite-plugin-pwa": "^0.14.4",
"vitest": "^0.28.5" "vitest": "^0.28.5"
} }
} }

View File

@ -1,20 +0,0 @@
{
"name": "movie-web",
"short_name": "movie-web",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#E880C5",
"background_color": "#16171D",
"display": "standalone",
"start_url": "/"
}

View File

@ -1,4 +1,5 @@
import { Redirect, Route, Switch } from "react-router-dom"; import { Redirect, Route, Switch } from "react-router-dom";
import { useRegisterSW } from "virtual:pwa-register/react";
import { BookmarkContextProvider } from "@/state/bookmark"; import { BookmarkContextProvider } from "@/state/bookmark";
import { WatchedContextProvider } from "@/state/watched"; import { WatchedContextProvider } from "@/state/watched";
@ -12,10 +13,66 @@ import { VideoTesterView } from "@/views/developer/VideoTesterView";
import { ProviderTesterView } from "@/views/developer/ProviderTesterView"; import { ProviderTesterView } from "@/views/developer/ProviderTesterView";
import { EmbedTesterView } from "@/views/developer/EmbedTesterView"; import { EmbedTesterView } from "@/views/developer/EmbedTesterView";
function ReloadPrompt() {
const {
offlineReady: [offlineReady, setOfflineReady],
needRefresh: [needRefresh, setNeedRefresh],
updateServiceWorker,
} = useRegisterSW({
onRegistered(r) {
// eslint-disable-next-line prefer-template
console.log("SW Registered: " + r);
},
onRegisterError(error) {
console.log("SW registration error", error);
},
});
const close = () => {
setOfflineReady(false);
setNeedRefresh(false);
};
return (
<div className="ReloadPrompt-container">
{(offlineReady || needRefresh) && (
<div className="ReloadPrompt-toast">
<div className="ReloadPrompt-message">
{offlineReady ? (
<span>App ready to work offline</span>
) : (
<span>
New content available, click on reload button to update.
</span>
)}
</div>
{needRefresh && (
<button
type="button"
className="ReloadPrompt-toast-button"
onClick={() => updateServiceWorker(true)}
>
Reload
</button>
)}
<button
type="button"
className="ReloadPrompt-toast-button"
onClick={() => close()}
>
Close
</button>
</div>
)}
</div>
);
}
function App() { function App() {
return ( return (
<WatchedContextProvider> <WatchedContextProvider>
<BookmarkContextProvider> <BookmarkContextProvider>
<ReloadPrompt />
<Switch> <Switch>
{/* functional routes */} {/* functional routes */}
<Route exact path="/v2-migration" component={V2MigrationView} /> <Route exact path="/v2-migration" component={V2MigrationView} />

View File

@ -19,7 +19,7 @@
"paths": { "paths": {
"@/*": ["./*"] "@/*": ["./*"]
}, },
"types": ["vite/client"] "types": ["vite/client", "vite-plugin-pwa/client"]
}, },
"include": ["src"] "include": ["src"]
} }

View File

@ -1,12 +1,46 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react-swc"; import react from "@vitejs/plugin-react-swc";
import loadVersion from "vite-plugin-package-version"; import loadVersion from "vite-plugin-package-version";
import { VitePWA } from "vite-plugin-pwa";
import checker from "vite-plugin-checker"; import checker from "vite-plugin-checker";
import path from "path"; import path from "path";
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
react(), react(),
VitePWA({
registerType: "autoUpdate",
injectRegister: "inline",
devOptions: {
enabled: true,
},
includeAssets: [
"favicon.ico",
"apple-touch-icon.png",
"safari-pinned-tab.svg",
],
manifest: {
name: "movie-web",
short_name: "movie-web",
description: "The place for your favourite movies & shows",
theme_color: "#120f1d",
background_color: "#120f1d",
display: "standalone",
start_url: "/",
icons: [
{
src: "android-chrome-192x192.png",
sizes: "192x192",
type: "image/png",
},
{
src: "android-chrome-512x512.png",
sizes: "512x512",
type: "image/png",
},
],
},
}),
loadVersion(), loadVersion(),
checker({ checker({
typescript: true, // check typescript build errors in dev server typescript: true, // check typescript build errors in dev server

2734
yarn.lock

File diff suppressed because it is too large Load Diff