This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-02-15
Channels
- # announcements (1)
- # babashka (1)
- # beginners (43)
- # cider (2)
- # clj-kondo (29)
- # clojure (61)
- # clojure-austin (18)
- # clojure-dev (7)
- # clojure-europe (30)
- # clojure-nl (1)
- # clojure-norway (23)
- # clojure-uk (5)
- # clojuredesign-podcast (8)
- # cloverage (1)
- # conjure (1)
- # data-science (1)
- # datahike (36)
- # datavis (1)
- # datomic (23)
- # emacs (14)
- # hyperfiddle (28)
- # lsp (5)
- # missionary (1)
- # music (1)
- # off-topic (11)
- # re-frame (11)
- # reitit (5)
- # releases (1)
- # shadow-cljs (65)
- # spacemacs (13)
- # squint (33)
- # tools-deps (56)
(edit) TLDR: the issue was that save changes (state/get-doc)
which creates a new atom. wrapping with e/snapshot
fixed the issue. updated the gist
not sure if this is an electric question or a prosemirror question. here's my setup for an rich text editor that saves on change:
(e/defn Saver [!doc]
(e/client
(let [doc (e/watch !doc)]
(e/discard
(e/server
(e/discard
(state/save-doc! (e/client (serialize-node doc)))))))))
(e/defn Editor [& [width]]
(e/client
(let [schema (create-schema)
!doc (atom (deserialize-node schema (e/server (state/get-doc))))]
(Saver. !doc)
(div (div (props {:id "proposal-editor" :class "prose"}))
(div (props {:id "content"}))
(println "Rendering editor view")
(EditorView.
(util/get-element-by-id "proposal-editor")
#?(:cljs #js {:state (EditorState.create. #js {:doc @!doc :plugins plugins})}))
nil))))
I have a plugin that updates the !doc
atom which triggers Saver
to persist the doc to the server. it seems to work except that every change produces a new instance of the editor (see video). I can make the issue go away by commenting out this line:
(Saver. !doc)
what is the Saver
electric function doing that might be messing with prosemirror? "Rendering editor view"
only gets printed once, so I don't think re-rendering is causing the issue.
full code in case it's helpful: https://gist.github.com/yayitswei/eb1796428911db7865ff0c310ce80614My guess would be that (state/get-doc)
updates reactively? Try wrapping it with e/snapshot
.
It doesn’t trigger at all? That I wouldn’t know. It looks like it should trigger exactly once.
Yes, it’s very precise. Hence the need for the occasional snapshot
to escape from it in situations like these.
Unless the atom instance changes, it won’t. This was the case for you: get-doc
updates, which means a new atom is created, which triggers the deref, since the this is now a new atom. Now your atom is stable, so the deref won’t re-run.
thanks again for your help. so this is single-player which is sufficient for now. any high-level tips or resources for making it multiplayer? prosemirror seems to have an opinionated way to do it, but i haven't tried using it with electric yet
I don’t know how you can make it work for multiplayer without using a CRDT. You can make it “safe” for multiplayer by locking the text field if someone is editing it.
I.e., guarantee that only one person ever edits the text field at the time, semaphore-style.
makes sense. locking would work for now i think. i'd need a timeout to release the lock, right?
Or when the editor has focus. But yeah, you’d probably need a timeout anyway, in case someone clocks out for the day and leaves the cursor in the field.
i'm hoping someone publishes a electric+CRDT example I can study someday 😀 in the meantime this will def work for my purposes 🙏
Funny you say that. Several years ago I was working at Atlassian implementing collaborative in cljc for editing in for prosemirror specifically to support migration to confluences new editor that replaced xwiki. Unfortunately its closed source and somewhat non-trivial especially table.s However prosemirror was pretty easy to work with as the events are fairly semantic and I remember seeing a couple open source libraries collaborative editing libraries although in javascript. I’ve not looked into any of them too deeply but this one looks promising https://github.com/inkandswitch/peritext https://www.inkandswitch.com/peritext/
Thanks for the resources and validation of prosemirror. I actually switched over from lexical and the API feels much simpler.
You probably saw that I recently wrote a collaborative text editor in Electric + Peritext recently. I’m pretty sure it’s two firsts: 1) Collaborative RT in pure Electric, 2) Peritext with blocks, but so it’s also at an early stage at the moment. For getting something out quickly, Yjs and Prosemirror ought to be one of the safest choices, despite the edge cases and problems it has.