Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion packages/web/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<meta name="og:title" content="Standard Notes, an end-to-end encrypted notes app."/>
<meta name="og:description" content="Standard Notes is an easy-to-use encrypted note-taking app for digitalists and professionals. Capture your notes, documents, and life's work all in one place."/>

<!-- CSP script-src hash: sha256-r26E+iPOhx7KM7cKn4trOSoD8u5E7wL7wwJ8UrR+rGs= -->
<!-- CSP script-src hashes: sha256-r26E+iPOhx7KM7cKn4trOSoD8u5E7wL7wwJ8UrR+rGs= (config), sha256-ZRgzGkk7dE5Vafy/x+4fOkq6Ysvyn2dpddLN4XBd9hI= (sw reg) -->
<script>
window.defaultSyncServer = "https://api.standardnotes.com";
window.defaultFilesHost = "https://files.standardnotes.com";
Expand All @@ -45,5 +45,14 @@
<link rel="stylesheet" media="all" href="./app.css" debug="false" />
</head>
<body>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').catch(function(err) {
console.log('SW registration failed:', err)
})
})
}
</script>
</body>
</html>
88 changes: 88 additions & 0 deletions packages/web/src/sw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
const CACHE_NAME = 'sn-app-v1'

// keep in sync with webpack copy patterns in web.webpack.config.js
const APP_SHELL = [
'/',
'/index.html',
'/app.js',
'/app.css',
'/favicon/favicon.ico',
'/favicon/favicon-32x32.png',
'/favicon/apple-touch-icon.png',
'/manifest.webmanifest',
]

self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(APP_SHELL)
})
)
// dont wait for old tabs to close
self.skipWaiting()
})

self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((names) => {
return Promise.all(
names
.filter((name) => name !== CACHE_NAME)
.map((name) => caches.delete(name))
)
})
)
self.clients.claim()
})

self.addEventListener('fetch', (event) => {
const { request } = event

// let API calls and websocket stuff go straight to network
if (request.url.includes('/api/') || request.url.includes('/socket')) {
return
}

// navigation requests: network first, fall back to cached shell
if (request.mode === 'navigate') {
event.respondWith(
fetch(request)
.then((resp) => {
// stash a fresh copy if it's good
if (resp.ok) {
const clone = resp.clone()
caches.open(CACHE_NAME).then((cache) => cache.put(request, clone))
}
return resp
})
.catch(() => caches.match('/index.html'))
)
return
}

// everything else: cache first, then network
event.respondWith(
caches.match(request).then((cached) => {
if (cached) {
// refresh cache in bg
fetch(request)
.then((resp) => {
if (resp.ok) {
caches.open(CACHE_NAME).then((cache) => cache.put(request, resp))
}
})
.catch(() => {})
return cached
}

return fetch(request).then((resp) => {
// only cache same-origin stuff
if (resp.ok && new URL(request.url).origin === self.location.origin) {
const clone = resp.clone()
caches.open(CACHE_NAME).then((cache) => cache.put(request, clone))
}
return resp
})
})
)
})
1 change: 1 addition & 0 deletions packages/web/web.webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module.exports = (env) => {
{ from: 'src/500.html' },
{ from: 'src/index.html' },
{ from: 'src/manifest.webmanifest' },
{ from: 'src/sw.js' },
{ from: 'src/robots.txt' },
{ from: 'src/.well-known', to: '.well-known' },
]
Expand Down
2 changes: 1 addition & 1 deletion packages/web/web.webpack.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module.exports = (env, argv) => {
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Security-Policy':
"default-src https: 'self'; base-uri 'self'; child-src * blob:; connect-src * blob:; font-src * data:; form-action 'self'; frame-ancestors * file:; frame-src * blob:; img-src 'self' * data: blob:; manifest-src 'self'; media-src 'self' blob: *.standardnotes.com; object-src 'self' blob: *.standardnotes.com; script-src 'self' 'sha256-r26E+iPOhx7KM7cKn4trOSoD8u5E7wL7wwJ8UrR+rGs=' 'unsafe-eval' 'wasm-unsafe-eval'; style-src *;",
"default-src https: 'self'; base-uri 'self'; child-src * blob:; connect-src * blob:; font-src * data:; form-action 'self'; frame-ancestors * file:; frame-src * blob:; img-src 'self' * data: blob:; manifest-src 'self'; media-src 'self' blob: *.standardnotes.com; object-src 'self' blob: *.standardnotes.com; script-src 'self' 'sha256-r26E+iPOhx7KM7cKn4trOSoD8u5E7wL7wwJ8UrR+rGs=' 'sha256-ZRgzGkk7dE5Vafy/x+4fOkq6Ysvyn2dpddLN4XBd9hI=' 'unsafe-eval' 'wasm-unsafe-eval'; worker-src 'self'; style-src *;",
},
hot: true,
static: './dist',
Expand Down