Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: feat: comments #1376

Draft
wants to merge 11 commits into
base: feature/liveblocks-v2
Choose a base branch
from
Draft

wip: feat: comments #1376

wants to merge 11 commits into from

Conversation

YousefED
Copy link
Collaborator

@YousefED YousefED commented Jan 16, 2025

First POC of native comments in BlockNote.

  • We implement several Comment / Thread related components that can be customized similar to other BlockNote components. Standard implementation will support Mantine / ShadCN / Ariakit variants.
  • The storage interface (ThreadStore) will be pluggable. This means you can "bring your own provider" if you like.

Providers

YjsThreadStore

We store thread / comment information directly in yjs so it can be easily integrate with existing sync / storage mechanisms. The downside of this is that comments require a more advanced permission model than text documents; so we need to provide a workaround for this and clearly explain the pros / cons. Of course, users can always implement their own (e.g.: REST-based) ThreadStore with more advanced permissions built-in.

TODO:

  • ! add unit tests
  • add server side validation (make sure users can't edit other users comments, etc)
  • implement / document how read-only users can add comments

LiveBlocks

The UI Components are roughly based on the LiveBlocks open source components. LiveBlocks users will have two different ways to use LiveBlocks:

  • Use LiveBlocks UI components: this can be done with Feature/liveblocks v2 #1259. This would support all liveblocks functionality (read status, attachments, etc), but the style is a bit different from the other BlockNote components.
  • Use BlockNote UI components (matching your existing mantine / shadcn / ... version of BlockNote). These are "first-class" supported in BlockNote but miss some features compared to liveblocks (i.e.: read status, attachments, etc)

TODO:

  • Implement LiveBlocksThreadStore (and possibly move to separate package)

TipTap

We can probably integrate directly with the TiptapCollabProvider

TODO:

  • Implement TipTapThreadStore

UX TODOs

  • ! implement stream threads (right sidebar)
  • ! implement anchored threads
  • ! implement resolve / unresolve
  • ! implement reactions
  • bug: delete thread error
  • clean up mantine design
  • add icons
  • implement shadcn / ariakit
  • comment editor: auto focus
  • comment editor: disable things like text alignment, etc
  • how to show soft-deletes

Misc

TODO:

  • ! implement user management
  • ! make sure UX reflects user auth
  • i18n
  • docs

Copy link

vercel bot commented Jan 16, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
blocknote ❌ Failed (Inspect) Jan 24, 2025 11:26am
blocknote-website ❌ Failed (Inspect) Jan 24, 2025 11:26am

@YousefED
Copy link
Collaborator Author

@dmonad I'm working on a POC for comments here. You can see:

Two questions about this:

  • You mentioned the only way to validate an update would be to apply it to a clone and compare changes (+ see if there's no prelim? updates added)
  • IF the user wants to store the Threads Y.Map as part of the regular Y.Doc that contains the entire document (instead of in a separate Y.Doc), is there an easy way to see if an incoming update affects that specific Y.Map? This way we could only run the validation logic (including cloning etc.) when there's been an update to the Threads datastructure.

@dmonad
Copy link

dmonad commented Jan 17, 2025

* You mentioned the only way to validate an update would be to apply it to a clone and compare changes (+ see if there's no prelim? updates added)

Even that is edgy… There are several parts of Yjs that could be exploited to sneak-in changes, even if you check pendingStructs. It might be possible to add deleted structs that will show up when a user undos changes. I generally advise against validating updates like this. It's a security hazard; unmaintainable unless you employ somebody that understands Yjs internals. I don't want anyone to copy this approach.

* IF the user wants to store the Threads Y.Map as part of the regular Y.Doc that contains the entire document (instead of in a separate Y.Doc), is there an easy way to see if an incoming update affects that specific Y.Map? This way we could only run the validation logic (including cloning etc.) when there's been an update to the Threads datastructure.

That is actually a more realistic approach. You could check each struct / delete whether it applies changes to only the children of a certain other type. This approach is also more memory efficient (no need to fork a document). However, you need to understand the Yjs internals to pull this off.

Ideally, comments are stored in a separate Yjs document with different permissions. If that is not possible, I recommend that read-only users are only able to add comments through an HTTP request (no manipulations on the Yjs document).

@YousefED
Copy link
Collaborator Author

I recommend that read-only users are only able to add comments through an HTTP request (no manipulations on the Yjs document).

I agree, read-only users should probably always use an HTTP request. However, for other users (with write access), I think we should also be able to validate changes. For example, a user should only be able to edit comments they created themselves. So I'm interested if / how we can validate this. Can also discuss this over a call, might be easier :)

Comment on lines +36 to +37

renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, any> }) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on if you want to support copy-paste of comments, maybe parseHTML?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

I think copy paste will need to be tested extensively :) for example, you could paste a comment that's not in the store, etc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants