Spaces:
Paused
Paused
File size: 6,702 Bytes
a0fda44 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import React, { useMemo, useState } from "react";
import { useSelector } from "react-redux";
import IconWrapper from "../../globals/IconWrapper";
import AttachFileModal from "./AttachFileModal";
import MessageInput from "./MessageInput";
import useRecorder from "../../../hooks/useRecorder";
import StopRecordModal from "./StopRecordModal";
import useMessageInput from "../../../hooks/useMessageInput";
import CTAButtons from "./CTAButtons";
import AttachFileOrRecordDuration from "./AttachFileOrRecordDuration";
import EmojiModal from "./EmojiModal";
import BubbleTail from "./BubbleTail";
function NewMessage({ currentChatRoom }) {
// Get current message mode
const messageMode = useSelector((state) => state.chatReducer.mode);
// Message Input
const {
addEmojiToMessage,
handleInput,
messageEmpty,
getCaretIndex,
emitTypingEvent,
setMessageEmpty,
} = useMessageInput({ currentChatRoom });
// Emoji modal visibility
const [emojiVisible, setEmojiVisible] = useState(false);
const isRecording = useMemo(() => messageMode === "recording", [messageMode]);
const isTyping = useMemo(() => messageMode === "typing", [messageMode]);
// Recorder hook to record messages
const {
formattedTime,
startRecording,
endRecording,
playRecording,
clearRecording,
pauseRecording,
} = useRecorder({ currentChatRoom });
return (
<div className="flex flex-col shrink-0">
<div className="flex items-end gap-[1.5rem] sm:gap-0">
{/* Message form bubble */}
<div
className={` overflow-x-hidden flex-grow duration-75 flex items-end ${
isRecording ? "mr-[6rem]" : "mr-0"
}`}
>
{/* Message form */}
<div
className={`bg-primary px-[1.5rem] py-[1rem] rounded-2xl rounded-br-none flex-grow flex items-end overflow-x-hidden`}
>
{/* Emoji picker */}
<IconWrapper
onClick={() => setEmojiVisible((prevState) => !prevState)}
className="shrink-0"
>
{emojiVisible && (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 16 16"
>
<g fill="currentColor" className="fill-secondary-text">
<path d="M14 5a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h12zM2 4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H2z" />
<path d="M13 10.25a.25.25 0 0 1 .25-.25h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5a.25.25 0 0 1-.25-.25v-.5zm0-2a.25.25 0 0 1 .25-.25h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5a.25.25 0 0 1-.25-.25v-.5zm-5 0A.25.25 0 0 1 8.25 8h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5A.25.25 0 0 1 8 8.75v-.5zm2 0a.25.25 0 0 1 .25-.25h1.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-1.5a.25.25 0 0 1-.25-.25v-.5zm1 2a.25.25 0 0 1 .25-.25h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5a.25.25 0 0 1-.25-.25v-.5zm-5-2A.25.25 0 0 1 6.25 8h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5A.25.25 0 0 1 6 8.75v-.5zm-2 0A.25.25 0 0 1 4.25 8h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5A.25.25 0 0 1 4 8.75v-.5zm-2 0A.25.25 0 0 1 2.25 8h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5A.25.25 0 0 1 2 8.75v-.5zm11-2a.25.25 0 0 1 .25-.25h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5a.25.25 0 0 1-.25-.25v-.5zm-2 0a.25.25 0 0 1 .25-.25h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5a.25.25 0 0 1-.25-.25v-.5zm-2 0A.25.25 0 0 1 9.25 6h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5A.25.25 0 0 1 9 6.75v-.5zm-2 0A.25.25 0 0 1 7.25 6h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5A.25.25 0 0 1 7 6.75v-.5zm-2 0A.25.25 0 0 1 5.25 6h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5A.25.25 0 0 1 5 6.75v-.5zm-3 0A.25.25 0 0 1 2.25 6h1.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-1.5A.25.25 0 0 1 2 6.75v-.5zm0 4a.25.25 0 0 1 .25-.25h.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-.5a.25.25 0 0 1-.25-.25v-.5zm2 0a.25.25 0 0 1 .25-.25h5.5a.25.25 0 0 1 .25.25v.5a.25.25 0 0 1-.25.25h-5.5a.25.25 0 0 1-.25-.25v-.5z" />
</g>
</svg>
)}
{!emojiVisible && (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 48 48"
>
<path
fill="currentColor"
d="M17.5 22a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5ZM33 19.5a2.5 2.5 0 1 1-5 0a2.5 2.5 0 0 1 5 0ZM18.452 34.681A11.718 11.718 0 0 0 24 36a11.718 11.718 0 0 0 9.816-5.1a1.249 1.249 0 1 0-2.13-1.307A9.212 9.212 0 0 1 24 33.5a9.22 9.22 0 0 1-7.687-3.907a1.248 1.248 0 1 0-2.13 1.307a11.718 11.718 0 0 0 4.269 3.781ZM24 4C12.954 4 4 12.954 4 24s8.954 20 20 20s20-8.954 20-20S35.046 4 24 4ZM6.5 24c0-9.665 7.835-17.5 17.5-17.5S41.5 14.335 41.5 24S33.665 41.5 24 41.5S6.5 33.665 6.5 24Z"
/>
</svg>
)}
</IconWrapper>
{/* Message Input */}
<MessageInput
isRecording={isRecording}
handleInput={handleInput}
messageEmpty={messageEmpty}
getCaretIndex={getCaretIndex}
emitTypingEvent={emitTypingEvent}
/>
<AttachFileOrRecordDuration
isRecording={isRecording}
formattedTime={formattedTime}
/>
</div>
<BubbleTail fillColor="fill-primary stroke-primary" />
</div>
{/* Action buttons to record stop recording and send messages or voice notes */}
<CTAButtons
startRecording={startRecording}
endRecording={endRecording}
isTyping={isTyping}
isRecording={isRecording}
clearRecording={clearRecording}
pauseRecording={pauseRecording}
setMessageEmpty={setMessageEmpty}
/>
</div>
{/* Modals */}
{/* To pick emoji */}
<EmojiModal
emojiVisible={emojiVisible}
setEmojiVisible={setEmojiVisible}
addEmojiToMessage={addEmojiToMessage}
/>
{/* To attach either video or photo */}
<AttachFileModal />
{/* Ask confirmation to stop recording if user types into keyboard while recording */}
<StopRecordModal
playRecording={playRecording}
clearRecording={clearRecording}
/>
</div>
);
}
export default NewMessage;
|