1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

getting messages diff

This commit is contained in:
Fedor Katurov 2020-09-09 18:45:29 +07:00
parent e1117a0d91
commit d935e9de42
8 changed files with 87 additions and 17 deletions

View file

@ -26,7 +26,7 @@ type IProps = ReturnType<typeof mapStateToProps> &
}; };
const MessageFormUnconnected: FC<IProps> = ({ const MessageFormUnconnected: FC<IProps> = ({
messages: { is_sending_messages, is_loading_messages, messages_error }, messages: { is_sending_messages, is_loading_messages, error },
messagesSendMessage, messagesSendMessage,
id = 0, id = 0,
@ -57,8 +57,8 @@ const MessageFormUnconnected: FC<IProps> = ({
return ( return (
<div className={styles.wrap}> <div className={styles.wrap}>
{messages_error && <div className={styles.error}>{ERROR_LITERAL[messages_error]}</div>} {error && <div className={styles.error}>{ERROR_LITERAL[error]}</div>}
{is_loading_messages && !messages_error && ( {is_loading_messages && !error && (
<Group className={styles.loader} horizontal> <Group className={styles.loader} horizontal>
<LoaderCircle size={20} /> <LoaderCircle size={20} />
<div>Обновляем</div> <div>Обновляем</div>

View file

@ -16,6 +16,7 @@ const mapStateToProps = state => ({
const mapDispatchToProps = { const mapDispatchToProps = {
messagesGetMessages: AUTH_ACTIONS.messagesGetMessages, messagesGetMessages: AUTH_ACTIONS.messagesGetMessages,
messagesRefreshMessages: AUTH_ACTIONS.messagesRefreshMessages,
messagesDeleteMessage: AUTH_ACTIONS.messagesDeleteMessage, messagesDeleteMessage: AUTH_ACTIONS.messagesDeleteMessage,
}; };
@ -27,6 +28,7 @@ const ProfileMessagesUnconnected: FC<IProps> = ({
user: { id }, user: { id },
messagesGetMessages, messagesGetMessages,
messagesDeleteMessage, messagesDeleteMessage,
messagesRefreshMessages,
}) => { }) => {
const wasAtBottom = useRef(true); const wasAtBottom = useRef(true);
const [wrap, setWrap] = useState<HTMLDivElement>(null); const [wrap, setWrap] = useState<HTMLDivElement>(null);
@ -48,13 +50,10 @@ const ProfileMessagesUnconnected: FC<IProps> = ({
}, [profile.user]); }, [profile.user]);
useEffect(() => { useEffect(() => {
if (profile.is_loading || !profile.user || !profile.user.username || messages.messages_error) const timer = setInterval(messagesRefreshMessages, 20000);
return;
const timer = setTimeout(() => messagesGetMessages(profile.user.username), 20000);
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [profile.user, messages.messages]); }, [messagesRefreshMessages]);
const storeRef = useCallback( const storeRef = useCallback(
(div: HTMLDivElement) => { (div: HTMLDivElement) => {

View file

@ -7,6 +7,15 @@ export const messagesGetMessages = (username: string) => ({
username, 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<IMessage>, onSuccess) => ({ export const messagesSendMessage = (message: Partial<IMessage>, onSuccess) => ({
type: MESSAGES_ACTIONS.SEND_MESSAGE, type: MESSAGES_ACTIONS.SEND_MESSAGE,
message, message,

View file

@ -5,9 +5,16 @@ import { API } from '~/constants/api';
export const apiMessagesGetUserMessages = ({ export const apiMessagesGetUserMessages = ({
access, access,
username, username,
after,
before,
}: {
access: string;
username: string;
after?: string;
before?: string;
}): Promise<IResultWithStatus<{ messages: IMessage[] }>> => }): Promise<IResultWithStatus<{ messages: IMessage[] }>> =>
api api
.get(API.USER.MESSAGES(username), configWithToken(access)) .get(API.USER.MESSAGES(username), configWithToken(access, { params: { after, before } }))
.then(resultMiddleware) .then(resultMiddleware)
.catch(errorMiddleware); .catch(errorMiddleware);

View file

@ -3,6 +3,8 @@ const p = 'MESSAGES.';
export const MESSAGES_ACTIONS = { export const MESSAGES_ACTIONS = {
SET_MESSAGES: `${p}SET_MESSAGES`, SET_MESSAGES: `${p}SET_MESSAGES`,
GET_MESSAGES: `${p}GET_MESSAGES`, GET_MESSAGES: `${p}GET_MESSAGES`,
REFRESH_MESSAGES: `${p}REFRESH_MESSAGES`,
LOAD_MORE: `${p}LOAD_MORE`,
SEND_MESSAGE: `${p}SEND_MESSAGE`, SEND_MESSAGE: `${p}SEND_MESSAGE`,
DELETE_MESSAGE: `${p}DELETE_MESSAGE`, DELETE_MESSAGE: `${p}DELETE_MESSAGE`,
}; };

View file

@ -6,13 +6,13 @@ export interface IMessagesState {
is_loading_messages: boolean; is_loading_messages: boolean;
is_sending_messages: boolean; is_sending_messages: boolean;
messages: IMessage[]; messages: IMessage[];
messages_error: string; error: string;
} }
const INITIAL_STATE: IMessagesState = { const INITIAL_STATE: IMessagesState = {
is_loading_messages: true, is_loading_messages: true,
is_sending_messages: false, is_sending_messages: false,
messages_error: null, error: null,
messages: [], messages: [],
}; };

View file

@ -16,11 +16,13 @@ import { reqWrapper } from '~/redux/auth/sagas';
import { import {
messagesDeleteMessage, messagesDeleteMessage,
messagesGetMessages, messagesGetMessages,
messagesRefreshMessages,
messagesSendMessage, messagesSendMessage,
messagesSet, messagesSet,
} from '~/redux/messages/actions'; } from '~/redux/messages/actions';
import { MESSAGES_ACTIONS } from '~/redux/messages/constants'; import { MESSAGES_ACTIONS } from '~/redux/messages/constants';
import { selectMessages } from '~/redux/messages/selectors'; import { selectMessages } from '~/redux/messages/selectors';
import { sortCreatedAtDesc } from '~/utils/date';
function* getMessages({ username }: ReturnType<typeof messagesGetMessages>) { function* getMessages({ username }: ReturnType<typeof messagesGetMessages>) {
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages); const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
@ -37,20 +39,27 @@ function* getMessages({ username }: ReturnType<typeof messagesGetMessages>) {
}) })
); );
const { error, data } = yield call(reqWrapper, apiMessagesGetUserMessages, { username }); const {
error,
data,
}: Unwrap<ReturnType<typeof apiMessagesGetUserMessages>> = yield call(
reqWrapper,
apiMessagesGetUserMessages,
{ username }
);
if (error || !data.messages) { if (error || !data.messages) {
return yield put( return yield put(
messagesSet({ messagesSet({
is_loading_messages: false, is_loading_messages: false,
messages_error: ERRORS.EMPTY_RESPONSE, error: ERRORS.EMPTY_RESPONSE,
}) })
); );
} }
yield put(messagesSet({ is_loading_messages: false, messages: data.messages })); yield put(messagesSet({ is_loading_messages: false, messages: data.messages }));
const { notifications } = yield select(selectAuthUpdates); const { notifications }: ReturnType<typeof selectAuthUpdates> = yield select(selectAuthUpdates);
// clear viewed message from notifcation list // clear viewed message from notifcation list
const filtered = notifications.filter( const filtered = notifications.filter(
@ -71,7 +80,7 @@ function* sendMessage({ message, onSuccess }: ReturnType<typeof messagesSendMess
if (!username) return; if (!username) return;
yield put(messagesSet({ is_sending_messages: true, messages_error: null })); yield put(messagesSet({ is_sending_messages: true, error: null }));
const { error, data }: Unwrap<ReturnType<typeof apiMessagesSendMessage>> = yield call( const { error, data }: Unwrap<ReturnType<typeof apiMessagesSendMessage>> = yield call(
reqWrapper, reqWrapper,
@ -86,7 +95,7 @@ function* sendMessage({ message, onSuccess }: ReturnType<typeof messagesSendMess
return yield put( return yield put(
messagesSet({ messagesSet({
is_sending_messages: false, is_sending_messages: false,
messages_error: error || ERRORS.EMPTY_RESPONSE, error: error || ERRORS.EMPTY_RESPONSE,
}) })
); );
} }
@ -127,7 +136,7 @@ function* deleteMessage({ id, is_locked }: ReturnType<typeof messagesDeleteMessa
if (!username) return; if (!username) return;
yield put(messagesSet({ is_sending_messages: true, messages_error: null })); yield put(messagesSet({ is_sending_messages: true, error: null }));
const { error, data }: Unwrap<ReturnType<typeof apiMessagesDeleteMessage>> = yield call( const { error, data }: Unwrap<ReturnType<typeof apiMessagesDeleteMessage>> = yield call(
reqWrapper, reqWrapper,
@ -165,8 +174,47 @@ function* deleteMessage({ id, is_locked }: ReturnType<typeof messagesDeleteMessa
); );
} }
function* refreshMessages({}: ReturnType<typeof messagesRefreshMessages>) {
const username: ReturnType<typeof selectAuthProfileUsername> = yield select(
selectAuthProfileUsername
);
if (!username) return;
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
yield put(messagesSet({ is_loading_messages: true }));
const after = messages.length > 0 ? messages[0].created_at : undefined;
const {
data,
error,
}: Unwrap<ReturnType<typeof apiMessagesGetUserMessages>> = 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*() { export default function*() {
yield takeLatest(MESSAGES_ACTIONS.GET_MESSAGES, getMessages); yield takeLatest(MESSAGES_ACTIONS.GET_MESSAGES, getMessages);
yield takeLatest(MESSAGES_ACTIONS.SEND_MESSAGE, sendMessage); yield takeLatest(MESSAGES_ACTIONS.SEND_MESSAGE, sendMessage);
yield takeLatest(MESSAGES_ACTIONS.DELETE_MESSAGE, deleteMessage); yield takeLatest(MESSAGES_ACTIONS.DELETE_MESSAGE, deleteMessage);
yield takeLatest(MESSAGES_ACTIONS.REFRESH_MESSAGES, refreshMessages);
} }

5
src/utils/date.ts Normal file
View file

@ -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();