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 uiReducer from "./slices/ui";
|
||||
import channelsReducer from "./slices/channels";
|
||||
import contactsReducer from "./slices/contacts";
|
||||
import channelMsgReducer from "./slices/message.channel";
|
||||
import userMsgReducer from "./slices/message.user";
|
||||
import { authApi } from "./services/auth";
|
||||
@@ -28,6 +29,7 @@ const persistedReducer = persistReducer(
|
||||
persistConfig,
|
||||
combineReducers({
|
||||
ui: uiReducer,
|
||||
contacts: contactsReducer,
|
||||
channels: channelsReducer,
|
||||
userMsg: userMsgReducer,
|
||||
channelMsg: channelMsgReducer,
|
||||
@@ -53,4 +55,27 @@ const store = configureStore({
|
||||
),
|
||||
});
|
||||
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;
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
addChannel,
|
||||
deleteChannel,
|
||||
} from "../../app/slices/channels";
|
||||
import { updateUsersStatus } from "../../app/slices/contacts";
|
||||
import {
|
||||
clearAuthData,
|
||||
setUsersVersion,
|
||||
@@ -71,6 +72,14 @@ const NotificationHub = ({ token, usersVersion = 0, afterMid = 0 }) => {
|
||||
dispatch(setUsersVersion({ version }));
|
||||
}
|
||||
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":
|
||||
{
|
||||
console.log("kicked");
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useGetContactsQuery } from "../../app/services/contact";
|
||||
|
||||
import { useSelector } from "react-redux";
|
||||
export default function useFilteredUsers() {
|
||||
const [input, setInput] = useState("");
|
||||
const { data: contacts } = useGetContactsQuery();
|
||||
const contacts = useSelector((store) => store.contacts);
|
||||
const [filteredUsers, setFilteredUsers] = useState(contacts);
|
||||
useEffect(() => {
|
||||
if (!input) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
clearChannelMsgUnread,
|
||||
setLastAccessTime,
|
||||
} from "../../../app/slices/message.channel";
|
||||
import { useGetContactsQuery } from "../../../app/services/contact";
|
||||
import Contact from "../../../common/component/Contact";
|
||||
import Layout from "../Layout";
|
||||
import {
|
||||
@@ -29,10 +28,9 @@ export default function ChannelChat({
|
||||
// const containerRef = useRef(null);
|
||||
const [dragFiles, setDragFiles] = useState([]);
|
||||
const dispatch = useDispatch();
|
||||
const msgs = useSelector((store) => {
|
||||
return store.channelMsg[cid] || {};
|
||||
const { msgs, users } = useSelector((store) => {
|
||||
return { msgs: store.channelMsg[cid] || {}, users: store.contacts };
|
||||
});
|
||||
const { data: users } = useGetContactsQuery();
|
||||
const handleClearUnreads = () => {
|
||||
dispatch(clearChannelMsgUnread(cid));
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useSelector } from "react-redux";
|
||||
import Message from "../../../common/component/Message";
|
||||
import Send from "../../../common/component/Send";
|
||||
import Contact from "../../../common/component/Contact";
|
||||
import { useGetContactsQuery } from "../../../app/services/contact";
|
||||
import Layout from "../Layout";
|
||||
|
||||
import { StyledHeader, StyledDMChat } from "./styled";
|
||||
@@ -11,10 +10,10 @@ import { StyledHeader, StyledDMChat } from "./styled";
|
||||
export default function DMChat({ uid = "", dropFiles = [] }) {
|
||||
console.log("dm files", dropFiles);
|
||||
const [dragFiles, setDragFiles] = useState([]);
|
||||
const contacts = useSelector((store) => store.contacts);
|
||||
const msgs = useSelector((store) => {
|
||||
return store.userMsg[uid] || {};
|
||||
});
|
||||
const { data: contacts } = useGetContactsQuery();
|
||||
const [currUser, setCurrUser] = useState(null);
|
||||
useEffect(() => {
|
||||
console.log({ uid });
|
||||
|
||||
@@ -6,7 +6,6 @@ import { useSelector } from "react-redux";
|
||||
import { MdAdd } from "react-icons/md";
|
||||
import { AiOutlineCaretDown } from "react-icons/ai";
|
||||
|
||||
import { useGetContactsQuery } from "../../app/services/contact";
|
||||
import StyledWrapper from "./styled";
|
||||
import Search from "../../common/component/Search";
|
||||
import Avatar from "../../common/component/Avatar";
|
||||
@@ -31,7 +30,7 @@ export default function ChatPage() {
|
||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||
const [contactsModalVisible, setContactsModalVisible] = useState(false);
|
||||
const { channel_id, user_id } = useParams();
|
||||
const { data: contacts } = useGetContactsQuery();
|
||||
const contacts = useSelector((store) => store.contacts);
|
||||
const toggleContactsModalVisible = () => {
|
||||
setContactsModalVisible((prev) => !prev);
|
||||
};
|
||||
@@ -121,7 +120,7 @@ export default function ChatPage() {
|
||||
<Avatar
|
||||
className="avatar"
|
||||
url={tmpSessionUser.avatar}
|
||||
id={user_id}
|
||||
name={tmpSessionUser.name}
|
||||
/>
|
||||
<div className="details">
|
||||
<div className="up">
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// import React from "react";
|
||||
// import toast from "react-hot-toast";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
import { useSelector } from "react-redux";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import { BsChatText } from "react-icons/bs";
|
||||
import { RiUserAddLine } from "react-icons/ri";
|
||||
import { IoShareOutline } from "react-icons/io5";
|
||||
import styled from "styled-components";
|
||||
import { useGetContactsQuery } from "../../app/services/contact";
|
||||
|
||||
import Avatar from "../../common/component/Avatar";
|
||||
|
||||
@@ -52,7 +51,7 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
export default function Profile({ uid = null }) {
|
||||
const { data: contacts } = useGetContactsQuery();
|
||||
const contacts = useSelector((store) => store.contacts);
|
||||
const [profile, setProfile] = useState(null);
|
||||
useEffect(() => {
|
||||
if (contacts && contacts) {
|
||||
@@ -66,7 +65,7 @@ export default function Profile({ uid = null }) {
|
||||
const { name, email, avatar } = profile;
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<Avatar className="avatar" url={avatar} id={uid} name={name} />
|
||||
<Avatar className="avatar" url={avatar} name={name} />
|
||||
<h2 className="name">{name}</h2>
|
||||
<span className="email">{email}</span>
|
||||
<ul className="icons">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// import { useState, useEffect } from "react";
|
||||
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 Contact from "../../common/component/Contact";
|
||||
import CurrentUser from "../../common/component/CurrentUser";
|
||||
@@ -10,7 +10,7 @@ import StyledWrapper from "./styled";
|
||||
|
||||
export default function ContactsPage() {
|
||||
const { user_id } = useParams();
|
||||
const { data: contacts } = useGetContactsQuery();
|
||||
const contacts = useSelector((store) => store.contacts);
|
||||
|
||||
console.log({ contacts, user_id });
|
||||
if (!contacts) return null;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useSelector, useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useGetContactsQuery } from "../../app/services/contact";
|
||||
import { clearAuthData } from "../../app/slices/auth.data";
|
||||
import { setContacts } from "../../app/slices/contacts";
|
||||
|
||||
// import { useGetChannelsQuery } from "../../app/services/channel";
|
||||
import { useGetServerQuery } from "../../app/services/server";
|
||||
@@ -41,8 +42,13 @@ export default function usePreload() {
|
||||
if (!matchedUser) {
|
||||
dispatch(clearAuthData());
|
||||
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]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user