diff options
| author | Alexis Hovorka <[email protected]> | 2022-01-09 19:53:09 -0700 | 
|---|---|---|
| committer | Alexis Hovorka <[email protected]> | 2022-01-09 19:53:09 -0700 | 
| commit | 0278a785d3ae63117215050899ac4b053bfe3e55 (patch) | |
| tree | 04aab7d3741107980433d4316eef5f7e0e4926ff /app/public | |
Initial commit
Diffstat (limited to 'app/public')
| -rw-r--r-- | app/public/404.html | 1 | ||||
| -rw-r--r-- | app/public/500.html | 1 | ||||
| -rw-r--r-- | app/public/index.html | 64 | ||||
| -rw-r--r-- | app/public/main.js | 18 | ||||
| -rw-r--r-- | app/public/manifest.webmanifest | 26 | ||||
| -rw-r--r-- | app/public/sock.js | 43 | ||||
| -rw-r--r-- | app/public/style.css | 14 | ||||
| -rw-r--r-- | app/public/sw1.js | 29 | ||||
| -rw-r--r-- | app/public/sw2.js | 40 | 
9 files changed, 236 insertions, 0 deletions
diff --git a/app/public/404.html b/app/public/404.html new file mode 100644 index 0000000..1a43d0a --- /dev/null +++ b/app/public/404.html @@ -0,0 +1 @@ +<pre>404 Not Found</pre> diff --git a/app/public/500.html b/app/public/500.html new file mode 100644 index 0000000..ee07335 --- /dev/null +++ b/app/public/500.html @@ -0,0 +1 @@ +<pre>500 Internal Server Error</pre> diff --git a/app/public/index.html b/app/public/index.html new file mode 100644 index 0000000..3c435f5 --- /dev/null +++ b/app/public/index.html @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<html lang="en"> +  <head> +    <title>Notes</title> +    <meta charset="UTF-8"> + +    <meta http-equiv="X-UA-Compatible" content="IE=edge"> +    <meta name="viewport" content="user-scalable=no,width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1"> + +    <!--link rel="icon" type="image/x-icon" href="favicon.ico"> +    <link rel="apple-touch-icon" href="img/apple-touch-icon-57.png"        sizes="57x57"    > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-60.png"        sizes="60x60"    > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-72.png"        sizes="72x72"    > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-76.png"        sizes="76x76"    > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-114.png"       sizes="114x114"  > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-120.png"       sizes="120x120"  > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-144.png"       sizes="144x144"  > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-152.png"       sizes="152x152"  > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-168.png"       sizes="168x168"  > +    <link rel="apple-touch-icon" href="img/apple-touch-icon-180.png"       sizes="180x180"  > +    <link rel="apple-touch-startup-image" href="img/apple-splash-2048.png" sizes="2048x2732"> +    <link rel="apple-touch-startup-image" href="img/apple-splash-1668.png" sizes="1668x2224"> +    <link rel="apple-touch-startup-image" href="img/apple-splash-1536.png" sizes="1536x2048"> +    <link rel="apple-touch-startup-image" href="img/apple-splash-1125.png" sizes="1125x2436"> +    <link rel="apple-touch-startup-image" href="img/apple-splash-1242.png" sizes="1242x2208"> +    <link rel="apple-touch-startup-image" href="img/apple-splash-750.png"  sizes="750x1334" > +    <link rel="apple-touch-startup-image" href="img/apple-splash-640.png"  sizes="640x1136" > +    <link rel="icon" type="image/png"     href="img/favicon-32.png"        sizes="32x32"    > +    <link rel="icon" type="image/png"     href="img/favicon-192.png"       sizes="192x192"  ><!- - Maskable:           - -> +    <link rel="icon" type="image/png"     href="img/favicon-256.png"       sizes="256x256"  ><!- - Safe area is circle - -> +    <link rel="icon" type="image/png"     href="img/favicon-512.png"       sizes="512x512"  ><!- - with 40% radius     - -> +    <link rel="icon" type="image/png"     href="img/favicon-96.png"        sizes="96x96"    > +    <link rel="icon" type="image/png"     href="img/favicon-48.png"        sizes="48x48"    > +    <link rel="icon" type="image/png"     href="img/favicon-16.png"        sizes="16x16"    > +    <link rel="shortcut icon" type="image/x-icon" href="favicon.ico"> +    <link rel="manifest" href="manifest.webmanifest"> + +    <meta name="mobile-web-app-capable" content="yes"> +    <meta name="apple-mobile-web-app-capable" content="yes"> +    <meta name="apple-mobile-web-app-title" content="Notes"> +    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> +    <meta name="application-name" content="Notes"> +    <meta name="msapplication-TileColor" content="#000000"> +    <meta name="msapplication-TileImage" content="img/mstile-144.png"> +    <meta name="msapplication-navbutton-color" content="#000000"> +    <meta name="msapplication-tooltip" content="Notes"> +    <meta name="msapplication-starturl" content="/"> +    <meta name="msapplication-tap-highlight" content="no"> +    <meta name="theme-color" content="#000000"--> + +    <link rel="canonical" href="https://notes.ahov.co/"> +    <meta name="author" content="Alexis Hovorka"> +    <meta name="description" content="Zettelkasten-inspired note taking web app"> + +    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400&display=swap"> +    <link rel="stylesheet" href="style.css"> +  </head> +  <body> +    <h1>Notes</h1> + +    <!--script src="sock.js"></script--> +    <script src="main.js"></script> +  </body> +</html> diff --git a/app/public/main.js b/app/public/main.js new file mode 100644 index 0000000..ff960c2 --- /dev/null +++ b/app/public/main.js @@ -0,0 +1,18 @@ +document.addEventListener("DOMContentLoaded", async () => { "use strict"; + +const secure = location.protocol === "https:"; +const $ = (s,c) => (c||document).querySelector(s); +function $$(x,y,z,a){a=(z||document).querySelectorAll(x);if(typeof y=="function")[].forEach.call(a,y);return a} +function m(a,b,c){c=document;b=c.createElement(b||"p");b.innerHTML=a.trim();for(a=c.createDocumentFragment();c=b.firstChild;)a.appendChild(c);return a.firstChild} + +//sock.init(`ws${secure?"s":""}://${location.host}/ws`); +//sock.on("hello", e => { +//  console.log("hello", e); +//  sock.send("world", {foo:"bar"}); +//}); + +//if ("serviceWorker" in navigator) { +//  navigator.serviceWorker.register("sw.js") +//    .then(() => console.log("Service worker registered")); +//} +}); diff --git a/app/public/manifest.webmanifest b/app/public/manifest.webmanifest new file mode 100644 index 0000000..9eb9f13 --- /dev/null +++ b/app/public/manifest.webmanifest @@ -0,0 +1,26 @@ +{ +  "name": "Notes", +  "short_name": "Notes", +  "description": "Zettelkasten-inspired note taking web app", +  "categories": ["productivity", "utilities"], +  "lang": "en-US", +  "start_url": "/", +  "scope": "/", +  "display": "standalone", +  "theme_color": "#000000", +  "background_color": "#000000", +  "icons": [ +    {"type": "image/png", "sizes": "48x48",   "src": "img/favicon-48.png" }, +    {"type": "image/png", "sizes": "96x96",   "src": "img/favicon-96.png" }, +    {"type": "image/png", "sizes": "192x192", "src": "img/favicon-192.png", "purpose": "maskable any"}, +    {"type": "image/png", "sizes": "256x256", "src": "img/favicon-256.png", "purpose": "maskable any"}, +    {"type": "image/png", "sizes": "512x512", "src": "img/favicon-512.png", "purpose": "maskable any"}, + +    {"type": "image/png", "sizes": "72x72",   "src": "img/apple-touch-icon-72.png" }, +    {"type": "image/png", "sizes": "144x144", "src": "img/apple-touch-icon-144.png"}, +    {"type": "image/png", "sizes": "168x168", "src": "img/apple-touch-icon-168.png"} +  ], +  "shortcuts": [ +    {"name": "New", "url": "/new"} +  ] +} diff --git a/app/public/sock.js b/app/public/sock.js new file mode 100644 index 0000000..b4905e5 --- /dev/null +++ b/app/public/sock.js @@ -0,0 +1,43 @@ +const sock = (() => { "use strict"; +const refresh = () => setTimeout(() => location.reload(), 1e3); + +let ws, pingTimeout; +const prequeue = []; +const handlers = { +  "reset": [refresh], +  "ping": [() => { +    clearTimeout(pingTimeout); +    pingTimeout = setTimeout(refresh, 3e4); +    sock.send("pong", {}); +  }], +}; + +const sock = { +  init: url => { +    ws = new WebSocket(url); +    ws.addEventListener("close", refresh); +    ws.addEventListener("error", refresh); +    ws.addEventListener("message", e => { +      const d = JSON.parse(e.data); +      (handlers[d.type]||[]).forEach(cb => cb(d.data)); +    }); +    ws.addEventListener("open", e => { +      while (prequeue.length) sock.send(...prequeue.shift()); +      (handlers["open"]||[]).forEach(cb => cb()); +      delete handlers["open"]; +    }); +  }, + +  on: (type, cb) => { +    if (type === "open" && ws && ws.readyState === WebSocket.OPEN) cb(); +    else (handlers[type]||(handlers[type]=[])).push(cb); +  }, + +  send: (type, data) => { +    if (ws && ws.readyState === WebSocket.OPEN) +      ws.send(JSON.stringify({type, data})); +    else prequeue.push([type, data]); +  }, +}; + +return sock })(); diff --git a/app/public/style.css b/app/public/style.css new file mode 100644 index 0000000..655e181 --- /dev/null +++ b/app/public/style.css @@ -0,0 +1,14 @@ +* { +  margin: 0; +  padding: 0; +  box-sizing: border-box; +  font-family: "Roboto", "Noto Sans", sans-serif; +  transition-timing-function: ease-in-out; +} + +body { +          user-select: none; +  -webkit-user-select: none; +  -webkit-touch-callout: none; +  -webkit-tap-highlight-color: transparent; +} diff --git a/app/public/sw1.js b/app/public/sw1.js new file mode 100644 index 0000000..37ae5e5 --- /dev/null +++ b/app/public/sw1.js @@ -0,0 +1,29 @@ +// https://gist.github.com/adactio/3717b7da007a9363ddf21f584aae34af + +// HTML files: try the network first, then the cache. +// Other files: try the cache first, then the network. +// Both: cache a fresh version if possible. +// (beware: the cache will grow and grow; there's no cleanup) + +const cacheName = "notes-cache-v1"; + +addEventListener("fetch", fetchEvent => { +  const request = fetchEvent.request; +  if (request.method !== "GET") return; +  fetchEvent.respondWith(async () => { +    const fetchPromise = fetch(request); +    fetchEvent.waitUntil(async () => { +      const responseFromFetch = await fetchPromise; +      const responseCopy = responseFromFetch.clone(); +      const myCache = await caches.open(cacheName); +      return myCache.put(request, responseCopy); +    }()); +    if (request.headers.get("Accept").includes("text/html")) { +      try { return await fetchPromise; } +      catch(error) { return caches.match(request); } +    } else { +      const responseFromCache = await caches.match(request); +      return responseFromCache || fetchPromise; +    } +  }()); +}); diff --git a/app/public/sw2.js b/app/public/sw2.js new file mode 100644 index 0000000..0dabb13 --- /dev/null +++ b/app/public/sw2.js @@ -0,0 +1,40 @@ +// https://googlechrome.github.io/samples/service-worker/basic/ + +const PRECACHE = "notes-precache-v1"; +const RUNTIME = "notes-runtime"; + +const PRECACHE_URLS = [ +  "./", // Alias for index.html +  "index.html", +  "style.css", +  "main.js" +]; + +self.addEventListener("install", e => e.waitUntil( +  caches.open(PRECACHE) +    .then(cache => cache.addAll(PRECACHE_URLS)) +    .then(self.skipWaiting()))); + +self.addEventListener("activate", e => { +  const currentCaches = [PRECACHE, RUNTIME]; +  e.waitUntil( // Clean up old caches +    caches.keys().then(cacheNames => +      cacheNames.filter(cacheName => !currentCaches.includes(cacheName)) +    ).then(cachesToDelete => Promise.all(cachesToDelete.map(cacheToDelete => +      caches.delete(cacheToDelete))) +    ).then(() => self.clients.claim()) +  ); +}); + +self.addEventListener("fetch", e => { +  if (e.request.url.startsWith(self.location.origin)) { +    e.respondWith(caches.match(e.request).then(cachedResponse => +      cachedResponse? cachedResponse +      : caches.open(RUNTIME).then(cache => +        fetch(e.request).then(res => +          cache.put(e.request, res.clone()).then(() => res) +        ) +      ) +    )); +  } +});  | 
