jbdoderlein / BetterOCaml

A small but efficient, intuitive and responsive OCaml IDE right in your browser! Ships OCaml v5.1.1, interpreter by your browser (so it works offline!), compiled with js_of_ocaml.
https://jbdoderlein.github.io/BetterOCaml/
Apache License 2.0
38 stars 8 forks source link

Could a service worker help offline usage? It worked! See this GIF demo #13

Closed Naereen closed 3 years ago

Naereen commented 3 years ago

I used this example and it worked!

Naereen commented 3 years ago

So the code to add is given below. I prefer to just give it here, rather than submit a PR, so you can try on your own up-to-date branch (with mobile-aware CSS), and add this feature only when you will be happy about it :+1:

Naereen commented 3 years ago

        // Chargement et events
        window.addEventListener("load", function () {
            new Resizer(document.querySelector('[name=resizerH1]'), 'V');
            document.getElementById('box_1').style.fontSize = "1.2em";
            document.getElementById('box_2').style.fontSize = "1.2em";

            /* beginning of new stuff to have service workers! */
            if('serviceWorker' in navigator){
                try {
                    navigator.serviceWorker.register('serviceWorker.js');
                    console.log("Service Worker Registered");
                } catch (error) {
                    console.log("Service Worker Registration Failed");
                }
            }
            /* end of new stuff to have service workers! */
        }, false);
Naereen commented 3 years ago
/*
  Service worker for BetterOCaml offline use

  - References: https://levelup.gitconnected.com/build-a-pwa-using-only-vanilla-javascript-bdf1eee6f37a
*/

console.log("Starting serviceWorker.js");

const staticAssets = [
  // './',
  './manifest.json',
  './index.html',
  './favicon.ico',
  './cache.appcache',
  // './css/',
  './css/bootstrap.css',
  './css/icon.css',
  './css/index.css',
  './css/codemirror/codemirror.min.css',
  './css/codemirror/dialog.css',
  './css/iconfont/MaterialIcons-Regular.eot',
  './css/iconfont/MaterialIcons-Regular.ttf',
  './css/iconfont/MaterialIcons-Regular.woff',
  './css/iconfont/MaterialIcons-Regular.woff2',
  './css/materialize/materialize.min.css',
  './css/theme/material.css',
  './css/theme/mdn-like.css',
  './css/theme/monokai.css',
  // './icon/',
  './icon/apple-touch-icon.png',
  './icon/android-chrome-192x192.png',
  './icon/android-chrome-512x512.png',
  './icon/favicon-16x16.png',
  './icon/favicon-32x32.png',
  // './screenshots/',
  './screenshots/screenshot1.png',
  // './js/',
  './js/buttons.js',
  // './js/serviceWorker.js',
  './js/editor_change.js',
  './js/jquery.min.js',
  './js/materialize.min.js',
  './js/resizer.js',
  './js/toplevel-4.08.js',
  './js/codemirror/closebrackets.js',
  './js/codemirror/codemirror.min.js',
  './js/codemirror/dialog.js',
  './js/codemirror/jump-to-line.js',
  './js/codemirror/matchbrackets.min.js',
  './js/codemirror/mllike.min.js',
  './js/codemirror/search.js',
  './js/codemirror/searchcursor.js',
  './js/codemirror/show-hint.js',
  './js/codemirror/sublime.min.js',
  './js/old/autocomplete.js',
  './js/old/utility.js'
];

self.addEventListener('install', async event => {
  const cache = await caches.open('static-cache');
  cache.addAll(staticAssets);
});

self.addEventListener('fetch', event => {
  const req = event.request;
  const url = new URL(req.url);

  if (url.origin === location.url) {
    event.respondWith(cacheFirst(req));
  } else {
    event.respondWith(networkFirst(req));
  }
});

async function cacheFirst(req) {
  const cachedResponse = caches.match(req);
  return cachedResponse || fetch(req);
}

async function networkFirst(req) {
  const cache = await caches.open('dynamic-cache');

  try {
    const res = await fetch(req);
    cache.put(req, res.clone());
    return res;
  } catch (error) {
    return await cache.match(req);
  }
}

console.log("Finished serviceWorker.js");

This worked by add the file at the ROOT (and not js/) folder. I guess by changing paths to ../css/, ../js/ it should work, but I tried different solutions and couldn't get it to work, so I got lazy and just moved this one .js file to the ROOT.

Naereen commented 3 years ago

I used this example and it worked!

See this GIF, showing that I can toggle the "offline" mode from inside Chromium dev tools, reload the app with cltr+r and it still loads with no error! (not force reload, shift+ctr+r, which erases the cache). The same works if I unplug my Ethernet wire, or disable my wifi!

Peek 27-02-2021 16-07

Naereen commented 3 years ago

So I think this will be enough to make the app

That's all I dreamed of last weekend, hooray!

Naereen commented 3 years ago

It works on my mobile phone too! Offine and "native" installed! YAY!

Naereen commented 3 years ago

Apparently the theme is not perfectly loaded for the editor part (only) if choosing another theme than the default one. I don't think it's really important...

Naereen commented 3 years ago

The editing and usage of the app is quite different from @romainvernoux's https://play.google.com/store/apps/details?id=fr.vernoux.ocaml (10 year old but still great!), but it's a good complement to have.