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

Add emoji autocompletion (#987) #1961

Merged
merged 5 commits into from
Mar 1, 2022
Merged

Conversation

mejo-
Copy link
Member

@mejo- mejo- commented Nov 23, 2021

Adds emoji autocompletion by typing :<search string>.

It utilizes the emoji functions from nextcloud-vue[1] and the TipTap
suggestions extension.

[1] nextcloud-libraries/nextcloud-vue#1474

Signed-off-by: Jonas Meurer jonas@freesources.org

Screencasts

recording

Summary

@mejo-
Copy link
Member Author

mejo- commented Nov 23, 2021

As discussed, I first looked into opportunities to outsource the emoji autocompletion into nextcloud-vue components. But unfortunately that's not really an option - at least I didn't see a good one.

The nextcloud-vue implementation would be specific to the RichContenteditable component and our implementation utilizes the TipTap Suggestions extension.

I'd be happy to learn about others' ideas on how to merge (parts of) the two approaches though 😊

@mejo- mejo- force-pushed the enh/emoji_autocompletion branch 3 times, most recently from c1fbadb to e3004ee Compare November 23, 2021 16:12
@mejo-
Copy link
Member Author

mejo- commented Nov 23, 2021

@nimishavijay and @jancborchardt feel free to drop some early feedback as well 😊

Copy link
Member

@julien-nc julien-nc left a comment

Choose a reason for hiding this comment

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

🚀 Wow it is very nice already!

The nextcloud-vue implementation would be specific to the RichContenteditable component and our implementation utilizes the TipTap Suggestions extension.

I guess it would require to implement something generic enough so it could be used in RichContenteditable and as a replacement of your EmojiSuggestions component.
I think it would be nicer to factorize the work on text suggestion.
I'll have a look at our Vue lib soonish.

When there is no suggestion, the TipTap emoji plugin sometimes provides an emojiRect with x==0 and y==0 which causes the suggestion box to jump to the top left corner. I didn't dig too deep but I feel this could be avoided with a few checks.

src/components/EmojiSuggestions.vue Outdated Show resolved Hide resolved
src/components/EmojiSuggestions.vue Outdated Show resolved Hide resolved
src/components/EmojiSuggestions.vue Outdated Show resolved Hide resolved
@nimishavijay
Copy link
Member

Looking super nice! Pretty much done looks-wise :D
Some questions I have:

  • does it auto complete on pressing tab or enter or both? Ideally it should be both
  • is the list of suggested emojis limited to a certain number? I'd say something around 5-6 would work
  • do you think we need to impose a max width on mobile and ellipsise so it doesn't extend beyond the screen?

@juliusknorr juliusknorr added 2. developing enhancement New feature or request feature: formatting Features related to text formatting and node types labels Nov 24, 2021
@juliusknorr juliusknorr added this to the Nextcloud 24 milestone Nov 24, 2021
@julien-nc
Copy link
Member

@nimishavijay

  • does it auto complete on pressing tab or enter or both? Ideally it should be both

The suggestion dropdown appears right after typing ":". You can then change the highlighted one with the arrows and select one with enter or by clicking it. Pressing the tab has no effect on the dropdown, it changes the focus to other stuff in the page.

  • is the list of suggested emojis limited to a certain number? I'd say something around 5-6 would work

Right now it's 5.

  • do you think we need to impose a max width on mobile and ellipsise so it doesn't extend beyond the screen?

Sounds good, yes.

@mejo- mejo- force-pushed the enh/emoji_autocompletion branch 2 times, most recently from dc4ea5d to b5feddf Compare November 24, 2021 11:22
@mejo-
Copy link
Member Author

mejo- commented Nov 24, 2021

When there is no suggestion, the TipTap emoji plugin sometimes provides an emojiRect with x==0 and y==0 which causes the suggestion box to jump to the top left corner. I didn't dig too deep but I feel this could be avoided with a few checks.

I digged a bit deeper here. The problem is that getBoundingClientRect() on the emojiSuggestion element returns positions (0, 0) for a short time in some cases. The only solution I could find so far is to cache the coordinates and to not update them in case of (0, 0): b5feddf

This works well in my tests, but not sure if it's the smartest solution. Let me know what you think 😬

@mejo-
Copy link
Member Author

mejo- commented Nov 24, 2021

* does it auto complete on pressing tab or enter or both? Ideally it should be both

Good point, I'll make it work on <Tab> as well.

* is the list of suggested emojis limited to a certain number? I'd say something around 5-6 would work

As @eneiluj said, it's limited to five for now (Github also shows five).

* do you think we need to impose a max width on mobile and ellipsise so it doesn't extend beyond the screen?

Good idea. What would be a good max-width on mobile?

@juliusknorr
Copy link
Member

When there is no suggestion, the TipTap emoji plugin sometimes provides an emojiRect with x==0 and y==0 which causes the suggestion box to jump to the top left corner. I didn't dig too deep but I feel this could be avoided with a few checks.

I digged a bit deeper here. The problem is that getBoundingClientRect() on the emojiSuggestion element returns positions (0, 0) for a short time in some cases. The only solution I could find so far is to cache the coordinates and to not update them in case of (0, 0): b5feddf

This works well in my tests, but not sure if it's the smartest solution. Let me know what you think grimacing

Seems good and a similar approach is used in https://github.com/ueberdosis/tiptap/blob/v1/examples/Components/Routes/Suggestions/index.vue#L230

@mejo-
Copy link
Member Author

mejo- commented Nov 24, 2021

* do you think we need to impose a max width on mobile and ellipsise so it doesn't extend beyond the screen?

I went with max-width: 90wv on mobile as that seemed like the most sensible value to me.

Also did some further CSS/positioning improvements, see 95e2583 for details. I updated the screencast above accordingly.

@mejo-
Copy link
Member Author

mejo- commented Nov 25, 2021

Supress further marks in Emoji nodes

So I looked into the problem of marks being applied within emoji search and came up with #1964, which is the proper fix here in my eyes. This also fixes the problem for inserting e.g. URLs with two underscores etc. Therefore I removed the quoted todo as it's out of scope for this PR.

@mejo- mejo- requested a review from julien-nc November 25, 2021 18:21
@mejo- mejo- changed the title WIP: Add emoji autocompletion (#987) Add emoji autocompletion (#987) Nov 25, 2021
@azul
Copy link
Contributor

azul commented Nov 25, 2021

I did not take a look at the code yet... but i am super excited to see this! Just wanted to share the excitement. And yes... i know there are emoji reactions for this... sometimes they are not enough though ;)

@mejo- mejo- force-pushed the enh/emoji_autocompletion branch 2 times, most recently from 7e99467 to 2d77a80 Compare November 25, 2021 21:33
@julien-nc
Copy link
Member

I digged a bit deeper here. The problem is that getBoundingClientRect() on the emojiSuggestion element returns positions (0, 0) for a short time in some cases. The only solution I could find so far is to cache the coordinates and to not update them in case of (0, 0): b5feddf

This works well in my tests, but not sure if it's the smartest solution. Let me know what you think grimacing

This fix makes sense. It now works very nicely 🚀.

Copy link
Member

@julien-nc julien-nc left a comment

Choose a reason for hiding this comment

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

Awesome!
As far as I've seen, in the suggestion list, when there's no query, only the last used emoji is added in the end. It would be nice to have the 3 last used or the 3 most used. What do you think? Does it make sense? Is it even possible/easy to implement?

@juliusknorr
Copy link
Member

@nextcloud/vue 5.0.0 was merged #2178

@mejo-
Copy link
Member Author

mejo- commented Feb 16, 2022

The only issue i ran into is that it's right now impossible to insert two emojis using autocompletion directly after each other. You need to put a space in between otherwise the dialog will not open.

For other keyboard shortcuts it makes sense not to be triggered within words. If you have text_with_underscores we don't want the with to become italic. However we're not converting :heart: to a heart emoji unless one presses tab or enter. So i think opening the emoji selector even when typing a word would be okay and would allow adding multiple emojis in a row or directly following a letterexclamation

An alternative would be to always append a space when adding an emoji. That's also, what others do. What do you think about that?

@max-nextcloud
Copy link
Collaborator

An alternative would be to always append a space when adding an emoji. That's also, what others do. What do you think about that?

That's a great idea. Avoids opening the emoji picker when ending a word with a colon like this:
Also should be fairly easy implementationwise. :D

@mejo- mejo- force-pushed the enh/emoji_autocompletion branch 2 times, most recently from 7ace9f8 to b05c62b Compare February 22, 2022 15:44
@mejo- mejo- requested review from max-nextcloud and julien-nc and removed request for azul February 22, 2022 15:45
@mejo-
Copy link
Member Author

mejo- commented Feb 22, 2022

I put some more work into the PR and think that it's ready to be merged now.

In particular, implementing automatic scrolling when navigating through the suggestion list was tricky and to be honest I'm a bit proud about the result 😊 b05c62b

Also, as discussed with @max-nextcloud, every inserted emoji now always gets a whitespace appended, to make it easy to insert several emojis in a row.

Copy link
Collaborator

@max-nextcloud max-nextcloud left a comment

Choose a reason for hiding this comment

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

Code looks very clean. Will give it a try and then merge.

@max-nextcloud
Copy link
Collaborator

/compile amend /

Copy link
Member

@juliusknorr juliusknorr left a comment

Choose a reason for hiding this comment

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

Works like a charm and also nice and clean from a code perspective 👍

@juliusknorr juliusknorr mentioned this pull request Feb 23, 2022
@max-nextcloud
Copy link
Collaborator

max-nextcloud commented Feb 24, 2022

Trying to fix the jest issue. I ran into something similar before.

  • reproduce it localy
  • figure out what its missing

maybe add to transformIgnorePatterns?

Okay... i think i found the underlying problem. There are some imports using src paths in @nextcloud/vue which should be using the package itself instead.

Using a locally linked @nextcloud/vue with these changes fixed the issue for me:

diff --git a/src/functions/emoji/emoji.js b/src/functions/emoji/emoji.js
index e54e8a28..126d327d 100644
--- a/src/functions/emoji/emoji.js
+++ b/src/functions/emoji/emoji.js
@@ -21,8 +21,7 @@
  */
 
 import data from 'emoji-mart-vue-fast/data/all.json'
-import { EmojiIndex } from 'emoji-mart-vue-fast/src'
-import frequently from 'emoji-mart-vue-fast/src/utils/frequently'
+import { EmojiIndex, frequently } from 'emoji-mart-vue-fast'
 
 // export const allEmojis = index.buildIndex()

The npm link has a sideeffect of not installing @babel/polyfill anymore since it's a nextcloud vue dependency - but not listed in our own package.json. It's deprecated anyway. So we should replace its only use in our code which is in tests. I'll add a commit with that.

@max-nextcloud
Copy link
Collaborator

nextcloud-libraries/nextcloud-vue#2521 has the upstream fix. We'll have to wait for a release of @nextcloud/vue to get this in.

mejo- and others added 4 commits March 1, 2022 10:27
Adds emoji autocompletion by typing `:<search_string>`.

It utilizes the emoji functions from nextcloud-vue[1] and the TipTap
suggestions extension.

[1] nextcloud-libraries/nextcloud-vue#1474

Signed-off-by: Jonas <jonas@freesources.org>
Navigating the suggestion list via arrow up/down keys is handled in
javascript, so we have to handle the scrolling in javascript too.

Only scrolls if the new selected item has not visible before.
At ArrowDown, scroll bottom of visible area to lower border of item.
At ArrowUp, scroll top of visible area to upper border of item.

Signed-off-by: Jonas <jonas@freesources.org>
Signed-off-by: Jonas <jonas@freesources.org>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
Importing `core-js/stable` as recommended by
https://babeljs.io/docs/en/babel-polyfill

It is also not listed in our package.json.
So far it was provided as a dependency of `emoji-mart-vue-fast`
via `@nextcloud/vue`.

Signed-off-by: Max <max@nextcloud.com>
Signed-off-by: Max <max@nextcloud.com>
@max-nextcloud max-nextcloud merged commit 5bb2ca9 into master Mar 1, 2022
@delete-merged-branch delete-merged-branch bot deleted the enh/emoji_autocompletion branch March 1, 2022 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2. developing enhancement New feature or request feature: formatting Features related to text formatting and node types upstream
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make it easy to insert emojis
6 participants