feat: add emoji picker to chat room message input
- Integrated emoji-picker-element library for emoji selection - Added emoji toggle button in message input container - Implemented emoji picker show/hide functionality - Created CSS styles for emoji picker positioning - Added event handling for emoji selection and outside click - Updated package.json to include emoji-picker-element dependency - Modified Prisma schema to use TEXT type for message content - Updated Prisma migration scripts to use dotenv for environment configuration
This commit is contained in:
parent
1e3b188d90
commit
3d41e2cc42
7 changed files with 111 additions and 11 deletions
|
@ -1,7 +1,10 @@
|
|||
import { createSignal, createEffect, For, Show } from 'solid-js';
|
||||
import { createSignal, createEffect, For, Show, onMount } from 'solid-js';
|
||||
import { gql } from '@urql/core';
|
||||
import { createQuery, createMutation, createSubscription } from '@urql/solid';
|
||||
import { Message } from '../types';
|
||||
import 'emoji-picker-element';
|
||||
import { EmojiClickEvent } from 'emoji-picker-element/shared';
|
||||
import { Picker } from 'emoji-picker-element';
|
||||
|
||||
const ROOM_QUERY = gql`
|
||||
query GetRoom($id: ID!) {
|
||||
|
@ -80,7 +83,13 @@ export function ChatRoom(props: ChatRoomProps) {
|
|||
const [messages, setMessages] = createSignal<Message[]>([]);
|
||||
const [confirmLeave, setConfirmLeave] = createSignal(false);
|
||||
const [leaveError, setLeaveError] = createSignal<string | null>(null);
|
||||
const [showEmojiPicker, setShowEmojiPicker] = createSignal(false);
|
||||
const [emojiPickerRef, setPickerRef] = createSignal<Picker | undefined>(
|
||||
undefined
|
||||
);
|
||||
let messagesContainer: HTMLDivElement | undefined;
|
||||
let messageInput: HTMLInputElement | undefined;
|
||||
let emojiPickerContainer: HTMLDivElement | undefined;
|
||||
|
||||
const scrollToBottom = () => {
|
||||
if (messagesContainer) {
|
||||
|
@ -198,6 +207,41 @@ export function ChatRoom(props: ChatRoomProps) {
|
|||
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
};
|
||||
|
||||
const toggleEmojiPicker = () => {
|
||||
setShowEmojiPicker(!showEmojiPicker());
|
||||
};
|
||||
|
||||
createEffect(() => {
|
||||
const handleEmojiSelect = (event: EmojiClickEvent) => {
|
||||
setMessage((prev) => prev + event.detail.unicode);
|
||||
messageInput?.focus();
|
||||
};
|
||||
const ref = emojiPickerRef();
|
||||
if (ref) {
|
||||
ref.addEventListener('emoji-click', handleEmojiSelect);
|
||||
return () => {
|
||||
ref.removeEventListener('emoji-click', handleEmojiSelect);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Close emoji picker when clicking outside
|
||||
onMount(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
emojiPickerContainer &&
|
||||
!emojiPickerContainer.contains(event.target as Node)
|
||||
) {
|
||||
setShowEmojiPicker(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div class='chat-room'>
|
||||
<Show when={roomQuery.data?.room} fallback={<div>Loading room...</div>}>
|
||||
|
@ -246,13 +290,30 @@ export function ChatRoom(props: ChatRoomProps) {
|
|||
</div>
|
||||
|
||||
<form class='message-form' onSubmit={handleSendMessage}>
|
||||
<input
|
||||
type='text'
|
||||
value={message()}
|
||||
onInput={(e) => setMessage(e.currentTarget.value)}
|
||||
placeholder='Type a message...'
|
||||
/>
|
||||
<div class='message-input-container'>
|
||||
<input
|
||||
ref={messageInput}
|
||||
type='text'
|
||||
value={message()}
|
||||
onInput={(e) => setMessage(e.currentTarget.value)}
|
||||
placeholder='Type a message...'
|
||||
/>
|
||||
<button
|
||||
type='button'
|
||||
class='emoji-toggle-button'
|
||||
onClick={toggleEmojiPicker}
|
||||
>
|
||||
😊
|
||||
</button>
|
||||
</div>
|
||||
<button type='submit'>Send</button>
|
||||
|
||||
{showEmojiPicker() && (
|
||||
<div ref={emojiPickerContainer} class='emoji-picker-container'>
|
||||
{/* @ts-ignore */}
|
||||
<emoji-picker ref={(el: Picker) => setPickerRef(el)}></emoji-picker>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue