Offline support

This commit is contained in:
Dallas Hoffman 2023-10-13 00:45:28 -04:00
parent 48c3b4b37e
commit fe2efb6790
No known key found for this signature in database
12 changed files with 4371 additions and 1 deletions

4289
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
"@sveltejs/adapter-static": "^2.0.3", "@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.20.4", "@sveltejs/kit": "^1.20.4",
"@vite-pwa/assets-generator": "^0.0.10", "@vite-pwa/assets-generator": "^0.0.10",
"@vite-pwa/sveltekit": "^0.2.7",
"patch-package": "^8.0.0", "patch-package": "^8.0.0",
"prettier": "^2.8.0", "prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.10.1", "prettier-plugin-svelte": "^2.10.1",

2
src/app.d.ts vendored
View File

@ -1,3 +1,5 @@
/// <reference types="vite-plugin-pwa/svelte" />
// See https://kit.svelte.dev/docs/types#app // See https://kit.svelte.dev/docs/types#app
// for information about these interfaces // for information about these interfaces
declare global { declare global {

View File

@ -0,0 +1,65 @@
<script lang="ts">
import { useRegisterSW } from 'virtual:pwa-register/svelte';
import Button from './button.svelte';
const { needRefresh, updateServiceWorker } = useRegisterSW({
onRegisteredSW(swUrl, registration) {
if (!registration) return;
setInterval(async () => {
if (!(!registration.installing && navigator)) return;
if ('connection' in navigator && !navigator.onLine) return;
const sw = await fetch(swUrl, {
cache: 'no-store',
headers: {
cache: 'no-store',
'cache-control': 'no-cache',
},
});
if (sw?.status === 200) await registration.update();
}, 60 * 60 * 1000);
},
});
function close() {
needRefresh.set(false);
}
</script>
{#if $needRefresh}
<div role="alert" class="app-update-prompt">
<p class="app-update-prompt__text">The app has been updated. Reload to update.</p>
<div class="app-update-prompt__buttons">
<Button on:click={() => updateServiceWorker(true)}>Reload</Button>
<Button secondary on:click={close}>Dismiss</Button>
</div>
</div>
{/if}
<style lang="scss">
.app-update-prompt {
position: fixed;
left: 1rem;
bottom: 2rem;
padding: 1rem;
min-width: 200px;
max-width: calc(50vw - 1rem);
border-radius: var(--border-radius);
background-color: var(--secondary-alt);
box-shadow: var(--card-shadow);
&__text {
color: var(--primary-inverse);
text-wrap: pretty;
}
&__buttons {
display: flex;
gap: 0.5rem;
width: fit-content;
margin-right: auto;
}
}
</style>

View File

@ -22,7 +22,7 @@
height: 4rem; height: 4rem;
margin: 0; margin: 0;
border-radius: 50%; border-radius: 50%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); box-shadow: var(--card-shadow);
& > :global(svg) { & > :global(svg) {
width: 2rem; width: 2rem;

View File

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import AppHeader from '$lib/components/app-header.svelte'; import AppHeader from '$lib/components/app-header.svelte';
import AppUpdatePrompt from '$lib/components/app-update-prompt.svelte';
import FilterTags from '$lib/components/filter-tags.svelte'; import FilterTags from '$lib/components/filter-tags.svelte';
import NoteAddButton from '$lib/components/notes/note-add-button.svelte'; import NoteAddButton from '$lib/components/notes/note-add-button.svelte';
import NoteListPlaceholder from '$lib/components/notes/note-list-placeholder.svelte'; import NoteListPlaceholder from '$lib/components/notes/note-list-placeholder.svelte';
@ -27,6 +28,7 @@
</main> </main>
<WelcomeModal /> <WelcomeModal />
<SettingsModal /> <SettingsModal />
<AppUpdatePrompt />
<style lang="scss"> <style lang="scss">
main { main {

Binary file not shown.

View File

@ -1,5 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite'; import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import { SvelteKitPWA } from '@vite-pwa/sveltekit';
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
@ -14,6 +15,16 @@ export default defineConfig({
}); });
}, },
}, },
SvelteKitPWA({
strategies: 'generateSW',
registerType: 'prompt',
manifest: false,
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,ttf,wasm}'],
globIgnores: ['**/apple-splash-*'],
maximumFileSizeToCacheInBytes: 5000000,
},
}),
], ],
build: { build: {
target: 'esnext', target: 'esnext',