From 7463e87a9c56b801268ff1f403230dc9ff1404a5 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Mon, 19 Apr 2021 15:22:41 -0400 Subject: [PATCH] Have the browser refresh on ghcid restart --- README.md | 12 ++++++++---- ema.cabal | 1 - src/Ema/App.hs | 11 ++++++++++- src/Ema/Example.hs | 8 ++++---- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a872f0d..b7c6365 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ema -ema is a **WIP** next-gen Haskell static site generator that is *change-aware*. In addition to static site generation, it provides a live server that hot-reload's on code *or* data change. +ema is a **WIP** next-gen Haskell static site generator that is *change-aware*. In addition to static site generation, it provides a live server that hot-reload's on code *or* data change[^1]. The ultimate goal of ema is to make it possible to easily implement your own [neuron](https://neuron.zettel.page/), or just about any app that creates a browser view of arbitrarily changing data (on disk, database, or whatever). ema is designed to facilitate creation of apps whose data is normally *edited* via traditional mechanisms (eg: text editor) but *rendered* as a delightful web page - so as to provide an economical read-only view, of your data, on desktop & mobile. @@ -14,6 +14,8 @@ main = do encodeUtf8 $ "Hello, " <> name ``` +[^1]: At the moment, only data change triggers a true hot reload; but code change triggers reload via a full page refresh in the browser, which creates a subtle flicker. Ideally this should be improved somehow, possibly by persisting the server and websocket across ghci(d) restarts (cf. [ghci-websockets](https://github.com/j-mueller/ghci-websockets)). + ## Hacking Open in VSCode, and run the build task. @@ -23,13 +25,15 @@ Open in VSCode, and run the build task. - [x] MVP - [ ] Implement hot reload, and ditch browser-sync - [x] server to client refresh - - [ ] client to server reconnect (on ghcid reload, or accidental client disconnect) - - [ ] or, investigate https://hackage.haskell.org/package/ghci-websockets + - [x] client to server reconnect (on ghcid reload, or accidental client disconnect) + - [x] or, investigate https://hackage.haskell.org/package/ghci-websockets - [ ] Example: filesystem watcher +- [ ] position re: hakyll -public, +pre-announce, - [ ] refactor and simplify - [ ] examples +- [ ] documentation ([howto](https://documentation.divio.com/)) doc notes, - use async:race to avoid ghcid ghosts diff --git a/ema.cabal b/ema.cabal index e0fdb4f..8c94db4 100644 --- a/ema.cabal +++ b/ema.cabal @@ -49,7 +49,6 @@ library , warp , websockets - -- record-hasfield is included due to https://github.com/commercialhaskell/stackage/issues/4449 mixins: base hiding (Prelude), relude (Relude as Prelude, Relude.Container.One), diff --git a/src/Ema/App.hs b/src/Ema/App.hs index b16d961..08754f2 100644 --- a/src/Ema/App.hs +++ b/src/Ema/App.hs @@ -122,6 +122,14 @@ runEma ema = do }); } + function refreshPage() { + // The setTimeout is necessary, otherwise reload will hang forever (at + // least on Brave browser) + setTimeout(function() { + window.location.reload(); + }, 100); + }; + window.onpageshow = () => { console.log("ema: Opening ws conn"); var ws = new WebSocket("ws://" + window.location.host); @@ -130,7 +138,8 @@ runEma ema = do ws.send(document.location.pathname); }; ws.onclose = () => { - console.log("ema: closed"); + console.log("ema: closed; reloading.."); + refreshPage(); }; ws.onmessage = evt => { // console.log(evt.data); diff --git a/src/Ema/Example.hs b/src/Ema/Example.hs index 0cc1dbe..9e8c6e1 100644 --- a/src/Ema/Example.hs +++ b/src/Ema/Example.hs @@ -62,15 +62,16 @@ timeC = do runSimpleSitePure :: IO () runSimpleSitePure = do (model, runTimeC) <- timeC - race_ runTimeC $ - runEma $ + race_ runTimeC (runEma $ ema model) + where + ema model = Ema model $ \now r -> Layout.tailwindSite (H.title "Simple Site") $ H.div ! A.class_ "container mx-auto" $ do H.header ! A.class_ "text-4xl font-bold border-b-1" $ "Simple Site!" case r of PR_Index -> do - H.p ! A.style "color: red;" $ "Checkout some profiles:" + H.p ! A.style "color: red; text-3xl" $ "Checkout some profiles:" forM_ ["Srid Ratna", "ema", "Great India"] $ \person -> H.li $ routeElem (PR_Person person) $ @@ -86,7 +87,6 @@ runSimpleSitePure = do color = colors !! mod epoch (length colors) cls = "text-" <> color <> "-500" H.span ! A.class_ cls $ H.toMarkup $ formatTime defaultTimeLocale "%Y/%m/%d %H:%M:%S" now - where routeElem r w = H.a ! A.class_ "text-xl text-purple-500 hover:underline" ! routeHref r $ w routeHref r =