-
-
Save Daltonic/80196de5b0f62a3066ab18625ea7d5a6 to your computer and use it in GitHub Desktop.
Dapp Cinemas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Menu } from '@headlessui/react' | |
import { FiEdit } from 'react-icons/fi' | |
import { BiLogInCircle } from 'react-icons/bi' | |
import { SiGnuprivacyguard } from 'react-icons/si' | |
import { BsChatLeftDots } from 'react-icons/bs' | |
import { FiChevronDown } from 'react-icons/fi' | |
import { MdOutlineJoinLeft } from 'react-icons/md' | |
import { toast } from 'react-toastify' | |
import { | |
createNewGroup, | |
joinGroup, | |
loginWithCometChat, | |
signUpWithCometChat, | |
} from '../services/chat' | |
import { setGlobalState, useGlobalState } from '../store' | |
const ChatActions = ({ movie, group }) => { | |
const [connectedAccount] = useGlobalState('connectedAccount') | |
const [owner] = useGlobalState('deployer') | |
const [currentUser] = useGlobalState('currentUser') | |
const handleSignUp = async () => { | |
await toast.promise( | |
new Promise(async (resolve, reject) => { | |
await signUpWithCometChat(connectedAccount) | |
.then((user) => resolve(user)) | |
.catch((error) => { | |
alert(JSON.stringify(error)) | |
reject(error) | |
}) | |
}), | |
{ | |
pending: 'Signning up...', | |
success: 'Signed up successfully, please login 👌', | |
error: 'Encountered error 🤯', | |
} | |
) | |
} | |
const handleLogin = async () => { | |
await toast.promise( | |
new Promise(async (resolve, reject) => { | |
await loginWithCometChat(connectedAccount) | |
.then((user) => { | |
setGlobalState('currentUser', user) | |
resolve(user) | |
window.location.reload() | |
}) | |
.catch((error) => { | |
alert(JSON.stringify(error)) | |
reject(error) | |
}) | |
}), | |
{ | |
pending: 'Logging...', | |
success: 'Logged in successfully 👌', | |
error: 'Encountered error 🤯', | |
} | |
) | |
} | |
const handleCreateGroup = async () => { | |
await toast.promise( | |
new Promise(async (resolve, reject) => { | |
await createNewGroup(`guid_${movie.id}`, movie.name) | |
.then((group) => { | |
setGlobalState('group', group) | |
resolve(group) | |
window.location.reload() | |
}) | |
.catch((error) => { | |
alert(JSON.stringify(error)) | |
reject(error) | |
}) | |
}), | |
{ | |
pending: 'Creating group...', | |
success: 'Group created successfully 👌', | |
error: 'Encountered error 🤯', | |
} | |
) | |
} | |
const handleJoinGroup = async () => { | |
await toast.promise( | |
new Promise(async (resolve, reject) => { | |
await joinGroup(`guid_${movie.id}`) | |
.then((group) => { | |
setGlobalState('group', group) | |
resolve() | |
window.location.reload() | |
}) | |
.catch((error) => { | |
alert(JSON.stringify(error)) | |
reject(error) | |
}) | |
}), | |
{ | |
pending: 'Joining group...', | |
success: 'Group joined successfully 👌', | |
error: 'Encountered error 🤯', | |
} | |
) | |
} | |
return ( | |
<Menu as="div" className="relative inline-block text-left mx-auto"> | |
<Menu.Button | |
className="inline-flex justify-center items-center space-x-2 | |
rounded-md bg-black bg-opacity-10 px-4 py-2 text-sm | |
font-medium text-black hover:bg-opacity-30 focus:outline-none | |
focus-visible:ring-2 focus-visible:ring-white | |
focus-visible:ring-opacity-75" | |
> | |
<span>Chat Options</span> | |
<FiChevronDown size={17} /> | |
</Menu.Button> | |
<Menu.Items | |
className="absolute right-0 mt-2 w-56 origin-top-right | |
divide-y divide-gray-100 rounded-md bg-white shadow-md | |
ing-1 ring-black ring-opacity-5 focus:outline-none" | |
> | |
{!currentUser && ( | |
<> | |
<Menu.Item> | |
{({ active }) => ( | |
<button | |
className={`flex justify-start items-center space-x-1 ${ | |
active ? 'bg-gray-200 text-black' : 'text-red-500' | |
} group flex w-full items-center rounded-md px-2 py-2 text-sm`} | |
onClick={handleSignUp} | |
> | |
<SiGnuprivacyguard size={17} /> | |
<span>Chat SignUp</span> | |
</button> | |
)} | |
</Menu.Item> | |
<Menu.Item> | |
{({ active }) => ( | |
<button | |
className={`flex justify-start items-center space-x-1 ${ | |
active ? 'bg-gray-200 text-black' : 'text-gray-900' | |
} group flex w-full items-center rounded-md px-2 py-2 text-sm`} | |
onClick={handleLogin} | |
> | |
<BiLogInCircle size={17} /> | |
<span>Chat Login</span> | |
</button> | |
)} | |
</Menu.Item> | |
</> | |
)} | |
{currentUser && ( | |
<> | |
{currentUser.uid != owner && group && !group.hasJoined && ( | |
<Menu.Item> | |
{({ active }) => ( | |
<button | |
className={`flex justify-start items-center space-x-1 ${ | |
active ? 'bg-gray-200 text-black' : 'text-gray-900' | |
} group flex w-full items-center rounded-md px-2 py-2 text-sm`} | |
onClick={handleJoinGroup} | |
> | |
<MdOutlineJoinLeft size={17} /> | |
<span>Join Group</span> | |
</button> | |
)} | |
</Menu.Item> | |
)} | |
{currentUser.uid == owner && !group && ( | |
<Menu.Item> | |
{({ active }) => ( | |
<button | |
className={`flex justify-start items-center space-x-1 ${ | |
active ? 'bg-gray-200 text-black' : 'text-gray-900' | |
} group flex w-full items-center rounded-md px-2 py-2 text-sm`} | |
onClick={handleCreateGroup} | |
> | |
<FiEdit size={17} /> | |
<span>Create Group</span> | |
</button> | |
)} | |
</Menu.Item> | |
)} | |
{group && group.hasJoined && ( | |
<Menu.Item> | |
{({ active }) => ( | |
<button | |
className={`flex justify-start items-center space-x-1 ${ | |
active ? 'bg-gray-200 text-black' : 'text-gray-900' | |
} group flex w-full items-center rounded-md px-2 py-2 text-sm`} | |
onClick={() => setGlobalState('chatModal', 'scale-100')} | |
> | |
<BsChatLeftDots size={17} /> | |
<span>Chat</span> | |
</button> | |
)} | |
</Menu.Item> | |
)} | |
</> | |
)} | |
</Menu.Items> | |
</Menu> | |
) | |
} | |
export default ChatActions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { FaTimes } from 'react-icons/fa' | |
import { setGlobalState, useGlobalState } from '../store' | |
import Identicon from 'react-identicons' | |
import { truncate } from '../store' | |
import { getMessages, sendMessage, listenForMessage } from '../services/chat' | |
import { useState, useEffect } from 'react' | |
const ChatModal = ({ movie }) => { | |
const [chatModal] = useGlobalState('chatModal') | |
const [message, setMessage] = useState('') | |
const [messages] = useGlobalState('messages') | |
const onSendMessage = async (e) => { | |
e.preventDefault() | |
if (!message) return | |
await sendMessage('guid_' + movie.id, message).then((msg) => { | |
setGlobalState('messages', (prevState) => [...prevState, msg]) | |
setMessage('') | |
scrollToEnd() | |
}) | |
} | |
useEffect(() => { | |
const fetchData = async () => { | |
await getMessages('guid_' + movie.id).then((msgs) => { | |
setGlobalState('messages', msgs) | |
scrollToEnd() | |
}) | |
await listenForMessage('guid_' + movie.id).then((msg) => { | |
setGlobalState('messages', (prevState) => [...prevState, msg]) | |
scrollToEnd() | |
}) | |
} | |
fetchData() | |
}, []) | |
const scrollToEnd = () => { | |
const elmnt = document.getElementById('messages-container') | |
elmnt.scrollTop = elmnt.scrollHeight | |
} | |
return ( | |
<div | |
className={`fixed -top-4 left-0 w-screen h-screen flex items-center justify-center bg-black bg-opacity-50 transform z-50 transition-transform duration-300 ${chatModal}`} | |
> | |
<div className="bg-slate-200 shadow-lg shadow-slate-900 rounded-xl w-11/12 md:w-3/5 h-[30rem] p-6 relative"> | |
<div className="flex justify-between items-center"> | |
<h2 className="capitalize">{movie.name}: Chat Room</h2> | |
<FaTimes | |
className="cursor-pointer" | |
onClick={() => setGlobalState('chatModal', 'scale-0')} | |
/> | |
</div> | |
<div | |
id="messages-container" | |
className="overflow-y-scroll overflow-x-hidden h-[20rem] scroll-bar mt-5 px-4 py-3 bg-gray-300 rounded-md" | |
> | |
<div className="w-11/12"> | |
{messages.map((msg, i) => ( | |
<Message message={msg.text} uid={msg.sender.uid} key={i} /> | |
))} | |
</div> | |
</div> | |
<form className="h-[4rem] w-full mt-4" onSubmit={onSendMessage}> | |
<input | |
value={message} | |
onChange={(e) => setMessage(e.target.value)} | |
className="h-full w-full p-5 focus:outline-none focus:ring-0 rounded-md border-none | |
bg-[rgba(0,0,0,0.7)] text-white placeholder-white" | |
placeholder="Leave a message..." | |
/> | |
</form> | |
</div> | |
</div> | |
) | |
} | |
const Message = ({ message, uid }) => { | |
return ( | |
<div className="flex justify-start items-center space-x-3 space-y-3"> | |
<div className="flex items-center space-x-2"> | |
<Identicon string={uid} size={15} className="rounded-full" /> | |
<p className="font-semibold text-sm">{truncate(uid, 4, 4, 11)}</p> | |
</div> | |
<p className="text-xs">{message}</p> | |
</div> | |
) | |
} | |
export default ChatModal |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment