-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Added emoji picker in mobile app keyboard topbar #7523
Conversation
Hello @harshal2030, Thanks for your pull request! A Core Committer will review your pull request soon. For code contributions, you can learn more about the review process here. |
I believe that it needs change with localization files if needed exact text from figma for image bottom sheet. I need input from your side on this, if similar text from localization can be used or needs a change. thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. The only required change is the one about not needing the customEmojis
. The rest I leave it to you to consider whether it make sense to address it here.
const handleEmojiClick = useCallback((emoji: string) => { | ||
let emojiDraft: string; | ||
|
||
const emojiData = getEmojiByName(emoji, customEmojis); | ||
|
||
if (emojiData?.image && emojiData.category !== 'custom') { | ||
const codeArray: string[] = emojiData.image.split('-'); | ||
const code = codeArray.reduce((acc, c) => { | ||
return acc + String.fromCodePoint(parseInt(c, 16)); | ||
}, ''); | ||
emojiDraft = code; | ||
} else { | ||
emojiDraft = `:${emoji}: `; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A great part of this logic probably comes from components/autocomplete/emoji_suggestion/emoji_suggestion.tsx
. Any chance we can extract it to a common function in the utils folder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I feel too that it can be refactored, will do it
const handleEmojiClick = useCallback((emoji: string) => { | ||
let emojiDraft: string; | ||
|
||
const emojiData = getEmojiByName(emoji, customEmojis); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel we don't need the custom emojis at this level, since they will go all through the else part of the next condition.
So we an pass here an empty list, and for this will result in the same behavior, right?
emojiDraft = `:${emoji}: `; | ||
} | ||
|
||
updateValue((v) => `${v}${emojiDraft} `); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this always add the emoji at the end or at the cursor? Right now I feel it can stay as is if it only adds it at the end, but we will probably add another ticket to add it at the cursor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I would like to work on that, would be really helpful if you can automatically assign me when issue created
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another minor thing.
import {changeOpacity} from '@utils/theme'; | ||
|
||
import CameraType, {type ImageOptions} from './image_type'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file has been renamed to image type, but you are still importing it here as camera type.
@harshal2030 Regarding the strings, you need to run @abhijit-singh The figma design had a different text than what we have nowadays in the app: If so, @harshal2030 you will need to update those two strings manually on |
Ok cool |
@harshal2030 & @larkox We don't need to update the strings right now. What we have in the app currently works 👍 |
@larkox I've updated code based on your comments also I found some bugs along the way such wrong cursor position on autocomplete for both @ mention and emoji. So I fixed those too in this PR. I'm attaching the screenshot before the fix to have better context. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor things, but LGTM. Great work!
<SlideUpPanelItem | ||
icon='camera-outline' | ||
onPress={onPhoto} | ||
testID='camera_type.photo' | ||
text={intl.formatMessage({id: 'camera_type.photo.option', defaultMessage: 'Capture Photo'})} | ||
text={intl.formatMessage({id: 'camera_type.photo.option', defaultMessage: 'Capture photo'})} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have an unexpected change here and the next component also.
let emojiDraft: string; | ||
const {emojiCode, emojiData} = getEmojiCodeAndData(emoji, []); | ||
|
||
if (emojiData?.image && emojiData.category !== 'custom') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have this if inside getEmojiCodeAndData
so I wonder if there is any "readable and nice" way to get rid of it.
I understand we still need to know if it is a unicode emoji or just text to add or not the :
, and that we don't add the :
consistently in the two places this function is called, so... Happy to leave it as it is, but if you come up with a cleaner way, I am all ears 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I'll try
@@ -319,6 +319,7 @@ export default function PostInput({ | |||
onChangeText={handleTextChange} | |||
onFocus={onFocus} | |||
onPaste={onPaste} | |||
selection={{start: cursorPosition, end: cursorPosition}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what this change is for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its for changing cursor position. Please see below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@larkox I've updated code based on your comments also I found some bugs along the way such wrong cursor position on autocomplete for both @ mention and emoji. So I fixed those too in this PR. I'm attaching the screenshot before the fix to have better context.
If we select an option in autocomplete when the cursor is between two text, the position of cursor not correct. The selection prop allow us to change cursor position
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this will mess with selections in general, since (if I am reading right) if I select some text, this will overwrite that selection, and leave it unselected. Am I right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes right, I'll fix it
@larkox fixed your comments, fixed selection prop too, still looking for better refactor |
@@ -319,6 +321,7 @@ export default function PostInput({ | |||
onChangeText={handleTextChange} | |||
onFocus={onFocus} | |||
onPaste={onPaste} | |||
selection={canUpdateCursorPosition ? {start: cursorPosition, end: cursorPosition} : undefined} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't completely get the idea here. Can you explain it?
I see that you set the canUpdateCursorPosition
state based on who is updating the cursor position, but it would feel that the moment one of the systems sets this to true, we stop being able to select some part of the input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the need of updating cursor is when the user uses autocomplete or pick emoji. Whenever user, does the same, canUpdateCursorPosition
sets to true but then after when user selects or type something, it changes to false and we no longer control selection. This way the selection doesn't gets over written
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yasserfaraazkhan Please give some love to this part of the functionality when you get to QA this.
/update-branch |
@larkox I've added one more issue to this PR, please review and let me know if anything needs change |
Building app in separate branch. |
app/utils/emoji/helpers.ts
Outdated
@@ -370,3 +369,24 @@ export const searchEmojis = (fuse: Fuse<string>, searchTerm: string) => { | |||
|
|||
return []; | |||
}; | |||
|
|||
export const getEmojiCode = (emoji: string, customEmojis: CustomEmojiModel[] = [], ios = false) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the last argument can be removed and use the Platform
module to identify if is iOS
app/utils/emoji/helpers.ts
Outdated
|
||
// We are going to set a double : on iOS to prevent the auto correct from taking over and replacing it | ||
// with the wrong value, this is a hack but I could not found another way to solve it | ||
const prefix = ios ? '::' : ':'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const prefix = ios ? '::' : ':'; | |
const prefix = Platform.OS === 'ios' ? '::' : ':'; |
if (Platform.OS === 'ios') { | ||
prefix = '::'; | ||
} | ||
const isIOS = Platform.OS === 'ios'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed, see the comment on getEmojiCode
utility function
const onLibrary = async () => { | ||
const options: ImageOptions = { | ||
mediaType: 'photo', | ||
saveToPhotos: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not needed
@enahum fixed your comments, let me know if anything needs change |
<SlideUpPanelItem | ||
icon='image-outline' | ||
onPress={onLibrary} | ||
testID='' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
Hi, there's been no update on this PR for a long time, is there anything I need to change? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this PR missing the check for the config to determine if the emoji picker is enabled or not? I couldn't find it anywhere
@enahum can you please more context on the config? I don't fully understand |
In the system console we have a setting to determine if the emoji picker should be enabled or not https://docs.mattermost.com/configure/site-configuration-settings.html#emoji-enablepicker If disabled, we should not show the option to open the emoji picker added in this PR |
ok, got it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @harshal2030! Awesome work! The basic functionality looks good but I can see a few weird issues here and there. Will try to explain them here and also attaching a screencap:
- After adding an emoji from the new emoji picker for the first time once you open a particular channel, the input cursor lands before the emoji. Expectation - the cursor should be placed after the emoji.
- Also, if you add more emojis after that, the placement is not consistent. They should ideally be placed one after the other. (Notice where each successive emoji gets added in the screencap attached)
- After adding an emoji, if you try to type something, the first character gets deleted automatically.
Screen.cap.1.mp4
Screen.cap.2.mp4
This Emoji picker looks like a Reaction modal. I've created a Emoji keyboard looks like video below. If you want, I will create a PR. EmojiKeyboard.mov |
@abhijit-singh I actually like what @minhthu-bic has done with the keyboard area, what do you think? The only change I would make is to move the custom emojis to the end of the list. |
This PR has been automatically labelled "stale" because it hasn't had recent activity. |
Summary
This PR adds emoji picker in the quick actions and merge library option with camera using bottom sheet
Ticket Link
Fixes mattermost/mattermost#24323
Fixes mattermost/mattermost#24460
Checklist
Device Information
This PR was tested on:
Device Name: Samsung Galaxy S20 FE
OS: Android 13
Screenshots
mm.cursor.mp4
Release Note