diff --git a/src/components/profile/MessageForm/index.tsx b/src/components/profile/MessageForm/index.tsx index c674e6a7..c9e123fb 100644 --- a/src/components/profile/MessageForm/index.tsx +++ b/src/components/profile/MessageForm/index.tsx @@ -26,7 +26,7 @@ type IProps = ReturnType & }; const MessageFormUnconnected: FC = ({ - messages: { is_sending_messages, is_loading_messages, messages_error }, + messages: { is_sending_messages, is_loading_messages, error }, messagesSendMessage, id = 0, @@ -57,8 +57,8 @@ const MessageFormUnconnected: FC = ({ return (
- {messages_error &&
{ERROR_LITERAL[messages_error]}
} - {is_loading_messages && !messages_error && ( + {error &&
{ERROR_LITERAL[error]}
} + {is_loading_messages && !error && (
Обновляем
diff --git a/src/containers/profile/ProfileMessages/index.tsx b/src/containers/profile/ProfileMessages/index.tsx index de3d4e9e..0963a10f 100644 --- a/src/containers/profile/ProfileMessages/index.tsx +++ b/src/containers/profile/ProfileMessages/index.tsx @@ -16,6 +16,7 @@ const mapStateToProps = state => ({ const mapDispatchToProps = { messagesGetMessages: AUTH_ACTIONS.messagesGetMessages, + messagesRefreshMessages: AUTH_ACTIONS.messagesRefreshMessages, messagesDeleteMessage: AUTH_ACTIONS.messagesDeleteMessage, }; @@ -27,6 +28,7 @@ const ProfileMessagesUnconnected: FC = ({ user: { id }, messagesGetMessages, messagesDeleteMessage, + messagesRefreshMessages, }) => { const wasAtBottom = useRef(true); const [wrap, setWrap] = useState(null); @@ -48,13 +50,10 @@ const ProfileMessagesUnconnected: FC = ({ }, [profile.user]); useEffect(() => { - if (profile.is_loading || !profile.user || !profile.user.username || messages.messages_error) - return; - - const timer = setTimeout(() => messagesGetMessages(profile.user.username), 20000); + const timer = setInterval(messagesRefreshMessages, 20000); return () => clearTimeout(timer); - }, [profile.user, messages.messages]); + }, [messagesRefreshMessages]); const storeRef = useCallback( (div: HTMLDivElement) => { diff --git a/src/redux/messages/actions.ts b/src/redux/messages/actions.ts index ce563b68..d9db12d2 100644 --- a/src/redux/messages/actions.ts +++ b/src/redux/messages/actions.ts @@ -7,6 +7,15 @@ export const messagesGetMessages = (username: string) => ({ username, }); +export const messagesRefreshMessages = () => ({ + type: MESSAGES_ACTIONS.REFRESH_MESSAGES, +}); + +export const messagesLoadMoreMessages = (username: string) => ({ + type: MESSAGES_ACTIONS.LOAD_MORE, + username, +}); + export const messagesSendMessage = (message: Partial, onSuccess) => ({ type: MESSAGES_ACTIONS.SEND_MESSAGE, message, diff --git a/src/redux/messages/api.ts b/src/redux/messages/api.ts index d485d2f4..ff69487d 100644 --- a/src/redux/messages/api.ts +++ b/src/redux/messages/api.ts @@ -5,9 +5,16 @@ import { API } from '~/constants/api'; export const apiMessagesGetUserMessages = ({ access, username, + after, + before, +}: { + access: string; + username: string; + after?: string; + before?: string; }): Promise> => api - .get(API.USER.MESSAGES(username), configWithToken(access)) + .get(API.USER.MESSAGES(username), configWithToken(access, { params: { after, before } })) .then(resultMiddleware) .catch(errorMiddleware); diff --git a/src/redux/messages/constants.ts b/src/redux/messages/constants.ts index 5145c23f..3bb91a02 100644 --- a/src/redux/messages/constants.ts +++ b/src/redux/messages/constants.ts @@ -3,6 +3,8 @@ const p = 'MESSAGES.'; export const MESSAGES_ACTIONS = { SET_MESSAGES: `${p}SET_MESSAGES`, GET_MESSAGES: `${p}GET_MESSAGES`, + REFRESH_MESSAGES: `${p}REFRESH_MESSAGES`, + LOAD_MORE: `${p}LOAD_MORE`, SEND_MESSAGE: `${p}SEND_MESSAGE`, DELETE_MESSAGE: `${p}DELETE_MESSAGE`, }; diff --git a/src/redux/messages/index.ts b/src/redux/messages/index.ts index 018fd4d6..c868715b 100644 --- a/src/redux/messages/index.ts +++ b/src/redux/messages/index.ts @@ -6,13 +6,13 @@ export interface IMessagesState { is_loading_messages: boolean; is_sending_messages: boolean; messages: IMessage[]; - messages_error: string; + error: string; } const INITIAL_STATE: IMessagesState = { is_loading_messages: true, is_sending_messages: false, - messages_error: null, + error: null, messages: [], }; diff --git a/src/redux/messages/sagas.ts b/src/redux/messages/sagas.ts index c2609a28..c45bc6ee 100644 --- a/src/redux/messages/sagas.ts +++ b/src/redux/messages/sagas.ts @@ -16,11 +16,13 @@ import { reqWrapper } from '~/redux/auth/sagas'; import { messagesDeleteMessage, messagesGetMessages, + messagesRefreshMessages, messagesSendMessage, messagesSet, } from '~/redux/messages/actions'; import { MESSAGES_ACTIONS } from '~/redux/messages/constants'; import { selectMessages } from '~/redux/messages/selectors'; +import { sortCreatedAtDesc } from '~/utils/date'; function* getMessages({ username }: ReturnType) { const { messages }: ReturnType = yield select(selectMessages); @@ -37,20 +39,27 @@ function* getMessages({ username }: ReturnType) { }) ); - const { error, data } = yield call(reqWrapper, apiMessagesGetUserMessages, { username }); + const { + error, + data, + }: Unwrap> = yield call( + reqWrapper, + apiMessagesGetUserMessages, + { username } + ); if (error || !data.messages) { return yield put( messagesSet({ is_loading_messages: false, - messages_error: ERRORS.EMPTY_RESPONSE, + error: ERRORS.EMPTY_RESPONSE, }) ); } yield put(messagesSet({ is_loading_messages: false, messages: data.messages })); - const { notifications } = yield select(selectAuthUpdates); + const { notifications }: ReturnType = yield select(selectAuthUpdates); // clear viewed message from notifcation list const filtered = notifications.filter( @@ -71,7 +80,7 @@ function* sendMessage({ message, onSuccess }: ReturnType> = yield call( reqWrapper, @@ -86,7 +95,7 @@ function* sendMessage({ message, onSuccess }: ReturnType> = yield call( reqWrapper, @@ -165,8 +174,47 @@ function* deleteMessage({ id, is_locked }: ReturnType) { + const username: ReturnType = yield select( + selectAuthProfileUsername + ); + + if (!username) return; + + const { messages }: ReturnType = yield select(selectMessages); + + yield put(messagesSet({ is_loading_messages: true })); + + const after = messages.length > 0 ? messages[0].created_at : undefined; + + const { + data, + error, + }: Unwrap> = yield call( + reqWrapper, + apiMessagesGetUserMessages, + { username, after } + ); + + yield put(messagesSet({ is_loading_messages: false })); + + if (error) { + return yield put( + messagesSet({ + error: error || ERRORS.EMPTY_RESPONSE, + }) + ); + } + + if (!data.messages || !data.messages.length) return; + + const newMessages = [...data.messages, ...messages].sort(sortCreatedAtDesc); + yield put(messagesSet({ messages: newMessages })); +} + export default function*() { yield takeLatest(MESSAGES_ACTIONS.GET_MESSAGES, getMessages); yield takeLatest(MESSAGES_ACTIONS.SEND_MESSAGE, sendMessage); yield takeLatest(MESSAGES_ACTIONS.DELETE_MESSAGE, deleteMessage); + yield takeLatest(MESSAGES_ACTIONS.REFRESH_MESSAGES, refreshMessages); } diff --git a/src/utils/date.ts b/src/utils/date.ts new file mode 100644 index 00000000..de79175e --- /dev/null +++ b/src/utils/date.ts @@ -0,0 +1,5 @@ +export const sortCreatedAtAsc = (a, b) => + new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); + +export const sortCreatedAtDesc = (a, b) => + new Date(b.created_at).getTime() - new Date(a.created_at).getTime();