Browse Source

optimizated actions

Ivar 2 years ago
parent
commit
8625357cff

+ 12 - 2
src/App.js

@@ -4,10 +4,13 @@ import {Provider, connect} from 'react-redux'
 import {Router, Route, Link, Redirect, Switch} from 'react-router-dom'
 import createHistory from "history/createBrowserHistory"
 import {
-  store
+  store,
+  socket
 } from "./reducers"
 import {
-  actionFullChatList
+  actionFullChatList,
+
+  actionUpdateChat
 } from "./actions"
 
 import {
@@ -29,6 +32,11 @@ const PageNoChat = () => (
 
 const AuthSwitch = ({ token }) => {
 
+  if (token) {
+    console.log('подключение сокета')
+    socket.emit('jwt', token)
+  }
+  
   return (
     <>      
       {token ? 
@@ -73,6 +81,8 @@ const history = createHistory()
 
 function App() {
 
+  // store.dispatch(actionUpdateChat('NewCHAT', [{_id: '617ad9262b5f0a03e6fd4037'}]))
+
   return (
     <Router history={history}>
       <Provider store={store}>

+ 0 - 3
src/actions/authActions.js

@@ -4,7 +4,6 @@ import {
    actionAuthLogin, 
    actionAuthLogout,
    actionAboutMe,
-   socket
 } from '../reducers'
 import {   
    actionUploadFile
@@ -14,7 +13,6 @@ import {
    export const actionFullLogout = () => (
       async (dispatch) => {
          await dispatch(actionAuthLogout())
-         // socket.disconnect()
       }
    )   
  
@@ -30,7 +28,6 @@ import {
          if (token) {
             await dispatch(actionAuthLogin(token))
             await dispatch(actionAboutMe())
-            // socket.emit('jwt', token)
          }
       }
    )

+ 1 - 1
src/actions/chatsActions.js

@@ -3,7 +3,7 @@ import {
    actionPromise, 
    actionChatList,
    actionChatOne,
-   actionChatLeft
+   actionChatLeft,
 } from '../reducers'
 import { actionGetAllLastMsg } from './msgActions'
 

+ 38 - 15
src/actions/msgActions.js

@@ -65,10 +65,18 @@ export const actionGetMsgsByChat = (chatId, skipCount=0, limitCount=50) => (
 )
 
 export const actionFullMsgsByChat = (chatId, currentCount, limitCount=50) => (
-   async (dispatch) => {
-      let payload = await dispatch(actionGetMsgsByChat(chatId, currentCount, limitCount))
-      if (payload) {
-         await dispatch(actionMsgList(payload))
+   async (dispatch, getState) => {
+      console.log('MSG STATE', getState())
+
+      console.log(getState().chats[chatId]?.messages?.length, currentCount + limitCount)
+      // TODO если длинна массива равна общему количеству то тоже не выполнять
+      // +2 так как затягиваем одно сообщение при загрузке всех чатов
+      if ( (getState().chats[chatId]?.messages?.length ?? 0) < currentCount + limitCount) {
+
+         let payload = await dispatch(actionGetMsgsByChat(chatId, currentCount, limitCount))
+         if (payload) {
+            await dispatch(actionMsgList(payload))
+         }
       }
    }
 )
@@ -84,6 +92,10 @@ const actionLastMsgByChat = (chatId) => (
          owner {
             _id
             login
+            nick
+            avatar {
+               url
+            }
          }
          text
          chat {
@@ -94,6 +106,20 @@ const actionLastMsgByChat = (chatId) => (
             originalFileName
             type
          }
+
+         forwardWith {
+            _id
+         }
+         replies {
+            _id
+         }
+
+         replyTo {
+            _id
+         }
+         forwarded {
+            _id
+         }
       }     
    }`, { 
          q: JSON.stringify([  { "chat._id": chatId },
@@ -111,12 +137,9 @@ export const actionGetAllLastMsg = (chats) => (
    async (dispatch) => {
 
       let msgReq = chats.map((chat) => dispatch(actionLastMsgByChat(chat._id)))
-      let msgRes = await Promise.all(msgReq)
 
-      if (msgRes) {        
-         for (const msg of msgRes.flat()) {
-            dispatch(actionMsgOne(msg))
-         }
+      for await (const [msg] of msgReq) {
+         msg && dispatch(actionMsgOne(msg))
       }
    }
 )
@@ -189,18 +212,18 @@ export const actionSendMsg = (chatId, text, inputName, files, msgId) => (
       for (const file of files) {
          if (file.preview.match(/blob/)) {
             let fileObj = await dispatch(actionUploadFile(inputName, file))
-            media.push({_id: fileObj?._id})
+            fileObj && media.push({_id: fileObj?._id})
          } else {
             let fileObj = file
             media.push({_id: fileObj?._id})
          }
       }
       let payload = await dispatch(actionUpdateMsg(chatId, text, media, msgId))
-      if (payload) {
-         await dispatch(actionMsgOne(payload))
-         let chatUpdated = await dispatch(actionGetChatById(chatId))
-         await dispatch(actionChatOne(chatUpdated))
-      }
+      // if (payload) {
+      //    await dispatch(actionMsgOne(payload))
+      //    let chatUpdated = await dispatch(actionGetChatById(chatId))
+      //    await dispatch(actionChatOne(chatUpdated))
+      // }
    }
 )
 

BIN
src/assets/msgSound.ogg


+ 2 - 4
src/components/ChatList.jsx

@@ -83,9 +83,7 @@ const ChatList = ({ chats=[], currChatId }) => {
             </Box>
 
               {chats.map(chat =>          
-                  (currChatId === chat._id) ? 
-                    <Chat key={chat._id} chat={chat} currChat={true} /> :
-                      <Chat key={chat._id} chat={chat} currChat={false} />
+                    <Chat key={chat._id} chat={chat} currChat={currChatId === chat._id} /> 
               )}  
           </div>  
         </List>
@@ -94,6 +92,6 @@ const ChatList = ({ chats=[], currChatId }) => {
       
   )
 }
-export const CChatList = connect( state => ({ chats: Object.values(state.chats) || [] }))(ChatList)
+export const CChatList = connect( state => ({ chats: Object.values(state.chats).filter(el => !!el._id)}))(ChatList)
 
 

+ 7 - 5
src/components/MsgList.jsx

@@ -3,7 +3,7 @@ import React, {useState, useEffect, useRef} from 'react'
 import { connect } from 'react-redux'
 import { dateFromStamp, stringColor, backURL } from '../helpers'
 
-import { UserAvatar } from '.'
+import { UserAvatar, CMyAvatar } from '.'
 
 
 const msgsWrapper = {
@@ -106,7 +106,7 @@ const Msg = ({ msg, prevOwner, prevTime, myId }) => {
       }  
    }
 
-   // console.log(allMedia)
+   // console.log(media)
 
 
 
@@ -130,8 +130,10 @@ const Msg = ({ msg, prevOwner, prevTime, myId }) => {
             >
             <div style={avBlock} >
                { (prOwner === owner._id && 
-                     prTime - createdAt < 600000) ? 
-                           <></> : <UserAvatar profile={owner} /> }
+                     prTime - createdAt < 600000) || 
+                           ( (myId === owner._id) ? 
+                                 <CMyAvatar /> : 
+                                       <UserAvatar profile={owner} /> ) }
             </div>
             <div style={(myId === owner._id) ? myBodyBlock : bodyBlock} >
 
@@ -144,7 +146,7 @@ const Msg = ({ msg, prevOwner, prevTime, myId }) => {
                   {
                      (media && media.length !== 0) &&
                            <div>
-                              {media.map((mediaObj) => <img key={mediaObj._id}
+                              {media.map((mediaObj) => <img key={mediaObj.url}
                                                             // type={mediaObj.type}
                                                             style={{maxWidth: "400px"}}
                                                             src={backURL + mediaObj.url } />

+ 5 - 4
src/components/SendingField.jsx

@@ -144,7 +144,7 @@ const MsgDropZone = ({ setText, setFiles, files, text, onEnter }) => {
 
   return (
    <>
-      <form action="/upload" method="post" encType="multipart/form-data" id='form'> 
+      <form action="/upload" method="post" encType="multipart/form-data" id='form' > 
          <section style={containerWrapp}>
 
 
@@ -178,9 +178,10 @@ const MsgDropZone = ({ setText, setFiles, files, text, onEnter }) => {
                      style={{ width: '100%' }}
                      onClick={(e) => e.stopPropagation()}
                      onChange={(e) => setText(e.target.value)}
-                     onKeyDown={(e) => {
-                        if (e.keyCode === 13 && !e.shiftKey) {                           
-                           (text.match(/^\s*$/) && files.length === 0) ||
+                     onKeyPress={(e) => {
+                        if (e.key === 'Enter' && !e.shiftKey) { 
+                           e.preventDefault()   
+                           ;(text.match(/^\s*$/) && files.length === 0) ||
                                  onEnter()
                            setText('')
                            setFiles([])

+ 4 - 1
src/pages/ChatsPage.jsx

@@ -12,7 +12,7 @@ const chatsPage= {
    overflowY: "auto"
  }
 
-const ChatsPage = ({ match:{params:{_id}}, auth, getChats, chatsCount=50 }) => {
+const ChatsPage = ({ match:{params:{_id}}, auth, getChats, chatsCount=20 }) => {
    const [chatBlock, setChatBlock] = useState(0)
  
    useEffect(async () => {
@@ -20,6 +20,9 @@ const ChatsPage = ({ match:{params:{_id}}, auth, getChats, chatsCount=50 }) => {
      if (userId) {
       await getChats(userId, chatBlock, chatsCount)
      } 
+     return function cleanUp() {
+       
+     }
    },[chatBlock])
  
    return (

+ 5 - 3
src/pages/MsgPage.jsx

@@ -42,12 +42,14 @@ const msgSend = {
 
 const MsgBlock = ({ chatId, getMsgs, msgsCount=20 }) => {
 
-   const [msgsBlock, setMsgsBlock] = useState(0)
+   const [msgsBlock, setMsgsBlock] = useState(1)
+
+   // перезагрузка и обновление стейта происходит тут ??????????
+   // надо как то отлавливать первый не первый рендер ????????
 
- 
    useEffect(() => {
       getMsgs(chatId, msgsBlock, msgsCount)
-   },[msgsBlock, chatId])
+   },[msgsBlock])
 
    return (
       <>  

+ 0 - 1
src/reducers/authReducer.js

@@ -1,5 +1,4 @@
 
-
 function jwtDecode(token) {
    try {
        let decoded = JSON.parse(atob(token.split('.')[1])) 

+ 20 - 14
src/reducers/chatsReducer.js

@@ -19,7 +19,7 @@
     if (!state) {
         return {}
     }
-
+    
     function refreshMsgs(newMsgs, oldMsgs) {
       const msgState = oldMsgs
 
@@ -31,7 +31,7 @@
         } else {
           msgState[currIndex] = newMsg
         }
-    }
+      }
 
       const newMsgState = msgState.sort((a, b) => {
         if (a._id > b._id) {
@@ -47,8 +47,22 @@
     }
 
 
-    const types = {
+    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) {
 
@@ -73,17 +87,7 @@
             }
           }
           
-          const newState = Object.fromEntries(
-            Object.entries(oldChats).sort((a, b) => {
-              if (a[1].lastModified > b[1].lastModified) {                
-                return -1
-              }
-              if (a[1].lastModified < b[1].lastModified) {
-                return 1
-              }
-              return 0
-            })
-          )
+          const newState = sortChats(oldChats)
 
           // console.log(newState, 'dasdasdasdasd')
           return newState
@@ -112,6 +116,7 @@
               messages: newMsgState
             }
           }
+
           return newState
         }
         return state
@@ -134,6 +139,7 @@
         {type: 'CHAT_LEFT', payload: chat}
   )
 
+  // добавить id чата
   export const actionMsgList = (msgs) => (
         {type: 'MSGS', payload: msgs}
   )

+ 8 - 2
src/reducers/index.js

@@ -18,7 +18,10 @@ import {
     actionUserFindOne,
     actionAboutMe
 } from './findUserActions'
-import {store} from './store'
+import {
+    store, 
+    socket
+} from './store'
 
 
 export {
@@ -39,7 +42,10 @@ export {
     actionUserFindOne,
     actionAboutMe
 } 
-export {store} 
+export {
+    store, 
+    socket
+} 
 
 
 

+ 44 - 17
src/reducers/store.js

@@ -12,8 +12,15 @@ import {
    actionChatLeft 
 } from './chatsReducer'
 
+import {   
+   actionGetChatById, 
+   actionFullLogout
+} from '../actions'
+
+import msgSound from '../assets/msgSound.ogg'
 // const { io } = require("socket.io-client");
 
+
 export const store =  createStore (  combineReducers({ 
                                     // promise: localStoredReducer(promiseReducer, 'promise'),
                                     // auth: localStoredReducer(authReducer, 'auth'),
@@ -30,29 +37,49 @@ store.dispatch(actionAboutMe())
 store.subscribe(() => console.log(store.getState()))
 
 
+///////////////////////////////////////////////////////////////////
+
+export const socket = window.io("ws://chat.fs.a-level.com.ua")
+
+socket.on('jwt_ok',   (data) => console.log(data))
+socket.on('jwt_fail', (error) => {
+   console.log(error)
+   store.dispatch(actionFullLogout())
+})
+
+socket.on('msg', async (msg) => { 
+   console.log('пришло смс')
+   
+   const state = store.getState()
+   const myId = state.auth.payload?.sub?.id
+   const ownerId = msg.owner?._id
+   if (myId !== ownerId) {
+      const inputMsgAudio = new Audio(msgSound)
+      inputMsgAudio.play()
+   }
+
+   const chatId = msg.chat?._id
+
+   await store.dispatch(actionMsgOne(msg)) 
 
-// export const socket = window.io("ws://chat.fs.a-level.com.ua")
+   if (chatId) {
+      let chatUpdated = await store.dispatch(actionGetChatById(chatId))
+      await store.dispatch(actionChatOne(chatUpdated))
+   }
+})
 
-// socket.on('jwt_ok',   (data) => console.log(data))
-// socket.on('jwt_fail', (error) => console.log(error))
+socket.on('chat', (chat) => { 
+   console.log('нас добавили в чат')
+   store.dispatch(actionChatOne(chat)) 
+})
 
-// socket.on('msg', (msg) => { 
-//    console.log('пришло смс')
-//     store.dispatch(actionMsgOne(msg)) 
-// })
-// socket.on('chat', (chat) => { 
-//     store.dispatch(actionChatOne(chat)) 
-// })
-// socket.on('chat_left', (chat) => { 
-//     store.dispatch(actionChatLeft(chat)) 
-// })
+socket.on('chat_left', (chat) => { 
+   console.log('нас выкинули из чата')
+   store.dispatch(actionChatLeft(chat)) 
+})
 
 
 
-// if (localStorage.authToken) {
-//    socket.emit('jwt', localStorage.authToken)
-// }
-// socket.disconnect()
 
 // combineReducers({cart: localStoredReducer(cartReducer, 'cart'),
 //                  promise: localStoredReducer(promiseReducer, 'promise') })