mirror of
https://github.com/duckietm/Nitro-Cool-UI.git
synced 2025-06-21 22:36:58 +00:00
Feat: emoji-mart in the Chatbar instead of a list
This commit is contained in:
parent
659a715374
commit
ae267e9430
@ -11,10 +11,13 @@
|
|||||||
"eslint": "eslint src --ext .ts,.tsx"
|
"eslint": "eslint src --ext .ts,.tsx"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emoji-mart/data": "^1.1.2",
|
||||||
|
"@emoji-mart/react": "^1.1.1",
|
||||||
"@nitrots/nitro-renderer": "file:submodules/renderer",
|
"@nitrots/nitro-renderer": "file:submodules/renderer",
|
||||||
"@tanstack/react-virtual": "^3.0.0-beta.60",
|
"@tanstack/react-virtual": "^3.0.0-beta.60",
|
||||||
"dompurify": "^3.0.9",
|
"dompurify": "^3.0.9",
|
||||||
"emoji-toolkit": "^7.0.1",
|
"emoji-mart": "^5.5.2",
|
||||||
|
"emoji-toolkit": "8.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.7.2",
|
"react-bootstrap": "^2.7.2",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { FC, MouseEvent, useEffect, useRef, useState } from 'react';
|
import { FC, MouseEvent, useEffect, useRef, useState } from 'react';
|
||||||
import { Overlay, Popover } from 'react-bootstrap';
|
import { Overlay, Popover } from 'react-bootstrap';
|
||||||
import { Base, Flex, Grid, NitroCardContentView } from '../../../../common';
|
import { Base, Flex, Grid, NitroCardContentView } from '../../../../common';
|
||||||
import { emojiList } from './EmojiList';
|
import data from '@emoji-mart/data'
|
||||||
|
import Picker from '@emoji-mart/react'
|
||||||
|
|
||||||
interface ChatInputEmojiSelectorViewProps
|
interface ChatInputEmojiSelectorViewProps
|
||||||
{
|
{
|
||||||
@ -16,6 +17,16 @@ export const ChatInputEmojiSelectorView: FC<ChatInputEmojiSelectorViewProps> = p
|
|||||||
const iconRef = useRef<HTMLDivElement>(null);
|
const iconRef = useRef<HTMLDivElement>(null);
|
||||||
const componentRef = useRef<HTMLDivElement>(null);
|
const componentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleEmojiSelect = (emoji: any) => {
|
||||||
|
addChatEmoji(emoji.native);
|
||||||
|
setSelectorVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addEmojiToChat = (emoji: string) => {
|
||||||
|
setChatValue(chatValue + emoji);
|
||||||
|
setIsTyping(true);
|
||||||
|
};
|
||||||
|
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
const className = 'emoji-icon';
|
const className = 'emoji-icon';
|
||||||
if (componentRef.current && !componentRef.current.contains(event.target as Node) && !(event.target as Element).classList.contains(className)) {
|
if (componentRef.current && !componentRef.current.contains(event.target as Node) && !(event.target as Element).classList.contains(className)) {
|
||||||
@ -48,19 +59,9 @@ export const ChatInputEmojiSelectorView: FC<ChatInputEmojiSelectorViewProps> = p
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Base pointer onClick={toggleSelector} innerRef={iconRef}>🙂</Base>
|
<Base pointer onClick={toggleSelector} innerRef={iconRef}>🙂</Base>
|
||||||
<Overlay show={selectorVisible} target={iconRef} placement="top">
|
<Overlay show={selectorVisible} target={iconRef} placement="top-end">
|
||||||
<Popover className="nitro-chat-style-selector-container">
|
<Popover>
|
||||||
<NitroCardContentView overflow="hidden" className="bg-transparent">
|
<Picker data={data} onEmojiSelect={handleEmojiSelect} />
|
||||||
<Grid columnCount={3} overflow="auto">
|
|
||||||
{emojiList && emojiList.length > 0 && emojiList.map((emojiId) => {
|
|
||||||
return (
|
|
||||||
<Flex center pointer key={emojiId} onClick={(event) => selectEmoji(emojiId)}>
|
|
||||||
<Base className="emoji" textColor="black" style={{ fontSize: '20px' }}>{emojiId}</Base>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Grid>
|
|
||||||
</NitroCardContentView>
|
|
||||||
</Popover>
|
</Popover>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
</>
|
</>
|
||||||
|
@ -78,7 +78,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nitro-chat-input-container .input-sizer input{
|
.nitro-chat-input-container .input-sizer input{
|
||||||
width: calc(100% - 80px)!important;
|
width: auto;
|
||||||
|
min-width: 1em;
|
||||||
|
grid-area: 1 / 2;
|
||||||
|
margin: 0;
|
||||||
|
resize: none;
|
||||||
|
background: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-chat-style-selector-container {
|
.nitro-chat-style-selector-container {
|
||||||
|
@ -218,11 +218,11 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
return styleIds;
|
return styleIds;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const addEmojiToChat = (emoji: string) =>
|
const addEmojiToChat = (emoji: string) => {
|
||||||
{
|
setChatValue(chatValue + emoji);
|
||||||
setChatValue(chatValue + emoji);
|
setIsTyping(true);
|
||||||
setIsTyping(true);
|
};
|
||||||
}
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
document.body.addEventListener('keydown', onKeyDownEvent);
|
document.body.addEventListener('keydown', onKeyDownEvent);
|
||||||
@ -247,7 +247,16 @@ export const ChatInputView: FC<{}> = props =>
|
|||||||
<div className="nitro-chat-input-container" onMouseEnter={ () => setShowInfohabboPages(true) } onMouseLeave={ () => setTimeout(() => setShowInfohabboPages(false), 100) }>
|
<div className="nitro-chat-input-container" onMouseEnter={ () => setShowInfohabboPages(true) } onMouseLeave={ () => setTimeout(() => setShowInfohabboPages(false), 100) }>
|
||||||
<div className="input-sizer align-items-center">
|
<div className="input-sizer align-items-center">
|
||||||
{ !floodBlocked &&
|
{ !floodBlocked &&
|
||||||
<input ref={ inputRef } type="text" className="chat-input" placeholder={ LocalizeText('widgets.chatinput.default') } value={ chatValue } maxLength={ maxChatLength } onChange={ event => updateChatInput(event.target.value) } onMouseDown={ event => setInputFocus() } /> }
|
<input
|
||||||
|
ref={ inputRef }
|
||||||
|
type="text"
|
||||||
|
className="chat-input"
|
||||||
|
placeholder={ LocalizeText('widgets.chatinput.default') }
|
||||||
|
value={ chatValue }
|
||||||
|
maxLength={ maxChatLength }
|
||||||
|
onChange={ event => updateChatInput(event.target.value) }
|
||||||
|
onMouseDown={ event => setInputFocus() } />
|
||||||
|
}
|
||||||
{ floodBlocked &&
|
{ floodBlocked &&
|
||||||
<Text variant="danger">{ LocalizeText('chat.input.alert.flood', [ 'time' ], [ floodBlockedSeconds.toString() ]) } </Text> }
|
<Text variant="danger">{ LocalizeText('chat.input.alert.flood', [ 'time' ], [ floodBlockedSeconds.toString() ]) } </Text> }
|
||||||
</div>
|
</div>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -8,15 +8,15 @@ interface ChatWidgetMessageViewProps
|
|||||||
chat: ChatBubbleMessage;
|
chat: ChatBubbleMessage;
|
||||||
makeRoom: (chat: ChatBubbleMessage) => void;
|
makeRoom: (chat: ChatBubbleMessage) => void;
|
||||||
bubbleWidth?: number;
|
bubbleWidth?: number;
|
||||||
|
selectedEmoji?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props => {
|
||||||
{
|
const { chat = null, makeRoom = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL, selectedEmoji } = props;
|
||||||
const { chat = null, makeRoom = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL } = props;
|
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
const [ isReady, setIsReady ] = useState<boolean>(false);
|
const [ isReady, setIsReady ] = useState<boolean>(false);
|
||||||
const { onClickChat = null } = useOnClickChat();
|
const { onClickChat = null } = useOnClickChat();
|
||||||
const elementRef = useRef<HTMLDivElement>();
|
const elementRef = useRef<HTMLDivElement>();;
|
||||||
|
|
||||||
const getBubbleWidth = useMemo(() =>
|
const getBubbleWidth = useMemo(() =>
|
||||||
{
|
{
|
||||||
@ -78,8 +78,9 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
|||||||
}, [ chat, isReady, isVisible, makeRoom ]);
|
}, [ chat, isReady, isVisible, makeRoom ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ elementRef } className={ `bubble-container newbubblehe ${ isVisible ? 'visible' : 'invisible' }` } onClick={ event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }>
|
<div ref={elementRef} className={`bubble-container newbubblehe ${isVisible ? 'visible' : 'invisible'}`} onClick={event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT)}>
|
||||||
{ (chat.styleId === 0) &&
|
{selectedEmoji && <span>{selectedEmoji}</span>}
|
||||||
|
{ (chat.styleId === 0) &&
|
||||||
<div className="user-container-bg" style={ { backgroundColor: chat.color } } /> }
|
<div className="user-container-bg" style={ { backgroundColor: chat.color } } /> }
|
||||||
<div className={ `chat-bubble bubble-${ chat.styleId } type-${ chat.type }` } style={ { maxWidth: getBubbleWidth } }>
|
<div className={ `chat-bubble bubble-${ chat.styleId } type-${ chat.type }` } style={ { maxWidth: getBubbleWidth } }>
|
||||||
<div className="user-container">
|
<div className="user-container">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user