import { Chat, common, Firegun } from "@yokowasis/firegun"; import React from "react"; import EditGroupChat from "./EditGroupChat"; import InviteButton from "./InviteButton"; import AddAdminButton from "./AddAdminButton"; import Close from "@mui/icons-material/Close"; import { Button, Divider, Grid, IconButton, TextField, Typography } from "@mui/material"; import AttachFile from "@mui/icons-material/AttachFile"; import Send from "@mui/icons-material/Send"; import { RefreshRounded, Search } from "@mui/icons-material"; import Delete from "@mui/icons-material/Delete"; import { chatType } from "@yokowasis/firegun/common"; import ChatBubble from "./ChatBubble"; export default function ChatMUI( props : { partnerKey : string, height : string, fg : Firegun, chat : Chat, show : boolean, alias : string, isGroup? : boolean, groupName? : string, updateLastMsg : (key:string,lastMsg:string) => void, }) { // React Ref const partner = React.useRef({ cert : "", pub : "", epub : "", groupOwner : "", groupAlias : "", }) const chatsMessages = React.useRef([]); const chatBubbleRef = React.useRef<{[x:string] : HTMLDivElement | null}>({}) const chatsMessagesDivRef = React.useRef(<>) // REACT STATE ------------------------------------------------- const [chatsMessagesDiv, setChatsMessagesDiv] = React.useState(<>); const [searchString, setSearchString] = React.useState(""); const [textMsg, setTextMsg] = React.useState(""); // REACT EFFECT ------------------------------------------------- // Init First Time React.useEffect(()=>{ (async ()=>{ if (props.partnerKey.indexOf("&")>=0) { let dateNow = common.getDate() if (props.isGroup) { // Group Chat let keys = props.partnerKey.split("&") let owner = keys[1]; let alias = keys[2]; partner.current.groupOwner = owner; partner.current.groupAlias = alias; let data = await props.chat.groupRetrieveChatMonthly( {owner : partner.current.groupOwner, alias : partner.current.groupAlias}, { month : dateNow.month, year : dateNow.year, date: dateNow.date }, ) renderChat(data); listenGroupChat(); } else { // 1 on 1 Chat let keys:string[]; keys = props.partnerKey.split("&"); let cert = await props.chat.getCert(keys[0]); partner.current.cert = (typeof cert === "string") ? cert : ""; partner.current.pub = keys[0]; partner.current.epub = keys[1]; props.chat.markAsRead({pub : partner.current.pub, epub : partner.current.epub},partner.current.cert); // Retrieve AvailableChat let chats = await props.chat.retrieveMonthly( {pub : partner.current.pub, epub : partner.current.epub}, { month : dateNow.month, year : dateNow.year} ) renderChat(chats); listenChat(); listenUnsent(); listenMarkAsRead(); } } else { console.log ("Partner Key Incomplete") } })() },[]) React.useEffect(()=>{ // Scroll to end var objDiv = document.getElementById(`chatbox-${props.partnerKey.slice(0,8)}`); if (objDiv) objDiv.scrollTop = objDiv.scrollHeight; },[chatsMessagesDiv]) // END REACT EFFECT ------------------------------------------------- // REACT FUNCTION ----------------------------------------------------- const listenMarkAsRead = () => { props.chat.listenMarkAsRead( {pub : partner.current.pub, epub : partner.current.epub}, markAsRead ) } const markAsRead = (timestamp:string) => { let changed = false; for (const chat of chatsMessages.current) { if (chat.timestamp <= timestamp) { chat.status = "read"; changed = true; } } if (changed) { renderChat() } } const listenChat = () => { props.chat.listen( { pub : partner.current.pub, epub : partner.current.epub }, ((b)=>{ let a:chatType; a = b as chatType; insertChat(a) }) ) } const listenGroupChat = () => { props.chat.groupListen( {owner : partner.current.groupOwner, alias : partner.current.groupAlias}, ((b)=>{ let a:chatType; a = b as chatType; insertChat(a) }) ) } const listenUnsent = () => { props.chat.listenUnsent({ pub : partner.current.pub, epub : partner.current.epub },(chatID)=>{ console.log ("UNSEND FIREGUN !!!"); deleteBubleChat(chatID); }) } const sendChat = async () => { let msg = textMsg; setTextMsg(""); console.log ("Sending Chat...") // Check apakah group send if (props.isGroup) { await props.chat.groupSend( partner.current.groupOwner, partner.current.groupAlias, msg ); } else { await props.chat.send( {pub : partner.current.pub, epub: partner.current.epub}, msg, partner.current.cert ); } console.log ("Sending Chat... Success") } const Elem = (props:{elem : JSX.Element}) => { return <>{props.elem} } const insertChat = (chat:chatType) => { chatsMessages.current.push(chat); let elem = <>
{chatBubbleRef.current[chat.id] = el; return chatBubbleRef.current[chat.id]}}> { (props.isGroup) ? : }
chatsMessagesDivRef.current = <> ; setChatsMessagesDiv(chatsMessagesDivRef.current); } const renderChat = (chats:chatType[]=[]) => { for (const chat of chats) { chatsMessages.current.push(chat); } chatsMessages.current.sort(common.dynamicSort("timestamp")); let elem:JSX.Element; elem = <> {chatsMessages.current.map((chat)=>
{chatBubbleRef.current[chat.id] = el; return chatBubbleRef.current[chat.id]}}> { (props.isGroup) ? : }
)} chatsMessagesDivRef.current = elem; setChatsMessagesDiv(chatsMessagesDivRef.current); } const deleteBubleChat = (chatID:string) => { chatsMessages.current = chatsMessages.current.filter(function( obj ) { return obj.timestamp.replace(/\//g,".") !== chatID; }); renderChat(); } const deleteMultiBubleChat = (chatIDS:string[]) => { chatsMessages.current = chatsMessages.current.filter(function( obj ) { return !chatIDS.includes(obj.timestamp.replace(/\//g,".")); }); renderChat(); } const deleteMultiChat = async (chatsArray : {chatID:string, timestamp:string}[]) => { const pubkey = partner.current.pub; let chatIDs:string[] = []; for (const val of chatsArray) { console.log (val); const date = val.timestamp.split("T")[0]; // Pake await biar tidak terlalu kencang deletenya, biar database tidak corrupt await props.fg.userDel(`chat-with/${pubkey}/${date}/${val.chatID}`) chatIDs.push(val.chatID); } console.log(chatIDs); deleteMultiBubleChat(chatIDs) } const decryptChat = async (chat:chatType):Promise => { let a = await props.chat.decryptChat( chat, {pub : partner.current.pub, epub : partner.current.epub}, ) if (a.msg) { return (a.msg as string); } else { return "" } } // END REACT FUNCTION ------------------------------------------------- // EVENT HANDLER ------------------------------------------------- const handleUnsentChat = (chatID:string, timestamp:string) => { const date = timestamp.split("T")[0]; if (props.isGroup) { const groupID = `${partner.current.groupOwner}&${partner.current.groupAlias}`; props.chat.groupDeleteChat(groupID, chatID, timestamp); deleteBubleChat(chatID); } else { props.chat.unsend({ pub : partner.current.pub, epub : partner.current.epub},date,chatID,partner.current.cert); deleteBubleChat(chatID); } } const handleDeleteAll = () => { let listElements = document.getElementsByClassName("bubbleChecked"); let chatsArray:{chatID:string, timestamp:string}[] = []; for (let i = 0; i < listElements.length; i++) { let elem:HTMLElement = (listElements[i] as any); let id = elem.dataset.chatid; if (id) { chatsArray.push({chatID:id, timestamp:id.replace(/\./g,"/")}); } } deleteMultiChat(chatsArray) } const handleSendChat = async () => { sendChat(); } const handleAttachFile = async () => { let inputElement = document.getElementById(`file-${props.partnerKey.slice(0,8)}`); if (inputElement) { let file = await common.fileTobase64(inputElement as HTMLInputElement) let data = { info : file.info, content : file.content } setTextMsg(JSON.stringify(data)); } } const handleDeleteChat = (chatID:string, timestamp:string) => { const pubkey = partner.current.pub; const date = timestamp.split("T")[0]; props.fg.userDel(`chat-with/${pubkey}/${date}/${chatID}`) deleteBubleChat(chatID); } // ENDEVENT HANDLER ------------------------------------------------- return ( <> { setSearchString(e.target.value) }} label="Search" size="small" variant="standard" sx={{paddingBottom : "10px"}} /> { props.chat.searchChat(searchString,partner.current.pub,partner.current.epub,(s)=>{console.log(s)}) }}> {props.isGroup ? props.groupName : props.alias} { // Harusnya di sini isGroup dan isAdmin props.isGroup ? <> : <> } { props.fg.clearData() }}> { let elem = document.getElementById(`chatmui-${props.partnerKey}`); if ( elem !== null) { elem.style.display = 'none' } }}>
{chatsMessagesDiv}
)=>{ setTextMsg( e.target.value )}} onKeyPress={(e: React.KeyboardEvent)=>{if (e.code === "Enter") {sendChat()}}} />
) }