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

Integrate Nostr-Editor #445

Merged
merged 26 commits into from
Nov 11, 2024
Merged

Integrate Nostr-Editor #445

merged 26 commits into from
Nov 11, 2024

Conversation

ticruz38
Copy link
Collaborator

Have the note creation to use nostr-editor, a set of nostr extension on top of the tiptap editor.

Bugs and known issue remaining:

  • The images are loaded and displayed inside the editor, as a result, the Compose component replace the ImageInput component. The goal is still to keep the underline carrousel, I miss a proper callback to get the uploaded image urls (onComplete not triggering)
  • When hitting Enter to select a mention, the editor does break the line, preventDefault does not help
  • tags or hashtags are immediately wrapped in tags, it is underlined as you type before "space" key is hit
  • nostr-editor comes with a nostr event parsing. Images url are immediately set in the content and in the tags. We could potentially use this functionality entirely and remove internal logic from Coracle, but it depends how confident you are with this dependency.
  • Image urls are not in the tags when sending the event, this will be resolved

Copy link
Collaborator

@staab staab left a comment

Choose a reason for hiding this comment

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

The images are loaded and displayed inside the editor, as a result, the Compose component replace the ImageInput component. The goal is still to keep the underline carrousel, I miss a proper callback to get the uploaded image urls (onComplete not triggering)

I'm not sure why onComplete wouldn't trigger, you may have to debug that in nostr-editor. Let me know if you'd like me to take a look. I do think we can potentially get rid of the image carousel at the bottom and put everything inline. I'd like the editor to show pretty much the same thing as would ultimately be rendered.

When hitting Enter to select a mention, the editor does break the line, preventDefault does not help

This is probably due to the use of onKeyDown in a way that's not integrated with tiptap. Take a look at how flotilla does mention suggestions via a tiptap plugin, you'll probably have to do something similar.

tags or hashtags are immediately wrapped in tags, it is underlined as you type before "space" key is hit

I haven't been able to figure out topics. I was able to avoid solving this in flotilla, but it does need to be done. Maybe ignore nostr-editors TagExtension and add a new Node type.

nostr-editor comes with a nostr event parsing. Images url are immediately set in the content and in the tags. We could potentially use this functionality entirely and remove internal logic from Coracle, but it depends how confident you are with this dependency.

Yep, rip out as much of coracle's code for this and start from scratch. It's outlived its usefulness, although we'll have to make sure the (many) bugfixes make it into the new version. I don't mind the dependency on tiptap, it's what's necessary to bring the UX to the next level.

Cesar and I had also talked about using tiptap to render notes. He was apparently able to get that working, but I've had some trouble. Anyway, I'm not sure it would be performant in practice so we probably shouldn't do it right away. Something to keep in mind though.

As I said before, feel free to nuke NoteImages, Content, NoteReply, NoteCreate, and NoteCreateInline (etc) and come up with new abstractions. I think it's going to be better to tackle the problem completely from scratch.

},

extensions: [
StarterKit,
Copy link
Collaborator

Choose a reason for hiding this comment

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

StarterKit has lots of stuff we don't want to support. See flotilla's set up for something much closer to reality.

Comment on lines 154 to 163
if (["Enter"].includes(e.code) && suggestions.get()) {
e.preventDefault()
const pubkey = suggestions.get()
if (pubkey) {
const content = $editor.getHTML()
// only replace the last occurence
const replacedContent = content.replace(/(.*)@\w+/, "$1")
$editor.commands.setContent(replacedContent, true)
$editor.commands.insertNProfile({nprofile: pubkeyEncoder.encode(pubkey)})
suggestions.setData([])
Copy link
Collaborator

Choose a reason for hiding this comment

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

This approach will probably not work, tiptap is too magical, you have to do things their way.

Comment on lines 20 to 30
{#if node}
<NodeViewWrapper data-type="tag" as="span">
<Anchor modal underline on:click={onClick}>
#{value}
</Anchor>
</NodeViewWrapper>
{:else}
<Anchor modal underline on:click={onClick}>
#{value}
</Anchor>
{/if}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't overload NoteContentTopic and PersonLink, just create new components specifically for the editor. Again, see flotilla for how I've structured it there.

src/app/shared/PersonLink.svelte Outdated Show resolved Hide resolved
@ticruz38
Copy link
Collaborator Author

ticruz38 commented Oct 21, 2024

Took a lot from Flotilla in this commit.

Created a new folder "editor" under the app directory, like Flotilla, but with different Edit component. Let me know if you would rather have it somewhere else, or just add the Edit[whatever].svelte files in the shared directory.

‼️NostrCreateInline and NostrReply still need to be adapted, the code break for any other url than notes/create. I still need to figure out the correct way to submit. For now it's weird, I upload the files and onSubmit() trigger in the onComplete callback of the file upload (kind of unrelated).

  • Any view that uses an editor will instantiate Editor with the correct parameters (essentially the session pubkey and eventual mentions)
  • Compose.svelte is still there atm, mostly for CSS purpose on the content of the editor (image blur-in blur-out while loaded)
  • Have to modify the uploadFile extension to store the files url being uploaded (to put them in the event tags)
  • Consider adding a small extension that will count words and characters being typed.
  • If we want to be close to a "live" note, I will support Spotify/Youtube/Github link with thumbnail eventually, this will not be a nostr extension but a slightly modified Media component

@staab
Copy link
Collaborator

staab commented Oct 21, 2024

Great, looking good.

For now it's weird, I upload the files and onSubmit() trigger in the onComplete callback of the file upload (kind of unrelated).

Yeah, I think the reason it's this way is so that submit is deferred until files get uploaded. As a result, we currently have to defer uploading files until the user submits the form (which is a feature in a way, because it avoids them uploading files they don't ultimately want to use). I do think that uploading files concurrently for a quick submit is a better way to do this though, so hopefully we can find a way around this pattern.

@ticruz38
Copy link
Collaborator Author

ticruz38 commented Oct 22, 2024

  • Adapted NoteCreate, NoteReply, NoteCreateInline to use the new Compose element.
  • Uploading all files before submitting at the moment. editor.commands.uploadFile re-upload all files in the editor atm. ImmediateUpload could be used too, but it does not trigger onComplete callback.
  • Added iframes preview for YouTube and Twitter, the twitter preview is being blocked by plausible.io, you might be able to configure it there. If you validate, I'll add those preview to Media.svelte, so we'll get a "native" preview for Tidal, Spotify, Youtube and Twitter.
  • WordCount extension to count characters and words.

Issues:

  • When opening/closing a reply, ie creating a draft, the editor will just render everything as text, haven't found how to force parse the content. Do you know how to force it?
  • Removed the imeta tags before submitting, have the image or video tags instead. What was the imeta tag used for and what are the parameters to it?

@staab
Copy link
Collaborator

staab commented Oct 22, 2024

Added iframes preview for YouTube and Twitter, the twitter preview is being blocked by plausible.io, you might be able to configure it there. If you validate, I'll add those preview to Media.svelte, so we'll get a "native" preview for Tidal, Spotify, Youtube and Twitter.

That might be the content security policy, see frame-src in index.html.

When opening/closing a reply, ie creating a draft, the editor will just render everything as text, haven't found how to force parse the content. Do you know how to force it?

I've struggled with this as well. @cesardeazevedo, do you happen to know the solution to this?

What was the imeta tag used for and what are the parameters to it?

See here: https://github.com/nostr-protocol/nips/blob/07de7ea7e5d2934afac1eb86db0cd0a0200039a0/92.md?plain=1#L7

@cesardeazevedo
Copy link

I haven't been able to figure out topics. I was able to avoid solving this in flotilla, but it does need to be done. Maybe ignore nostr-editors TagExtension and add a new Node type.

Not so sure about the actual issue here but the tag extension was very buggy before version 0.0.3.

Cesar and I had also talked about using tiptap to render notes. He was apparently able to get that working, but I've had some trouble.

I feel like the editor still struggles with things like hardbreak lines, I have found difficult to understand the correct approach.

I'm not sure it would be performant in practice

I would imagine the nostr-editor to be considerably slower than welshman/content (although would love to see some benchmarks), so use it with caution.

Have to modify the uploadFile extension to store the files url being uploaded (to put them in the event tags)

Nostr-editor indeed needs to provide an easy way to access the uploaded files, gonna work on that.

I miss a proper callback to get the uploaded image urls

This part indeed needs some improvement.

When opening/closing a reply, ie creating a draft, the editor will just render everything as text, haven't found how to force parse the content. Do you know how to force it?

Not so sure if I understood correctly, but you can't directly set a event content when initializing the editor

  const editor = useEditor({
    content: 'Hello nostr:nprofile1qy88wumn8ghj7mn0wvhxcmmv9uq32amnwvaz7tmjv4kxz7fwv3sk6atn9e5k7tcprfmhxue69uhhyetvv9ujuem9w3skccne9e3k7mf0wccsqgxxvqas78x0a339m8qgkaf7fam5atmarne8dy3rzfd4l4x6w2qpncmfs8zh',
  })

This will render as text as tiptap won't apply any pasteRules here, I tried to find a way many times but couldn't, you have to call setEventContent manually.

  onCreate({ editor }) {
    editor.commands.setEventContent({
      id: '...',
      content: 'Hello nostr:nprofile1qy88wumn8ghj7mn0wvhxcmmv9uq32amnwvaz7tmjv4kxz7fwv3sk6atn9e5k7tcprfmhxue69uhhyetvv9ujuem9w3skccne9e3k7mf0wccsqgxxvqas78x0a339m8qgkaf7fam5atmarne8dy3rzfd4l4x6w2qpncmfs8zh',
    })
  }

Interestingly you can set a HTML representation of the editor state, which is the content you get when copying the content directly from the editor (check the clipboard inspector)

  const editor = useEditor({
    content: `<meta charset='utf-8'><p data-pm-slice="1 1 []"><span nprofile="nostr:nprofile1qy88wumn8ghj7mn0wvhxcmmv9uq32amnwvaz7tmjv4kxz7fwv3sk6atn9e5k7tcprfmhxue69uhhyetvv9ujuem9w3skccne9e3k7mf0wccsqgxxvqas78x0a339m8qgkaf7fam5atmarne8dy3rzfd4l4x6w2qpncmfs8zh" pubkey="c6603b0f1ccfec625d9c08b753e4f774eaf7d1cf2769223125b5fd4da728019e" relays="wss://nos.lol/,wss://relay.damus.io/,wss://relay.getalby.com/v1" data-type="nprofile">@</span> </p>`
  })

@ticruz38
Copy link
Collaborator Author

I've struggled with this as well. @cesardeazevedo, do you happen to know the solution to this?

It seems to be solved now by instantiating the editor with the content as HTML.

That might be the content security policy, see frame-src in index.html.

Have finally managed to have tweet preview working while keeping the content security policy, that's 2 twitter script tag, once being labelled with a git tag, but it works

  • Had to replicate the FileUpload extension, impossible to get the desired behaviour just by configuring it properly or via the callbacks provided. Might be worth a PR on Nostr-Editor. Just added another command.getMetaTags() that will give me the nip-94 image tags present in the note, as provided by the endpoint response. There was also an issue where the updated attributes (src, uploading etc) were placed on the wrong node, this might be related to 2 extensions manipulating things at the same time.
  • I still want to test it with a blossom endpoint, do you know any?
  • The new editor has been replicated everywhere compose was used before, should we use it in channel as well?
  • Twitter and Youtube preview are now in the Media component, it shows up in the note feed basically
  • Images load immediately now, there is a blur-in blur-out animation while it loads. you might upload some image accidentally but submit is much faster.

Happy to get your feedback on the editor, until then I'll just keep merging dev and move on to other issues

@ticruz38
Copy link
Collaborator Author

thanks @cesardeazevedo for your answer !

I managed to have it all working well with file upload, I will keep testing and issue a PR on nostr-editor if needed.

I did have that strange issue where file attributes where not reported correctly when using immediate uploads, the examples on nostr-editor repo works as expected, but with the Coracle config, it consistently updated the wrong node, the one right before the actual Image node (pos - 1).

@staab
Copy link
Collaborator

staab commented Oct 23, 2024

Might be worth a PR on Nostr-Editor.

Please do, it's worth having upstream.

I still want to test it with a blossom endpoint, do you know any?

Try https://blossom.hzrd149.com/

should we use it in channel as well?

Yeah, let's do it.

--

I'll test the PR, can you rebase from dev to fix the conflicts?

Copy link
Collaborator

@staab staab left a comment

Choose a reason for hiding this comment

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

Sorry to make you undo a fair amount of work, but I don't think it's necessary to render everything as blocks. WYSIWYG is nice in theory, but since we're using a different renderer anyway, we're going to have differences between compose/render. Take a look at how flotilla handles things like links and entities. Pretty much everything should be inline in the editor, and not super rich.

Also, compare the behavior of enter between production and this PR, it's important that enter/shift+enter/meta+enter stay the same. I was testing it out and published a dumb note accidentally because of the change. Try to get the design looking the same too, in terms of colors, textarea height, etc. A lot of finessing has gone into what we currently have.

index.html Outdated Show resolved Hide resolved
@ticruz38
Copy link
Collaborator Author

ticruz38 commented Oct 24, 2024

  • Removed all images and link preview from the editor, it now display files and links like Flotilla or on the previous Oracle editor.

Also, compare the behavior of enter between production and this PR, it's important that enter/shift+enter/meta+enter stay the same

My understanding is that mod-enter is to submit, enter and shift-enter is for hardbreak. It is now the default configuration for the editor.

Try to get the design looking the same too, in terms of colors, textarea height, etc. A lot of finessing has gone into what we currently have.

Have been through all the Compose component, styles should be aligned. There is one annoying style bug, the animation when you open a reply, it goes in 2 phase if you pay attention to the cursor, have spent a fair amount of time getting this right, no luck so far. I'll sleep on it

@staab
Copy link
Collaborator

staab commented Oct 24, 2024

My understanding is that mod-enter is to submit, enter and shift-enter is for hardbreak. It is now the default configuration for the editor.

It is in a chat context, but it's actually the reverse when composing a note. Sort of weird, but seems the most intuitive.

@ticruz38
Copy link
Collaborator Author

ticruz38 commented Oct 25, 2024

Try https://blossom.hzrd149.com/

Been hitting cors for any endpoint I tried, also https://void.cat.

Comment on lines 225 to 248
this.editor.storage.fileUpload.tags.push([
"imeta",
`url ${res.size}`,
`size ${res.size}`,
`m ${res.type}`,
`x ${res.sha256}`,
])
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Blossom do not seems to enforce a standard for meta tags in the response, I'm taking all useful fields in the default response to build a meta tag.

@staab
Copy link
Collaborator

staab commented Oct 28, 2024

Something is very wrong with some of these PRs, try checking dev out and cherry-picking your changes, then doing git rebase -i dev. There are a whole bunch of changes from dev that are being merged back in here. When reconciling branches, try to always rebase rather than merge.

Also, maybe try https://blossom.f7z.io/ for blossom?

@ticruz38
Copy link
Collaborator Author

There are a whole bunch of changes from dev that are being merged back in here. When reconciling branches, try to always rebase rather than merge.

I rebased from origin/dev indeed, I had to go through twenty-ish commits cherrypicking the right changes, I might be doing something wrong, I'm not very used to rebase
Do you mean this PR is reversing some changes from dev?

@staab
Copy link
Collaborator

staab commented Oct 28, 2024

It's the reverse, the diff is including changes that already exist on dev. This is likely due to me force-pushing to dev at some point in the past after a merge (which is why rebase works better). Try rebasing with -i and change pick to squash for all listed commits. That will give you a single commit to work with. Or check out a fresh copy of dev, then git reset feat/nostr-editor to pull your changes over without any history.

@staab
Copy link
Collaborator

staab commented Oct 28, 2024

I'm happy to hop on a call and work on it with you if that would be helpful

src/app.css Show resolved Hide resolved
src/app.css Show resolved Hide resolved
Comment on lines 265 to 267
} catch (error) {
console.error(error)
this.editor.storage.fileUpload.loading.set(false)
Copy link
Collaborator

Choose a reason for hiding this comment

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

No need for this bit, finally will still run if an error happens


if (!content) return showWarning("Please provide a description.")

if (!skipNsecWarning && content.match(/\bnsec1.+/)) return nsecWarning.set(true)

const tags = [...tagsFromContent(content), ...getClientTags()]
const tags = [...tagsFromContent(content), ...getClientTags(), ...editor.commands.getMetaTags()]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems like tagsFromContent could be replaced by nostr-editor's new tags functionality, or at least getEditorTags

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Cesar recently started working on it, it probably isn't ready yet.
getEditorTags will gives you all #whatever in the editor. It refers to hashtags not nostr event tags

<i slot="button" class="fa fa-paperclip cursor-pointer" />
</ImageInput>
<button
class="hover:bg-white-l staatliches flex h-7 w-7 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded bg-white px-6 text-xl text-black transition-all"
Copy link
Collaborator

Choose a reason for hiding this comment

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

This button should look like the others. Also, be careful about using black and white, which won't play well with light theme.

@staab
Copy link
Collaborator

staab commented Oct 31, 2024

Some display bugs and behavior issues:

  • Ctrl+enter doesn't submit the form on reply, but enter does. It should be the reverse
  • Nothing should render as a block, currently invoices, quotes, links do
  • link-content doesn't look as good as it does in flotilla. It should have some kind of background to it.
  • There are some weird artifacts with the mention suggestion dialog. Also, the size changes and the arrow moves, they should stay still.
Screenshot 2024-10-31 at 8 47 22 AM Screenshot 2024-10-31 at 9 08 15 AM

Also, the PR needs a rebase. I ran one locally and it worked fine, so I think the reset did the trick.

@ticruz38
Copy link
Collaborator Author

ticruz38 commented Nov 1, 2024

  • reply now submit on mod+enter and not enter
  • Editor link, event, address and invoices render like in flotilla except the background is a different colour
  • The suggestions display used to be like flotilla (animation and so on), now it looks closer to Coracle, a lighter background for selected item, no animation.

@ticruz38
Copy link
Collaborator Author

ticruz38 commented Nov 4, 2024

Also, maybe try https://blossom.f7z.io/ for blossom?

CORS blocked too, only tried from localhost, it might be it

@staab staab marked this pull request as ready for review November 7, 2024 21:31
Copy link
Collaborator

@staab staab left a comment

Choose a reason for hiding this comment

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

Getting there!

Screenshot 2024-11-07 at 1 41 29 PM
Screen.Recording.2024-11-07.at.2.00.26.PM.mov

I also ran into this error when pasting a nevent:

proxy.js:385 Uncaught TypeError: Cannot read properties of undefined (reading 'length')
    at Array.displayEvent (EditEvent.svelte:16:20)
    at Array.create_default_slot (EditEvent.svelte:36:18)
    at create_slot (utils.js:165:22)
    at create_dynamic_element (EditorContent.svelte:34:24)
    at create_fragment2 (NodeViewWrapper.svelte:13:11)
    at init (Component.js:148:34)
    at new NodeViewWrapper (NodeViewWrapper.svelte:14:21)
    at create_fragment (EditEvent.svelte:35:65)
    at init (Component.js:148:34)
    at new EditEvent (EditEvent.svelte:27:14)

Pasting npubs is also buggy:

Screen.Recording.2024-11-07.at.2.03.57.PM.mov

Background for link-content looks bad in onboarding (as well as in replies and chat):

Screenshot 2024-11-07 at 2 09 50 PM

src/app/editor/FileUpload.ts Outdated Show resolved Hide resolved
src/app/editor/FileUpload.ts Outdated Show resolved Hide resolved
src/app/views/UserSettings.svelte Outdated Show resolved Hide resolved
src/app/editor/FileUpload.ts Outdated Show resolved Hide resolved
@ticruz38
Copy link
Collaborator Author

ticruz38 commented Nov 8, 2024

  • Newline rendering issue was solved with your suggestion
  • Have modified tag so that we can immediately mention people, The behaviour has slightly change, tag is now display once we hit the space key
  • I could not reproduce the issue, however it will no longer break if the content is undefined or can't be resolved.
  • [] I tried with different npub with different editor content, I could not reproduce the bug. Can you send me the content or more step on how to reproduce the bug, does it happen every time?
  • Background link, mention, tags etc are unchanged, but the text content will now be the "reverse" of the background, so the contrast between text and background is always high.

@staab staab merged commit a3c20ce into coracle-social:dev Nov 11, 2024
2 checks passed
Copy link
Collaborator

@staab staab left a comment

Choose a reason for hiding this comment

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

Merged 🎉 although I have a couple small changes you can follow up on

src/app/views/UserSettings.svelte Show resolved Hide resolved
src/app/editor/index.ts Show resolved Hide resolved
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.

3 participants