fsprojects / FsReveal

FsReveal parses markdown and F# script file and generates reveal.js slides.
http://fsprojects.github.io/FsReveal
258 stars 100 forks source link

Auto-Update slides in Edit mode #35

Closed forki closed 9 years ago

forki commented 9 years ago

In edit mode we start suave to host our slides. Whenever we save a file in the slides folder FAKE / FsReveals rebuilds our slide deck. With hitting F5 we can refresh the browser. That's already super nice.

Now how can we use suave / reveal.js to update the slides without hitting refresh? This is somehow already working with vanilla reveal.js and (I think ?!) node.js.

So how would this work for us?

//cc @haf @troykershaw @kimsk

haf commented 9 years ago

You could always do a http://html5doctor.com/server-sent-events/ plus an event handler in js:

addEventListener('files-updated', function() { window.location.refresh() });

And from suave: https://github.com/SuaveIO/suave/blob/master/src/Suave/Http.fsi#L1459

And listen to the events server-side: https://github.com/zeromq/fszmq plus https://github.com/thomasfl/filewatcher and http://zeromq.org/bindings:ruby

or through a FileSystemWatcher

forki commented 9 years ago

the filesystemwatcher is already there https://github.com/fsprojects/FsReveal/blob/master/build.fsx#L61

I assume the analog to the 'files-updated' is already anywhere in the reveal.js source (where?)

So if I understand correctly we only need to keep a reference to the server (from https://github.com/fsprojects/FsReveal/blob/master/build.fsx#L78) and raise the right event in suave from https://github.com/fsprojects/FsReveal/blob/master/build.fsx#L63.

/cc @agross

haf commented 9 years ago

I haven't been able to find a reference to reveal.js auto-updating on files changed, so no, files-updated was my own event.

forki commented 9 years ago

I'd really love to see this working.

troykershaw commented 9 years ago

The Node people do this really well using LiveReload. If we use the LiveReload client, it simplifies the work we need to do to actually reload what has changed.

The protocol doc is here. I have little experience with websockets, but once the connection has been made, updates are simple.

Websockets are only supported on Win 8+, but OSX and Linux should be fine.

Does Suave have any websocket support?

TonyAbell commented 9 years ago

I think SignalR as graceful fall back on Sockets to long polling. How would a SingleR solution differ from using LiveReload and Sockets?

troykershaw commented 9 years ago

Signalr works, but we have to write the client refresh code. If we're happy with a full page reload when something changes, then that's easy.

forki commented 9 years ago

I thought the suave solution above should work. I just don't get it to work.

haf commented 9 years ago

@forki Can you run the SSE demo from the samples folder?

forki commented 9 years ago

it compiles and I get it starting but I have no idea what to do. is there a description?

haf commented 9 years ago

If you navigate to /events in your browser, what do you see?

forki commented 9 years ago

somthing pushing data. that's nice.

I meant i don't know how to apply it to this issue here ;-)

haf commented 9 years ago

Sorry, I haven't written any docs, only the sample. Here's how you construct the thing that sends events: https://github.com/SuaveIO/suave/blob/master/examples/Example/CounterDemo.fs#L33

You can see there's a type?

Using this API: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener you can listen to a message of that type.

Using the methods from here: https://github.com/SuaveIO/suave/blob/master/src/Suave/Http.fsi#L1514-L1559 you can then let the server talk to the client.

So what I was thinking was that you spawn a controller actor, which is your publisher, basically, and you let it listen to the file changed events http://bramjochems.com/blog/2013/12/monitoring-files-folder/ and keep a list inside your actor of all the connected clients; whenever you get a file system event, you publish a message of that type to all clients.

You can key the connection from the request is inside the HttpRequest from Suave.

Since the write function in the example returns an async that can write to the socket, you can let the async wait be the inbox.Receive() call inside an actor.

Or you could also keep the write-method as-in from the example and poll the 'controller actor' after every sleep -- that way you don't have to keep a list of observers in the controller actor.

Some ideas.

haf commented 9 years ago

Here's a simple example, client-side http://html5doctor.com/server-sent-events/ which links to a polyfill https://github.com/Yaffle/EventSource that makes it even easier to consume the messages.

ademar commented 9 years ago

I've submitted PRs #72 and #73 that implement this feature. Let me know what you think

forki commented 9 years ago

This is released in 0.9 and works like a charme.

dance

Thanks so much!