Fork me on GitHub
#hyperfiddle
<
2023-05-18
>
teodorlu11:05:57

Hi! CodeMirror and ProseMirror have some built-in capabilities for collaborative editing. But as far as I'm aware, both are strictly client-side Javascript libraries. Electric doesn't have the "client side only" limitation. Has anyone tried using Electric to provide reactive network behavior collaborative editing with CodeMirror or ProseMirror? https://codemirror.net/ | https://prosemirror.net/

Dustin Getz19:05:17

I think a CRDT is the right approach for this, I don't see any obvious benefit in reimplementing the CRDT with Electric

👍 2
Dustin Getz19:05:01

i.e. https://marijnhaverbeke.nl/blog/collaborative-editing.html - the core patterns here do not come for free with Electric

👍 2
teodorlu21:05:29

Right, the merge logic is not trivial at all. It probably makes more sense to solve that in Electric userspace. Different Electric might have different persistence layers, and might need different kinds of editing interfaces.

jjttjj20:05:33

Hi, still very new to electric but really liking it. I'm wondering how to go about doing the following. I want to click a button on the client that initiates a "stream" of random numbers, with some time delay between them, and eventually terminating. below the button i want a dom element to show the random numbers, accumulating them as they arrive. I have it working with e/watch and e/def and an atom

#?(:clj (def !x (atom [])))
(e/def x (e/server (e/watch !x)))

...

(dom/div
            (dom/button
              (dom/on "click"
                (e/fn [e]
                  (e/server
                    (future
                      (dotimes [_  10]
                             (let [n (rand-int 100)]
                               (Thread/sleep 100)
                               (println (swap! !x conj n))))))))
              (dom/text "button"))
            (e/for [n x]
              (dom/text (str n " "))))
But in the "real" version of this i want to start many such short lived processes on the server that should stream their updates to the client. I'm wondering what's the Electric way to create an "anonymous" flow on the server (without e/def) and stream the results to the client. I think I've been slowly making progress towards understanding enough to do this, reading electric source code and refreshing my missionary knowledge, but if anyone has a quick example in the meantime that'd be great

3
Dustin Getz20:05:58

We're calling this "progress" (i.e. a button that has a progress indicator while it downloads something)

Dustin Getz20:05:17

The current ui4/button can kinda do this but there is an impedance mismatch, it wasn't really designed for that. We've learned a LOT since throwing that together and this is part of the current active workstream to rebuild the UI namespace

Dustin Getz20:05:46

Here is a hacked together example of a button with progress under the current ui4/button

Dustin Getz20:05:05

I make no claim that this is idiomatic, it surely will evolve, just giving you something that works today

Dustin Getz20:05:33

It is almost certainly "bad" - the natural way to model this is to have the button's reactive callback return a sequence of reactive values, but unfortunately the button has some weird semantics on that callback, we're taking a look at it like tomorrow

noonian20:05:08

I ran into a similar case when I want to run an electric function on a callback and the function involves network calls/delays that could cause it to outlive the callback fn's lifecycle. I've been using this pattern of having a atom-wrapped boolean to signal when to do something and changing that in a callback. It doesn't read well but it gets the job done

(e/defn Foo []
  (let [!do-thing? (atom nil)
        do-thing? (e/watch !do-thing?)]
    (when do-thing?
      (SomeElectricFn.))
    (dom/div
      (dom/button
          (dom/on "click"
            (e/fn [e]
              (reset! !do-thing? true)))
        (dom/text "do the thing")))))

Dustin Getz20:05:44

> outlive the [ui4/button] callback fn's lifecycle yeah this is what sucks

💯 2
2
Dustin Getz20:05:32

the ui4/button's "callback" will terminate and unmount after the first non-Pending value is seen, which Leo flagged as a terrible idea many months ago

jjttjj20:05:47

Very interesting, thanks to both of you!

Dustin Getz21:05:21

to be clear, dom/on is the actual thing that sucks

noonian21:05:54

Electric is awesome, and it's still early days! It's a gotcha right now but not too bad to work around and I'm sure the proper api's and idioms will emerge over time

🙂 2
2
jjttjj21:05:20

Yeah 2 days in I've been really blown away by how nice it feels to do client/server stuff. Excited to keep learning it and see it evolve

🙂 2