22import React , { useState , useEffect , useRef } from 'react' ;
33import { useAuth } from '../hooks/useAuth' ;
44import { ChatMessage } from '../types' ;
5- import { ArrowLeft , Video , Plus , Send , X , Smile , Trash2 , Loader2 , MoreVertical } from 'lucide-react' ;
5+ import { ArrowLeft , Video , Plus , Send , X , Smile , Trash2 , Loader2 , MoreVertical , Image as ImageIcon } from 'lucide-react' ;
66import { format } from 'date-fns' ;
77import { motion , AnimatePresence } from 'framer-motion' ;
88import * as ReactRouterDOM from 'react-router-dom' ;
@@ -55,9 +55,33 @@ const ChatPage: React.FC = () => {
5555 const [ newMessage , setNewMessage ] = useState ( '' ) ;
5656 const [ imagePreviews , setImagePreviews ] = useState < string [ ] > ( [ ] ) ;
5757 const [ reactingTo , setReactingTo ] = useState < string | null > ( null ) ;
58+ const [ showStickerPicker , setShowStickerPicker ] = useState ( false ) ;
5859 const messagesEndRef = useRef < HTMLDivElement > ( null ) ;
5960 const fileInputRef = useRef < HTMLInputElement > ( null ) ;
6061
62+ // Popular emojis/stickers (can be extended)
63+ const stickers = [
64+ '😀' , '😃' , '😄' , '😁' , '😆' , '😅' , '😂' , '🤣' , '😊' , '😇' ,
65+ '🙂' , '🙃' , '😉' , '😌' , '😍' , '🥰' , '😘' , '😗' , '😙' , '😚' ,
66+ '😋' , '😛' , '😝' , '😜' , '🤪' , '🤨' , '🧐' , '🤓' , '😎' , '🤩' ,
67+ '🥳' , '😏' , '😒' , '😞' , '😔' , '😟' , '😕' , '🙁' , '😣' , '😖' ,
68+ '😫' , '😩' , '🥺' , '😢' , '😭' , '😤' , '😠' , '😡' , '🤬' , '🤯' ,
69+ '😳' , '🥵' , '🥶' , '😱' , '😨' , '😰' , '😥' , '😓' , '🤗' , '🤔' ,
70+ '🤭' , '🤫' , '🤥' , '😶' , '😐' , '😑' , '😬' , '🙄' , '😯' , '😦' ,
71+ '😧' , '😮' , '😲' , '🥱' , '😴' , '🤤' , '😪' , '😵' , '🤐' , '🥴' ,
72+ '🤢' , '🤮' , '🤧' , '😷' , '🤒' , '🤕' , '🤑' , '🤠' , '😈' , '👿' ,
73+ '👹' , '👺' , '🤡' , '💩' , '👻' , '💀' , '☠️' , '👽' , '👾' , '🤖' ,
74+ '🎃' , '😺' , '😸' , '😹' , '😻' , '😼' , '😽' , '🙀' , '😿' , '😾' ,
75+ '👋' , '🤚' , '🖐' , '✋' , '🖖' , '👌' , '🤏' , '✌️' , '🤞' , '🤟' ,
76+ '🤘' , '🤙' , '👈' , '👉' , '👆' , '🖕' , '👇' , '☝️' , '👍' , '👎' ,
77+ '✊' , '👊' , '🤛' , '🤜' , '👏' , '🙌' , '👐' , '🤲' , '🤝' , '🙏' ,
78+ '✍️' , '💪' , '🦾' , '🦿' , '🦵' , '🦶' , '👂' , '🦻' , '👃' , '🧠' ,
79+ '🦷' , '🦴' , '👀' , '👁️' , '👅' , '👄' , '💋' , '💘' , '💝' , '💖' ,
80+ '💗' , '💓' , '💞' , '💕' , '💟' , '❣️' , '💔' , '❤️' , '🧡' , '💛' ,
81+ '💚' , '💙' , '💜' , '🖤' , '🤍' , '🤎' , '💯' , '💢' , '💥' , '💫' ,
82+ '💦' , '💨' , '🕳️' , '💣' , '💬' , '👁️🗨️' , '🗨️' , '🗯️' , '💭' , '💤' ,
83+ ] ;
84+
6185 useEffect ( ( ) => {
6286 setChatActive ( true ) ;
6387 return ( ) => setChatActive ( false ) ;
@@ -97,6 +121,18 @@ const ChatPage: React.FC = () => {
97121 }
98122 } ;
99123
124+ const handleStickerSelect = async ( sticker : string ) => {
125+ setShowStickerPicker ( false ) ;
126+ try {
127+ await sendMessage ( {
128+ content_text : sticker
129+ } ) ;
130+ } catch ( error ) {
131+ console . error ( "Failed to send sticker:" , error ) ;
132+ alert ( "Failed to send sticker. Please try again." ) ;
133+ }
134+ } ;
135+
100136 return (
101137 < div className = "h-[calc(100vh-140px)] md:h-[calc(100vh-64px)] flex flex-col bg-black text-white relative overflow-hidden rounded-3xl border border-white/5" >
102138 < header className = "flex items-center justify-between p-4 border-b border-zinc-800 bg-black/80 backdrop-blur-md sticky top-0 z-20" >
@@ -263,7 +299,7 @@ const ChatPage: React.FC = () => {
263299 ) }
264300 </ AnimatePresence >
265301
266- < form onSubmit = { handleSend } className = "flex items-center gap-3" >
302+ < form onSubmit = { handleSend } className = "flex items-center gap-3 relative " >
267303 < button
268304 type = "button"
269305 onClick = { ( ) => fileInputRef . current ?. click ( ) }
@@ -280,13 +316,46 @@ const ChatPage: React.FC = () => {
280316 onChange = { handleFileChange }
281317 />
282318
319+ < button
320+ type = "button"
321+ onClick = { ( ) => setShowStickerPicker ( ! showStickerPicker ) }
322+ className = { `p-3 rounded-2xl text-zinc-400 hover:text-white transition-all border border-white/5 ${
323+ showStickerPicker ? 'bg-indigo-600 text-white' : 'bg-zinc-900 hover:bg-zinc-800'
324+ } `}
325+ >
326+ < Smile size = { 20 } />
327+ </ button >
328+
329+ { /* Sticker Picker */ }
330+ { showStickerPicker && (
331+ < motion . div
332+ initial = { { opacity : 0 , y : 10 } }
333+ animate = { { opacity : 1 , y : 0 } }
334+ exit = { { opacity : 0 , y : 10 } }
335+ className = "absolute bottom-full left-0 mb-2 w-80 h-64 bg-[#1A1A1A] border border-white/10 rounded-2xl p-4 overflow-y-auto shadow-2xl z-50"
336+ >
337+ < div className = "grid grid-cols-8 gap-2" >
338+ { stickers . map ( ( sticker , index ) => (
339+ < button
340+ key = { index }
341+ onClick = { ( ) => handleStickerSelect ( sticker ) }
342+ className = "p-2 hover:bg-zinc-800 rounded-lg text-2xl transition-colors"
343+ >
344+ { sticker }
345+ </ button >
346+ ) ) }
347+ </ div >
348+ </ motion . div >
349+ ) }
350+
283351 < div className = "flex-1 relative" >
284352 < input
285353 type = "text"
286354 value = { newMessage }
287355 onChange = { ( e ) => setNewMessage ( e . target . value ) }
288356 placeholder = "Send a secure message..."
289357 className = "w-full py-4 pl-5 pr-12 bg-zinc-900/50 border border-white/5 rounded-2xl focus:outline-none focus:border-indigo-500/50 transition-all text-sm placeholder-zinc-600"
358+ onFocus = { ( ) => setShowStickerPicker ( false ) }
290359 />
291360 < button
292361 type = "submit"
0 commit comments