feat: users online status
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
|
const initialState = [];
|
||||||
|
const contactsSlice = createSlice({
|
||||||
|
name: `contacts`,
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setContacts(state, action) {
|
||||||
|
console.log("set Contacts store", state);
|
||||||
|
const contacts = action.payload || [];
|
||||||
|
return contacts;
|
||||||
|
},
|
||||||
|
updateUsersStatus(state, action) {
|
||||||
|
const onlines = action.payload;
|
||||||
|
onlines.forEach((item) => {
|
||||||
|
const { uid, online = false } = item;
|
||||||
|
const curr = state.find(({ uid: id }) => id == uid);
|
||||||
|
console.log("update user status", curr, online);
|
||||||
|
if (curr) {
|
||||||
|
curr.online = online;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export const { setContacts, updateUsersStatus } = contactsSlice.actions;
|
||||||
|
export default contactsSlice.reducer;
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
import authDataReducer from "./slices/auth.data";
|
import authDataReducer from "./slices/auth.data";
|
||||||
import uiReducer from "./slices/ui";
|
import uiReducer from "./slices/ui";
|
||||||
import channelsReducer from "./slices/channels";
|
import channelsReducer from "./slices/channels";
|
||||||
|
import contactsReducer from "./slices/contacts";
|
||||||
import channelMsgReducer from "./slices/message.channel";
|
import channelMsgReducer from "./slices/message.channel";
|
||||||
import userMsgReducer from "./slices/message.user";
|
import userMsgReducer from "./slices/message.user";
|
||||||
import { authApi } from "./services/auth";
|
import { authApi } from "./services/auth";
|
||||||
@@ -28,6 +29,7 @@ const persistedReducer = persistReducer(
|
|||||||
persistConfig,
|
persistConfig,
|
||||||
combineReducers({
|
combineReducers({
|
||||||
ui: uiReducer,
|
ui: uiReducer,
|
||||||
|
contacts: contactsReducer,
|
||||||
channels: channelsReducer,
|
channels: channelsReducer,
|
||||||
userMsg: userMsgReducer,
|
userMsg: userMsgReducer,
|
||||||
channelMsg: channelMsgReducer,
|
channelMsg: channelMsgReducer,
|
||||||
@@ -53,4 +55,27 @@ const store = configureStore({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
setupListeners(store.dispatch);
|
setupListeners(store.dispatch);
|
||||||
|
// export function swapToUserStore(userId) {
|
||||||
|
// console.log({ userId });
|
||||||
|
// const newConfig = {
|
||||||
|
// ...persistConfig,
|
||||||
|
// keyPrefix: userId,
|
||||||
|
// };
|
||||||
|
// store.replaceReducer(
|
||||||
|
// persistReducer(
|
||||||
|
// newConfig,
|
||||||
|
// combineReducers({
|
||||||
|
// ui: uiReducer,
|
||||||
|
// channels: channelsReducer,
|
||||||
|
// userMsg: userMsgReducer,
|
||||||
|
// channelMsg: channelMsgReducer,
|
||||||
|
// authData: authDataReducer,
|
||||||
|
// [authApi.reducerPath]: authApi.reducer,
|
||||||
|
// [contactApi.reducerPath]: contactApi.reducer,
|
||||||
|
// [channelApi.reducerPath]: channelApi.reducer,
|
||||||
|
// [serverApi.reducerPath]: serverApi.reducer,
|
||||||
|
// })
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
// }
|
||||||
export default store;
|
export default store;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
addChannel,
|
addChannel,
|
||||||
deleteChannel,
|
deleteChannel,
|
||||||
} from "../../app/slices/channels";
|
} from "../../app/slices/channels";
|
||||||
|
import { updateUsersStatus } from "../../app/slices/contacts";
|
||||||
import {
|
import {
|
||||||
clearAuthData,
|
clearAuthData,
|
||||||
setUsersVersion,
|
setUsersVersion,
|
||||||
@@ -71,6 +72,14 @@ const NotificationHub = ({ token, usersVersion = 0, afterMid = 0 }) => {
|
|||||||
dispatch(setUsersVersion({ version }));
|
dispatch(setUsersVersion({ version }));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "users_state":
|
||||||
|
case "users_state_changed":
|
||||||
|
{
|
||||||
|
let { type, ...rest } = data;
|
||||||
|
const onlines = type == "users_state_changed" ? [rest] : rest.users;
|
||||||
|
dispatch(updateUsersStatus(onlines));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "kick":
|
case "kick":
|
||||||
{
|
{
|
||||||
console.log("kicked");
|
console.log("kicked");
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useGetContactsQuery } from "../../app/services/contact";
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
export default function useFilteredUsers() {
|
export default function useFilteredUsers() {
|
||||||
const [input, setInput] = useState("");
|
const [input, setInput] = useState("");
|
||||||
const { data: contacts } = useGetContactsQuery();
|
const contacts = useSelector((store) => store.contacts);
|
||||||
const [filteredUsers, setFilteredUsers] = useState(contacts);
|
const [filteredUsers, setFilteredUsers] = useState(contacts);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!input) {
|
if (!input) {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
clearChannelMsgUnread,
|
clearChannelMsgUnread,
|
||||||
setLastAccessTime,
|
setLastAccessTime,
|
||||||
} from "../../../app/slices/message.channel";
|
} from "../../../app/slices/message.channel";
|
||||||
import { useGetContactsQuery } from "../../../app/services/contact";
|
|
||||||
import Contact from "../../../common/component/Contact";
|
import Contact from "../../../common/component/Contact";
|
||||||
import Layout from "../Layout";
|
import Layout from "../Layout";
|
||||||
import {
|
import {
|
||||||
@@ -29,10 +28,9 @@ export default function ChannelChat({
|
|||||||
// const containerRef = useRef(null);
|
// const containerRef = useRef(null);
|
||||||
const [dragFiles, setDragFiles] = useState([]);
|
const [dragFiles, setDragFiles] = useState([]);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const msgs = useSelector((store) => {
|
const { msgs, users } = useSelector((store) => {
|
||||||
return store.channelMsg[cid] || {};
|
return { msgs: store.channelMsg[cid] || {}, users: store.contacts };
|
||||||
});
|
});
|
||||||
const { data: users } = useGetContactsQuery();
|
|
||||||
const handleClearUnreads = () => {
|
const handleClearUnreads = () => {
|
||||||
dispatch(clearChannelMsgUnread(cid));
|
dispatch(clearChannelMsgUnread(cid));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { useSelector } from "react-redux";
|
|||||||
import Message from "../../../common/component/Message";
|
import Message from "../../../common/component/Message";
|
||||||
import Send from "../../../common/component/Send";
|
import Send from "../../../common/component/Send";
|
||||||
import Contact from "../../../common/component/Contact";
|
import Contact from "../../../common/component/Contact";
|
||||||
import { useGetContactsQuery } from "../../../app/services/contact";
|
|
||||||
import Layout from "../Layout";
|
import Layout from "../Layout";
|
||||||
|
|
||||||
import { StyledHeader, StyledDMChat } from "./styled";
|
import { StyledHeader, StyledDMChat } from "./styled";
|
||||||
@@ -11,10 +10,10 @@ import { StyledHeader, StyledDMChat } from "./styled";
|
|||||||
export default function DMChat({ uid = "", dropFiles = [] }) {
|
export default function DMChat({ uid = "", dropFiles = [] }) {
|
||||||
console.log("dm files", dropFiles);
|
console.log("dm files", dropFiles);
|
||||||
const [dragFiles, setDragFiles] = useState([]);
|
const [dragFiles, setDragFiles] = useState([]);
|
||||||
|
const contacts = useSelector((store) => store.contacts);
|
||||||
const msgs = useSelector((store) => {
|
const msgs = useSelector((store) => {
|
||||||
return store.userMsg[uid] || {};
|
return store.userMsg[uid] || {};
|
||||||
});
|
});
|
||||||
const { data: contacts } = useGetContactsQuery();
|
|
||||||
const [currUser, setCurrUser] = useState(null);
|
const [currUser, setCurrUser] = useState(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log({ uid });
|
console.log({ uid });
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { useSelector } from "react-redux";
|
|||||||
import { MdAdd } from "react-icons/md";
|
import { MdAdd } from "react-icons/md";
|
||||||
import { AiOutlineCaretDown } from "react-icons/ai";
|
import { AiOutlineCaretDown } from "react-icons/ai";
|
||||||
|
|
||||||
import { useGetContactsQuery } from "../../app/services/contact";
|
|
||||||
import StyledWrapper from "./styled";
|
import StyledWrapper from "./styled";
|
||||||
import Search from "../../common/component/Search";
|
import Search from "../../common/component/Search";
|
||||||
import Avatar from "../../common/component/Avatar";
|
import Avatar from "../../common/component/Avatar";
|
||||||
@@ -31,7 +30,7 @@ export default function ChatPage() {
|
|||||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||||
const [contactsModalVisible, setContactsModalVisible] = useState(false);
|
const [contactsModalVisible, setContactsModalVisible] = useState(false);
|
||||||
const { channel_id, user_id } = useParams();
|
const { channel_id, user_id } = useParams();
|
||||||
const { data: contacts } = useGetContactsQuery();
|
const contacts = useSelector((store) => store.contacts);
|
||||||
const toggleContactsModalVisible = () => {
|
const toggleContactsModalVisible = () => {
|
||||||
setContactsModalVisible((prev) => !prev);
|
setContactsModalVisible((prev) => !prev);
|
||||||
};
|
};
|
||||||
@@ -121,7 +120,7 @@ export default function ChatPage() {
|
|||||||
<Avatar
|
<Avatar
|
||||||
className="avatar"
|
className="avatar"
|
||||||
url={tmpSessionUser.avatar}
|
url={tmpSessionUser.avatar}
|
||||||
id={user_id}
|
name={tmpSessionUser.name}
|
||||||
/>
|
/>
|
||||||
<div className="details">
|
<div className="details">
|
||||||
<div className="up">
|
<div className="up">
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
// import React from "react";
|
// import React from "react";
|
||||||
// import toast from "react-hot-toast";
|
// import toast from "react-hot-toast";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
import { BsChatText } from "react-icons/bs";
|
import { BsChatText } from "react-icons/bs";
|
||||||
import { RiUserAddLine } from "react-icons/ri";
|
import { RiUserAddLine } from "react-icons/ri";
|
||||||
import { IoShareOutline } from "react-icons/io5";
|
import { IoShareOutline } from "react-icons/io5";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { useGetContactsQuery } from "../../app/services/contact";
|
|
||||||
|
|
||||||
import Avatar from "../../common/component/Avatar";
|
import Avatar from "../../common/component/Avatar";
|
||||||
|
|
||||||
@@ -52,7 +51,7 @@ const StyledWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export default function Profile({ uid = null }) {
|
export default function Profile({ uid = null }) {
|
||||||
const { data: contacts } = useGetContactsQuery();
|
const contacts = useSelector((store) => store.contacts);
|
||||||
const [profile, setProfile] = useState(null);
|
const [profile, setProfile] = useState(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (contacts && contacts) {
|
if (contacts && contacts) {
|
||||||
@@ -66,7 +65,7 @@ export default function Profile({ uid = null }) {
|
|||||||
const { name, email, avatar } = profile;
|
const { name, email, avatar } = profile;
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<Avatar className="avatar" url={avatar} id={uid} name={name} />
|
<Avatar className="avatar" url={avatar} name={name} />
|
||||||
<h2 className="name">{name}</h2>
|
<h2 className="name">{name}</h2>
|
||||||
<span className="email">{email}</span>
|
<span className="email">{email}</span>
|
||||||
<ul className="icons">
|
<ul className="icons">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// import { useState, useEffect } from "react";
|
// import { useState, useEffect } from "react";
|
||||||
import { NavLink, useParams } from "react-router-dom";
|
import { NavLink, useParams } from "react-router-dom";
|
||||||
import { useGetContactsQuery } from "../../app/services/contact";
|
import { useSelector } from "react-redux";
|
||||||
import Search from "../../common/component/Search";
|
import Search from "../../common/component/Search";
|
||||||
import Contact from "../../common/component/Contact";
|
import Contact from "../../common/component/Contact";
|
||||||
import CurrentUser from "../../common/component/CurrentUser";
|
import CurrentUser from "../../common/component/CurrentUser";
|
||||||
@@ -10,7 +10,7 @@ import StyledWrapper from "./styled";
|
|||||||
|
|
||||||
export default function ContactsPage() {
|
export default function ContactsPage() {
|
||||||
const { user_id } = useParams();
|
const { user_id } = useParams();
|
||||||
const { data: contacts } = useGetContactsQuery();
|
const contacts = useSelector((store) => store.contacts);
|
||||||
|
|
||||||
console.log({ contacts, user_id });
|
console.log({ contacts, user_id });
|
||||||
if (!contacts) return null;
|
if (!contacts) return null;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useSelector, useDispatch } from "react-redux";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useGetContactsQuery } from "../../app/services/contact";
|
import { useGetContactsQuery } from "../../app/services/contact";
|
||||||
import { clearAuthData } from "../../app/slices/auth.data";
|
import { clearAuthData } from "../../app/slices/auth.data";
|
||||||
|
import { setContacts } from "../../app/slices/contacts";
|
||||||
|
|
||||||
// import { useGetChannelsQuery } from "../../app/services/channel";
|
// import { useGetChannelsQuery } from "../../app/services/channel";
|
||||||
import { useGetServerQuery } from "../../app/services/server";
|
import { useGetServerQuery } from "../../app/services/server";
|
||||||
@@ -41,8 +42,13 @@ export default function usePreload() {
|
|||||||
if (!matchedUser) {
|
if (!matchedUser) {
|
||||||
dispatch(clearAuthData());
|
dispatch(clearAuthData());
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
|
} else {
|
||||||
|
const markedContacts = contacts.map((u) => {
|
||||||
|
return u.uid == matchedUser.uid ? { ...u, online: true } : u;
|
||||||
|
});
|
||||||
|
dispatch(setContacts(markedContacts));
|
||||||
|
setChecked(true);
|
||||||
}
|
}
|
||||||
setChecked(true);
|
|
||||||
}
|
}
|
||||||
}, [contacts]);
|
}, [contacts]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user