123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- import React, { useEffect } from "react";
- import { gql } from "../helpers";
- import { actionChatsCount } from "../actions";
- import { createStore, combineReducers, applyMiddleware } from "redux";
- import thunk from "redux-thunk";
- import {
- actionOnMsg,
- actionOnChat,
- actionOnChatLeft,
- actionFullLogout,
- actionFullMsgsByChat
- } from "../actions";
- import io from "socket.io-client";
- import { actionFindUsers } from "../actions";
- export function promiseReducer(state, { type, status, payload, error, name }) {
- if (!state) {
- return {};
- }
- if (type === "PROMISE") {
- return {
- ...state,
- [name]: {
- status: status,
- payload:
- (status === "PENDING" &&
- state[name] &&
- state[name].payload) ||
- payload,
- error: error,
- },
- };
- //для пользы при работе с промисами надо бы пока PENDING не делать payload undefined
- //при наличии старого payload
- }
- return state;
- }
- const actionPending = (name) => ({ type: "PROMISE", status: "PENDING", name });
- const actionResolved = (name, payload) => ({
- type: "PROMISE",
- status: "RESOLVED",
- name,
- payload,
- });
- const actionRejected = (name, error) => ({
- type: "PROMISE",
- status: "REJECTED",
- name,
- error,
- });
- export const actionPromise = (name, promise) => async (dispatch) => {
- dispatch(actionPending(name));
- try {
- let data = await promise;
- dispatch(actionResolved(name, data));
- return data;
- } catch (error) {
- dispatch(actionRejected(name, error));
- }
- };
- // ------------------
- function jwtDecode(token) {
- try {
- const decoded = JSON.parse(atob(token.split(".")[1]));
- return decoded;
- } catch (err) {
- console.log(err);
- }
- }
- export function authReducer(state, { type, token }) {
- if (!state) {
- if (localStorage.authToken) {
- token = localStorage.authToken;
- type = "AUTH_LOGIN";
- } else {
- return {};
- }
- }
- if (type === "AUTH_LOGIN") {
- const payload = jwtDecode(token);
- if (typeof payload === "object") {
- localStorage.authToken = token;
- return {
- ...state,
- token,
- payload,
- };
- } else {
- console.error(
- "Токен " + localStorage.authToken + " неверный и был удален"
- );
- delete localStorage.authToken;
- return state || {};
- }
- }
- if (type === "AUTH_LOGOUT") {
- delete localStorage.authToken;
- return {};
- }
- return state;
- }
- export const actionAuthLogin = (token) => ({ type: "AUTH_LOGIN", token });
- export const actionAuthLogout = () => ({ type: "AUTH_LOGOUT" });
- // -----------------------------------
- export function chatsReducer(state, { type, payload }) {
- if (!state) {
- return {};
- }
- function refreshMsgs(newMsgs, oldMsgs) {
- const msgState = [...oldMsgs];
- for (const newMsg of newMsgs || []) {
- const currIndex = msgState.findIndex(
- (oldMsg) => oldMsg._id === newMsg._id
- );
- if (currIndex === -1) {
- msgState.push(newMsg);
- } else {
- msgState[currIndex] = newMsg;
- }
- }
- const newMsgState = msgState.sort((a, b) => {
- if (a._id > b._id) {
- return 1;
- }
- if (a._id < b._id) {
- return -1;
- }
- return 0;
- });
- return newMsgState;
- }
- function getInfoAboutNext(msgState) {
- const informedState = [];
- for (let i = 0; i < msgState.length; i++) {
- const msg = msgState[i];
- msg.nextMsg = msgState[i + 1] || null;
- informedState.push(msg);
- }
- return informedState;
- }
- function sortChats(unsortedChats) {
- return Object.fromEntries(
- Object.entries(unsortedChats).sort((a, b) => {
- if (a[1].lastModified > b[1].lastModified) {
- return -1;
- }
- if (a[1].lastModified < b[1].lastModified) {
- return 1;
- }
- return 0;
- })
- );
- }
- const types = {
- CHATS() {
- if (payload) {
- const oldChats = { ...state };
- for (const chat of payload) {
- const oldChat = oldChats[chat._id];
- if (!oldChat) {
- oldChats[chat._id] = { ...chat };
- } else
- for (const key in chat) {
- const oldValue = oldChat[key];
- const newValue = chat[key];
- if (newValue) {
- if (key === "messages") {
- oldChats[chat._id][key] = getInfoAboutNext(
- refreshMsgs(newValue, oldValue)
- );
- } else {
- oldChats[chat._id][key] = newValue;
- }
- } else {
- oldChats[chat._id][key] = oldValue;
- }
- }
- }
- const newState = sortChats(oldChats);
- return newState;
- }
- return state;
- },
- CHAT_LEFT() {
- const { [payload._id]: removed, ...newState } = state;
- return newState;
- },
- CHATS_CLEAR() {
- return {};
- },
- MSGS() {
- if (payload && payload.length > 0) {
- const chatId = payload[0]?.chat?._id;
- const msgState = state[chatId]?.messages || [];
- const newMsgState = getInfoAboutNext(
- refreshMsgs(payload, msgState)
- );
- const newState = {
- ...state,
- [chatId]: {
- ...state[chatId],
- messages: newMsgState,
- },
- };
- return newState;
- }
- return state;
- },
- };
- if (type in types) {
- return types[type]();
- }
- return state;
- }
- export const actionChatList = (chats) => ({ type: "CHATS", payload: chats });
- export const actionChatOne = (chat) => ({ type: "CHATS", payload: [chat] });
- export const actionChatLeft = (chat) => ({ type: "CHAT_LEFT", payload: chat });
- export const actionChatsClear = () => ({ type: "CHATS_CLEAR" });
- export const actionMsgList = (msgs) => ({ type: "MSGS", payload: msgs });
- export const actionMsgOne = (msg) => ({ type: "MSGS", payload: [msg] });
- // -------------------------------
- export const actionUserFindOne = (userId, name = "findUserOne") =>
- actionPromise(
- name,
- gql(
- `query findUserOne($q: String) {
- UserFindOne (query: $q){
- _id
- createdAt
- login
- nick
- avatar {
- _id
- url
- }
- chats{
- avatar {
- _id
- url
- }
- messages {
- _id
- createdAt
- text
- owner {
- _id
- createdAt
- login
- nick
- }
- media {
- _id
- createdAt
- text
- url
- originalFileName
- type
- }
- }
- _id
- createdAt
- title
- lastMessage {
- _id
- createdAt
- text
- }
- }
- }
- }
- `,
- {
- q: JSON.stringify([{ _id: userId }]),
- }
- )
- );
- export const actionAboutMe = () => async (dispatch, getState) => {
- let { auth } = getState();
- let id = auth?.payload?.sub?.id;
- if (id) {
- await dispatch(actionUserFindOne(id, "myProfile"));
- await dispatch(actionChatsCount(id));
- }
- };
- // -----------------------
- export const store = createStore(
- combineReducers({
- auth: authReducer,
- chats: chatsReducer,
- promise: promiseReducer,
- }),
- applyMiddleware(thunk)
- );
- store.dispatch(actionAboutMe());
- ///////////////////////////////////////////////////////////////////
- // if (Object.keys(store.getState().auth).length > 0) {}
-
- export const socket = window.io("ws://chat.ed.asmer.org.ua");
- socket.on("jwt_ok", (data) => console.log(data));
- socket.on("jwt_fail", (error) => {
- console.log(error);
- store.dispatch(actionFullLogout());
- });
- socket.on("msg", (msg) => {
- console.log("пришло смс");
- // store.dispatch(actionOnMsg(msg));
- store.dispatch(actionMsgOne(msg));
- });
- socket.on("chat", (chat) => {
- console.log("нас добавили в чат");
- store.dispatch(actionOnChat(chat));
- const state = store.getState();
- // socket.disconnect(true);
- // socket.connect();
- socket.emit("jwt", state.auth.token);
- });
- socket.on("chat_left", (chat) => {
- console.log("нас выкинули из чата");
- store.dispatch(actionOnChatLeft(chat));
- });
-
- store.subscribe(() => console.log(store.getState()));
- // console.log(store.getState());
- const bodyColor = () => {
- return (document.body.style.background = "#eee");
- };
- bodyColor();
|