From dfcab8b2a9bd1d40d6a5fafec20ead16c891f67b Mon Sep 17 00:00:00 2001 From: ccases Date: Wed, 20 Oct 2021 12:37:21 +0800 Subject: [PATCH 1/3] changed from states to context --- src/APIContext.js | 12 ----- src/AllUsersContext.js | 6 --- src/Services/UserContexts.js | 7 +++ src/components/Chat/Chat.js | 16 +++---- src/components/Chat/ChatArea.js | 16 ++----- src/components/Chat/ChatForm.js | 13 ++++- src/components/Chat/ChatHeader.js | 6 ++- src/components/Dashboard/Dashboard.js | 69 +++++++++++---------------- src/components/Header/Header.js | 18 +++---- src/components/SearchBar/SearchBar.js | 24 +++++----- src/components/Sidebar/Sidebar.js | 33 ++++++++----- 11 files changed, 103 insertions(+), 117 deletions(-) delete mode 100644 src/APIContext.js delete mode 100644 src/AllUsersContext.js create mode 100644 src/Services/UserContexts.js diff --git a/src/APIContext.js b/src/APIContext.js deleted file mode 100644 index 5b2dcbc..0000000 --- a/src/APIContext.js +++ /dev/null @@ -1,12 +0,0 @@ -import { createContext } from "react"; - -const headerTemplate = { - "access-token": "", - client: "", - uid: "", - expiry: "", -}; - -const APIHeaders = createContext(headerTemplate); - -export default APIHeaders; diff --git a/src/AllUsersContext.js b/src/AllUsersContext.js deleted file mode 100644 index c33a2fe..0000000 --- a/src/AllUsersContext.js +++ /dev/null @@ -1,6 +0,0 @@ - -import { createContext } from "react"; - -const AllUsers = createContext([]); - -export default AllUsers; diff --git a/src/Services/UserContexts.js b/src/Services/UserContexts.js new file mode 100644 index 0000000..5c3f2ea --- /dev/null +++ b/src/Services/UserContexts.js @@ -0,0 +1,7 @@ +import { createContext } from "react"; + +const UserDbContext = createContext(); +const ChannelDbContext = createContext(); +const ChatContext = createContext(); + +export { UserDbContext, ChannelDbContext, ChatContext }; diff --git a/src/components/Chat/Chat.js b/src/components/Chat/Chat.js index 78febee..8c00031 100644 --- a/src/components/Chat/Chat.js +++ b/src/components/Chat/Chat.js @@ -1,15 +1,20 @@ import React, { useState, useEffect } from "react"; import ChatArea from "./ChatArea"; import ChatForm from "./ChatForm"; +import { UserDbContext, ChatContext } from "../../Services/UserContexts"; import "./Chat.css"; import ChatHeader from "./ChatHeader"; +import { useContext } from "react/cjs/react.development"; function Chat(props) { - const { chat, recentDms, userDb, setRecentDms, setUserDb } = props; + const { recentDms, setRecentDms } = props; const [chatWith, setChatWith] = useState(""); const [convo, setConvo] = useState([]); const [chatType, setChatType] = useState("User"); // can be Channel, CAPITALIZE FIRST LETTER! + const [chat, setChat] = useContext(ChatContext); + const [userDb, setUserDb] = useContext(UserDbContext); + useEffect(() => { if (!chat) return; if (chat["owner_id"] !== undefined) { @@ -26,12 +31,7 @@ function Chat(props) { return (
- +
{ setShowAddMembers((prev) => !prev); diff --git a/src/components/Dashboard/Dashboard.js b/src/components/Dashboard/Dashboard.js index d4840a5..9e0636c 100644 --- a/src/components/Dashboard/Dashboard.js +++ b/src/components/Dashboard/Dashboard.js @@ -4,6 +4,11 @@ import Chat from "../Chat/Chat"; import Headers from "../../Helpers/Headers"; import Header from "../Header/Header"; import * as UserAPI from "../../UserAPI"; +import { + ChannelDbContext, + UserDbContext, + ChatContext, +} from "../../Services/UserContexts"; import "./Dashboard.css"; function Dashboard() { @@ -99,55 +104,37 @@ function Dashboard() { if (channelsAreLoaded) n++; if (n === dependencies) setLoadingComplete(true); - - let found = userDb.find((user) => user.uid === headers.uid); - setChat(found); + if (userDb) { + let found = userDb.find((user) => user.uid === headers.uid); + setChat(found); + } }, [usersAreLoaded, recentsAreLoaded, channelsAreLoaded]); - useEffect(() => {}, [filteredRecents, channelDb]); - const displayErrorMsg = () => { return
Please log in again to continue
; }; return (
{isErrorLoading ? displayErrorMsg() : null} - -
-
- {loadingComplete && ( -
- )} -
-
- {loadingComplete && ( - - )} -
-
- {loadingComplete && ( - - )} -
-
+ + + +
+
+ {loadingComplete &&
} +
+
+ {loadingComplete && } +
+
+ {loadingComplete && ( + + )} +
+
+
+
+
); } diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js index 47b0da5..96d40e5 100644 --- a/src/components/Header/Header.js +++ b/src/components/Header/Header.js @@ -4,20 +4,16 @@ import SearchBar from "../SearchBar/SearchBar"; import Logout from "../Logout/Logout"; import { FiClock } from "react-icons/fi"; -function Header({ userDb, channelDb, setChat, setUserDb }) { +function Header() { return (
- - +
); diff --git a/src/components/SearchBar/SearchBar.js b/src/components/SearchBar/SearchBar.js index 773bdac..a101a25 100644 --- a/src/components/SearchBar/SearchBar.js +++ b/src/components/SearchBar/SearchBar.js @@ -1,22 +1,24 @@ -import React, { useState, useCallback } from "react"; +import React, { useState, useCallback, useContext } from "react"; import SearchResult from "./SearchResult"; import Headers from "../../Helpers/Headers"; import { useEffect } from "react/cjs/react.development"; import * as UserAPI from "../../UserAPI"; import { BiSearch } from "react-icons/bi"; import MsgPrompt from "../MsgPrompt/MsgPrompt"; + +import { + ChannelDbContext, + UserDbContext, + ChatContext, +} from "../../Services/UserContexts"; import "./SearchBar.css"; function SearchBar(props) { - const { - placeholder, - setChatWith, - userDb, - setUserDb, - searchBarFor, - onAddMember, - setNewMember, - } = props; + const { placeholder, searchBarFor, onAddMember, setNewMember } = props; + + const [userDb, setUserDb] = useContext(UserDbContext); + const [chat, setChat] = useContext(ChatContext); + const [channelDb, setChannelDb] = useContext(ChannelDbContext); const [searchEntry, setSearchEntry] = useState(""); const [header] = useState(Headers); const [searchSuggestions, setSearchSuggestions] = useState([]); @@ -71,7 +73,7 @@ function SearchBar(props) { } else { setResponseMsg(""); setErrors(false); - setChatWith(found); + setChat(found); setIsActive(false); } }; diff --git a/src/components/Sidebar/Sidebar.js b/src/components/Sidebar/Sidebar.js index 89d2db7..e605d72 100644 --- a/src/components/Sidebar/Sidebar.js +++ b/src/components/Sidebar/Sidebar.js @@ -16,12 +16,17 @@ import { RiArrowRightSFill, RiAddFill, } from "react-icons/ri"; +import { ChannelDbContext, ChatContext } from "../../Services/UserContexts"; import SidebarOptions from "./SidebarOptions"; import DirectMessages from "../DirectMessages/DirectMessages"; -import { useEffect } from "react/cjs/react.development"; +import { useContext, useEffect } from "react/cjs/react.development"; function Sidebar(props) { - const { recentDms, channelDb, setChat, chat } = props; + const { recentDms } = props; + + const [chat, setChat] = useContext(ChatContext); + const [channelDb, setChannelDb] = useContext(ChannelDbContext); + const [setUserChannels] = useState([]); const [setUserName] = useState([]); const [dmsExpanded, setDmsExpanded] = useState(true); @@ -65,7 +70,7 @@ function Sidebar(props) { setChat(selectedChannel); }} className={"channel-name " + (isActive ? "isActiveChat" : "")} - key={channel.id} + key={channel.name} >   {channel.name}
@@ -88,16 +93,18 @@ function Sidebar(props) {
Slack Clone{" "} - +
+ +

From 2f4e8038492e2838e0d9053e224d56e26f1d6c58 Mon Sep 17 00:00:00 2001 From: ccases Date: Wed, 20 Oct 2021 15:04:35 +0800 Subject: [PATCH 2/3] new message working, but there is an initial lag --- src/components/Chat/Chat.js | 33 ++++++------ src/components/Chat/ChatArea.js | 39 ++++++++------- src/components/Chat/ChatForm.js | 8 ++- src/components/Chat/ChatHeader.js | 6 ++- src/components/Chat/NewChat.css | 29 +++++++++++ src/components/Chat/NewChat.js | 72 +++++++++++++++++++++++++++ src/components/SearchBar/SearchBar.js | 29 ++++++++--- src/components/Sidebar/Sidebar.css | 9 ++-- src/components/Sidebar/Sidebar.js | 7 ++- 9 files changed, 184 insertions(+), 48 deletions(-) create mode 100644 src/components/Chat/NewChat.css create mode 100644 src/components/Chat/NewChat.js diff --git a/src/components/Chat/Chat.js b/src/components/Chat/Chat.js index 8c00031..7654fc2 100644 --- a/src/components/Chat/Chat.js +++ b/src/components/Chat/Chat.js @@ -5,13 +5,13 @@ import { UserDbContext, ChatContext } from "../../Services/UserContexts"; import "./Chat.css"; import ChatHeader from "./ChatHeader"; import { useContext } from "react/cjs/react.development"; +import NewChat from "./NewChat"; function Chat(props) { const { recentDms, setRecentDms } = props; - const [chatWith, setChatWith] = useState(""); const [convo, setConvo] = useState([]); const [chatType, setChatType] = useState("User"); // can be Channel, CAPITALIZE FIRST LETTER! - + const [newChat, setNewChat] = useState(""); const [chat, setChat] = useContext(ChatContext); const [userDb, setUserDb] = useContext(UserDbContext); @@ -20,11 +20,9 @@ function Chat(props) { if (chat["owner_id"] !== undefined) { // if object passed has owner id, set chat type to channel! setChatType("Channel"); - setChatWith(chat); } else if (chat["email"] !== undefined) { // if chat has property: email, single user lang siya setChatType("User"); - setChatWith(chat); } }, [chat]); @@ -33,20 +31,23 @@ function Chat(props) {
- + {!chat ? ( + + ) : ( + + )}

diff --git a/src/components/Chat/ChatArea.js b/src/components/Chat/ChatArea.js index a653ecf..3aad238 100644 --- a/src/components/Chat/ChatArea.js +++ b/src/components/Chat/ChatArea.js @@ -18,28 +18,28 @@ function ChatArea(props) { if (header["access-token"] === undefined || userId === undefined) { return; } - setConvo([]); // reset all messages before going into the next one - retrieveMsgs(userId, chatType, false); - }, [userId, header, setConvo, chatType]); - useEffect(() => { - if (header["access-token"] === undefined || userId === undefined) { - return; + let type = ""; + if (!chat) return; + if (chat["owner_id"] !== undefined) { + // if object passed has owner id, set chat type to channel! + type = "Channel"; + } else if (chat["email"] !== undefined) { + // if chat has property: email, single user lang siya + type = "User"; } setConvo([]); // reset all messages before going into the next one - retrieveMsgs(userId, chatType, false); - - let clen = convo.length; - if (clen > 1) { - setPrevLen(clen); - } - }, []); + if (userId === undefined) console.log("undefined ID at 31"); + retrieveMsgs(userId, type, false); + }, [userId, header, setConvo, chat]); useEffect(() => { - let clen = convo.length; - if (clen > 1) { - if (prevLen !== clen) { - scrollToBottom(); - setPrevLen(clen); + if (convo) { + let clen = convo.length; + if (clen > 1) { + if (prevLen !== clen) { + scrollToBottom(); + setPrevLen(clen); + } } } }, [chat, convo]); @@ -51,6 +51,7 @@ function ChatArea(props) { } const interval = setInterval(() => { + if (userId === undefined) console.log("undefined ID at 31"); retrieveMsgs(userId, chatType, true); UserAPI.getRecent(header) .then((res) => { @@ -105,6 +106,7 @@ function ChatArea(props) { }; const retrieveMsgs = (userId, chatType, isChecking = false) => { + if (!userId || !chat) return; UserAPI.getMsgs(header, userId, chatType).then((res) => { let len = res.data.data.length; let convoLen = convo.length; @@ -154,6 +156,7 @@ function ChatArea(props) { if (chatType === "Channel" && chat.owner_id) { channelOwner = userDb.find((user) => user.id === chat.owner_id).uid; } + if (chat === undefined) return
; if (userEmail === header.uid) return (
diff --git a/src/components/Chat/ChatForm.js b/src/components/Chat/ChatForm.js index afc1389..25c9273 100644 --- a/src/components/Chat/ChatForm.js +++ b/src/components/Chat/ChatForm.js @@ -30,7 +30,7 @@ import { } from "react-icons/bs"; function ChatForm(props) { - const { userId, setConvo, chatType } = props; + const { userId, setConvo, chatType, newChat } = props; const [chat, setChat] = useContext(ChatContext); const [channelDb, setChannelDb] = useContext(ChannelDbContext); @@ -65,6 +65,12 @@ function ChatForm(props) { let input = chatInput; if (chatInput == null || input.trim().length === 0) return; if (header["access-token"] === undefined) return; + if (!chat) { + raw.receiver_id = newChat.id; + if (!newChat) alert("Enter a valid receiver first!"); + setChat(newChat); + setConvo([]); + } UserAPI.sendMsg(header, raw) .then((res) => { UserAPI.getMsgs(header, userId, chatType) diff --git a/src/components/Chat/ChatHeader.js b/src/components/Chat/ChatHeader.js index ebaa558..282f3e0 100644 --- a/src/components/Chat/ChatHeader.js +++ b/src/components/Chat/ChatHeader.js @@ -63,7 +63,11 @@ function ChatHeader({ chat, chatType }) { />
- {chatType === "User" ? ( + {!chat ? ( +
+

New Message

+
+ ) : chatType === "User" ? (

{chat.uid}

diff --git a/src/components/Chat/NewChat.css b/src/components/Chat/NewChat.css new file mode 100644 index 0000000..434c530 --- /dev/null +++ b/src/components/Chat/NewChat.css @@ -0,0 +1,29 @@ +.newchat-input-search { + font-size: 1em; + border: none; + width: 100%; + padding: 10px; + outline: none; + color: black; + background-color: white; +} +.newchat-input-search:focus { + color: black !important; +} +.newchat-input-container { + display: flex; + color: rgba(0, 0, 0, 0.4); + align-items: center; + padding: 10px 20px; + width: 100%; + border-bottom: 1px solid rgba(0, 0, 0, 0.3); + box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.4); + position: relative; +} +.newchat-suggestions-wrapper { + position: absolute; + top: calc(1em + 33px); + left: 60px; + overflow-y: scroll; + max-height: 400px; +} diff --git a/src/components/Chat/NewChat.js b/src/components/Chat/NewChat.js new file mode 100644 index 0000000..fd46f09 --- /dev/null +++ b/src/components/Chat/NewChat.js @@ -0,0 +1,72 @@ +import React, { useState, useContext, useEffect, useCallback } from "react"; +import { ChannelDbContext, UserDbContext } from "../../Services/UserContexts"; +import SearchResult from "../SearchBar/SearchResult"; +import "./NewChat.css"; + +function NewChat(props) { + const { setNewChat } = props; + const [searchEntry, setSearchEntry] = useState(""); + const [userDb, setUserDb] = useContext(UserDbContext); + const [channelDb, channelDbContext] = useContext(ChannelDbContext); + const [isActive, setIsActive] = useState(false); + const [searchSuggestions, setSearchSuggestions] = useState([]); + + useEffect(() => { + setSearchSuggestions( + userDb.filter((user) => user.uid.includes(searchEntry)) + ); + }, [userDb, searchEntry]); + useEffect(() => { + if (searchSuggestions.length === 1) { + setNewChat(searchSuggestions[0]); + } + }, [searchSuggestions]); + + const handleClick = useCallback( + (e) => { + let cl = e.target.classList; + if (cl.contains("result")) { + setIsActive(false); + } else if (!cl.contains("input-search")) { + setIsActive(false); + } + }, + [setIsActive] + ); + useEffect(() => { + document.addEventListener("click", handleClick); + return () => document.removeEventListener("click", handleClick); + }, [handleClick]); + const Suggestions = searchSuggestions + ? searchSuggestions.map((user) => { + return ( + + ); + }) + : null; + return ( +
+
+ To:{" "} + { + setSearchEntry(e.target.value); + }} + placeholder="somebody@example.com" + onFocus={() => setIsActive(true)} + /> +
+ {isActive && Suggestions} +
+
+
+ ); +} + +export default NewChat; diff --git a/src/components/SearchBar/SearchBar.js b/src/components/SearchBar/SearchBar.js index a101a25..98a3093 100644 --- a/src/components/SearchBar/SearchBar.js +++ b/src/components/SearchBar/SearchBar.js @@ -12,6 +12,7 @@ import { ChatContext, } from "../../Services/UserContexts"; import "./SearchBar.css"; +import { IoFastFood } from "react-icons/io5"; function SearchBar(props) { const { placeholder, searchBarFor, onAddMember, setNewMember } = props; @@ -50,16 +51,19 @@ function SearchBar(props) { return () => document.removeEventListener("click", handleClick); }, [handleClick]); + const filterCallback = (chatObj) => { + if (chatObj.uid) return chatObj.uid.includes(searchEntry); + else if (chatObj.name) return chatObj.name.includes(searchEntry); + }; useEffect(() => { if (header["access-token"] === undefined) return; if (userDb[0] === undefined) { alert("still loading db"); return; } - setSearchSuggestions( - userDb.filter((user) => user.uid.includes(searchEntry)) - ); - }, [searchEntry, userDb, header]); + let arr = userDb.concat(channelDb); + setSearchSuggestions(arr.filter(filterCallback)); + }, [searchEntry, userDb, header, channelDb]); const submitHandler = (e) => { e.preventDefault(); @@ -89,15 +93,24 @@ function SearchBar(props) { }; let suggestions = searchSuggestions ? searchSuggestions.map((user) => { - return ( + if (user.uid) + return ( + + ); + else if (user.name) - ); + />; }) : null; return ( diff --git a/src/components/Sidebar/Sidebar.css b/src/components/Sidebar/Sidebar.css index 3669ad5..18db85c 100644 --- a/src/components/Sidebar/Sidebar.css +++ b/src/components/Sidebar/Sidebar.css @@ -69,7 +69,10 @@ opacity: 0.9; background-color: #340e36; } - +.sidebar-newmsg { + cursor: pointer; + border-radius: 50%; +} .user-name { padding-top: 3px; } @@ -102,7 +105,7 @@ pointer-events: none; } -.disclaimer{ +.disclaimer { margin-right: 20px; padding: 8px 0; font-size: 12px; @@ -113,4 +116,4 @@ bottom: 0; background-color: #4a154b; width: calc(var(--sidebar-width)); -} \ No newline at end of file +} diff --git a/src/components/Sidebar/Sidebar.js b/src/components/Sidebar/Sidebar.js index e605d72..348dc1c 100644 --- a/src/components/Sidebar/Sidebar.js +++ b/src/components/Sidebar/Sidebar.js @@ -93,7 +93,12 @@ function Sidebar(props) {
Slack Clone{" "} -
+
{ + setChat(""); + }} + > Date: Wed, 20 Oct 2021 15:08:05 +0800 Subject: [PATCH 3/3] spacing changes --- src/components/Chat/ChatArea.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Chat/ChatArea.js b/src/components/Chat/ChatArea.js index 3aad238..5236e3b 100644 --- a/src/components/Chat/ChatArea.js +++ b/src/components/Chat/ChatArea.js @@ -51,8 +51,6 @@ function ChatArea(props) { } const interval = setInterval(() => { - if (userId === undefined) console.log("undefined ID at 31"); - retrieveMsgs(userId, chatType, true); UserAPI.getRecent(header) .then((res) => { setRecentDms(res.data.data); @@ -60,6 +58,8 @@ function ChatArea(props) { .catch((e) => { console.log(e); }); + if (userId === undefined) console.log("undefined ID at 61"); + retrieveMsgs(userId, chatType, true); }, 3000); return () => clearInterval(interval);