mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
messages: refactored reducer
This commit is contained in:
parent
64b27e517f
commit
be7829f130
3 changed files with 176 additions and 171 deletions
|
@ -1,48 +1,29 @@
|
|||
import { IMessage, IResultWithStatus } from '~/redux/types';
|
||||
import { api, configWithToken, errorMiddleware, resultMiddleware } from '~/utils/api';
|
||||
import { api, cleanResult } from '~/utils/api';
|
||||
import { API } from '~/constants/api';
|
||||
import {
|
||||
ApiDeleteMessageRequest,
|
||||
ApiDeleteMessageResult,
|
||||
ApiGetUserMessagesRequest,
|
||||
ApiGetUserMessagesResponse,
|
||||
ApiSendMessageRequest,
|
||||
ApiSendMessageResult,
|
||||
} from '~/redux/messages/types';
|
||||
|
||||
export const apiMessagesGetUserMessages = ({
|
||||
access,
|
||||
username,
|
||||
after,
|
||||
before,
|
||||
}: {
|
||||
access: string;
|
||||
username: string;
|
||||
after?: string;
|
||||
before?: string;
|
||||
}): Promise<IResultWithStatus<{ messages: IMessage[] }>> =>
|
||||
export const apiGetUserMessages = ({ username, after, before }: ApiGetUserMessagesRequest) =>
|
||||
api
|
||||
.get(API.USER.MESSAGES(username), configWithToken(access, { params: { after, before } }))
|
||||
.then(resultMiddleware)
|
||||
.catch(errorMiddleware);
|
||||
.get<ApiGetUserMessagesResponse>(API.USER.MESSAGES(username), {
|
||||
params: { after, before },
|
||||
})
|
||||
.then(cleanResult);
|
||||
|
||||
export const apiMessagesSendMessage = ({
|
||||
access,
|
||||
username,
|
||||
message,
|
||||
}): Promise<IResultWithStatus<{ message: IMessage }>> =>
|
||||
export const apiSendMessage = ({ username, message }: ApiSendMessageRequest) =>
|
||||
api
|
||||
.post(API.USER.MESSAGE_SEND(username), { message }, configWithToken(access))
|
||||
.then(resultMiddleware)
|
||||
.catch(errorMiddleware);
|
||||
.post<ApiSendMessageResult>(API.USER.MESSAGE_SEND(username), { message })
|
||||
.then(cleanResult);
|
||||
|
||||
export const apiMessagesDeleteMessage = ({
|
||||
access,
|
||||
username,
|
||||
id,
|
||||
is_locked,
|
||||
}: {
|
||||
access: string;
|
||||
username: string;
|
||||
id: number;
|
||||
is_locked: boolean;
|
||||
}): Promise<IResultWithStatus<{ message: IMessage }>> =>
|
||||
export const apiDeleteMessage = ({ username, id, is_locked }: ApiDeleteMessageRequest) =>
|
||||
api
|
||||
.delete(
|
||||
API.USER.MESSAGE_DELETE(username, id),
|
||||
configWithToken(access, { params: { is_locked } })
|
||||
)
|
||||
.then(resultMiddleware)
|
||||
.catch(errorMiddleware);
|
||||
.delete<ApiDeleteMessageResult>(API.USER.MESSAGE_DELETE(username, id), {
|
||||
params: { is_locked },
|
||||
})
|
||||
.then(cleanResult);
|
||||
|
|
|
@ -5,14 +5,9 @@ import {
|
|||
selectAuthProfileUsername,
|
||||
selectAuthUpdates,
|
||||
} from '~/redux/auth/selectors';
|
||||
import {
|
||||
apiMessagesDeleteMessage,
|
||||
apiMessagesGetUserMessages,
|
||||
apiMessagesSendMessage,
|
||||
} from '~/redux/messages/api';
|
||||
import { apiDeleteMessage, apiGetUserMessages, apiSendMessage } from '~/redux/messages/api';
|
||||
import { ERRORS } from '~/constants/errors';
|
||||
import { IMessageNotification, Unwrap } from '~/redux/types';
|
||||
import { wrap } from '~/redux/auth/sagas';
|
||||
import {
|
||||
messagesDeleteMessage,
|
||||
messagesGetMessages,
|
||||
|
@ -25,185 +20,188 @@ import { selectMessages } from '~/redux/messages/selectors';
|
|||
import { sortCreatedAtDesc } from '~/utils/date';
|
||||
|
||||
function* getMessages({ username }: ReturnType<typeof messagesGetMessages>) {
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
try {
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_loading_messages: true,
|
||||
messages:
|
||||
messages &&
|
||||
messages.length > 0 &&
|
||||
(messages[0].to.username === username || messages[0].from.username === username)
|
||||
? messages
|
||||
: [],
|
||||
})
|
||||
);
|
||||
|
||||
const { error, data }: Unwrap<typeof apiMessagesGetUserMessages> = yield call(
|
||||
wrap,
|
||||
apiMessagesGetUserMessages,
|
||||
{ username }
|
||||
);
|
||||
|
||||
if (error || !data.messages) {
|
||||
return yield put(
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_loading_messages: false,
|
||||
error: ERRORS.EMPTY_RESPONSE,
|
||||
is_loading_messages: true,
|
||||
messages:
|
||||
messages &&
|
||||
messages.length > 0 &&
|
||||
(messages[0].to.username === username || messages[0].from.username === username)
|
||||
? messages
|
||||
: [],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
yield put(messagesSet({ is_loading_messages: false, messages: data.messages }));
|
||||
const data: Unwrap<typeof apiGetUserMessages> = yield call(apiGetUserMessages, {
|
||||
username,
|
||||
});
|
||||
|
||||
const { notifications }: ReturnType<typeof selectAuthUpdates> = yield select(selectAuthUpdates);
|
||||
yield put(messagesSet({ is_loading_messages: false, messages: data.messages }));
|
||||
|
||||
// clear viewed message from notifcation list
|
||||
const filtered = notifications.filter(
|
||||
notification =>
|
||||
notification.type !== 'message' ||
|
||||
(notification as IMessageNotification).content.from.username !== username
|
||||
);
|
||||
const { notifications }: ReturnType<typeof selectAuthUpdates> = yield select(selectAuthUpdates);
|
||||
|
||||
if (filtered.length !== notifications.length) {
|
||||
yield put(authSetUpdates({ notifications: filtered }));
|
||||
// clear viewed message from notifcation list
|
||||
const filtered = notifications.filter(
|
||||
notification =>
|
||||
notification.type !== 'message' ||
|
||||
(notification as IMessageNotification)?.content?.from?.username !== username
|
||||
);
|
||||
|
||||
if (filtered.length !== notifications.length) {
|
||||
yield put(authSetUpdates({ notifications: filtered }));
|
||||
}
|
||||
} catch (error) {
|
||||
messagesSet({
|
||||
error: error || ERRORS.EMPTY_RESPONSE,
|
||||
});
|
||||
} finally {
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_loading_messages: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function* sendMessage({ message, onSuccess }: ReturnType<typeof messagesSendMessage>) {
|
||||
const username: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
try {
|
||||
const username: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
|
||||
if (!username) return;
|
||||
if (!username) return;
|
||||
|
||||
yield put(messagesSet({ is_sending_messages: true, error: null }));
|
||||
yield put(messagesSet({ is_sending_messages: true, error: '' }));
|
||||
|
||||
const { error, data }: Unwrap<typeof apiMessagesSendMessage> = yield call(
|
||||
wrap,
|
||||
apiMessagesSendMessage,
|
||||
{
|
||||
const data: Unwrap<typeof apiSendMessage> = yield call(apiSendMessage, {
|
||||
username,
|
||||
message,
|
||||
});
|
||||
|
||||
const { user }: ReturnType<typeof selectAuthProfile> = yield select(selectAuthProfile);
|
||||
|
||||
if (user?.username !== username) {
|
||||
return yield put(messagesSet({ is_sending_messages: false }));
|
||||
}
|
||||
);
|
||||
|
||||
if (error || !data.message) {
|
||||
return yield put(
|
||||
messagesSet({
|
||||
is_sending_messages: false,
|
||||
error: error || ERRORS.EMPTY_RESPONSE,
|
||||
})
|
||||
);
|
||||
}
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
|
||||
const { user }: ReturnType<typeof selectAuthProfile> = yield select(selectAuthProfile);
|
||||
if (message.id && message.id > 0) {
|
||||
// modified
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_sending_messages: false,
|
||||
messages: messages.map(item => (item.id === message.id ? data.message : item)),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// created
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_sending_messages: false,
|
||||
messages: [data.message, ...messages],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (user.username !== username) {
|
||||
return yield put(messagesSet({ is_sending_messages: false }));
|
||||
}
|
||||
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
|
||||
if (message.id > 0) {
|
||||
// modified
|
||||
onSuccess();
|
||||
} catch (error) {
|
||||
messagesSet({
|
||||
error: error || ERRORS.EMPTY_RESPONSE,
|
||||
});
|
||||
} finally {
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_sending_messages: false,
|
||||
messages: messages.map(item => (item.id === message.id ? data.message : item)),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// created
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_sending_messages: false,
|
||||
messages: [data.message, ...messages],
|
||||
is_loading_messages: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
onSuccess();
|
||||
}
|
||||
|
||||
function* deleteMessage({ id, is_locked }: ReturnType<typeof messagesDeleteMessage>) {
|
||||
const username: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
try {
|
||||
const username: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
|
||||
if (!username) return;
|
||||
if (!username) return;
|
||||
|
||||
yield put(messagesSet({ is_sending_messages: true, error: null }));
|
||||
yield put(messagesSet({ is_sending_messages: true, error: '' }));
|
||||
|
||||
const { error, data }: Unwrap<typeof apiMessagesDeleteMessage> = yield call(
|
||||
wrap,
|
||||
apiMessagesDeleteMessage,
|
||||
{
|
||||
const data: Unwrap<typeof apiDeleteMessage> = yield call(apiDeleteMessage, {
|
||||
username,
|
||||
id,
|
||||
is_locked,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
if (error || !data.message) {
|
||||
return yield put(
|
||||
const currentUsername: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
|
||||
if (currentUsername !== username) {
|
||||
return yield put(messagesSet({ is_sending_messages: false }));
|
||||
}
|
||||
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_sending_messages: false,
|
||||
messages: messages.map(item => (item.id === id ? data.message : item)),
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
messagesSet({
|
||||
error: error || ERRORS.EMPTY_RESPONSE,
|
||||
});
|
||||
} finally {
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_loading_messages: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const currentUsername: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
|
||||
if (currentUsername !== username) {
|
||||
return yield put(messagesSet({ is_sending_messages: false }));
|
||||
}
|
||||
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
|
||||
yield put(
|
||||
messagesSet({
|
||||
is_sending_messages: false,
|
||||
messages: messages.map(item => (item.id === id ? data.message : item)),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function* refreshMessages({}: ReturnType<typeof messagesRefreshMessages>) {
|
||||
const username: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
try {
|
||||
const username: ReturnType<typeof selectAuthProfileUsername> = yield select(
|
||||
selectAuthProfileUsername
|
||||
);
|
||||
|
||||
if (!username) return;
|
||||
if (!username) return;
|
||||
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
const { messages }: ReturnType<typeof selectMessages> = yield select(selectMessages);
|
||||
|
||||
yield put(messagesSet({ is_loading_messages: true }));
|
||||
yield put(messagesSet({ is_loading_messages: true }));
|
||||
|
||||
const after = messages.length > 0 ? messages[0].created_at : undefined;
|
||||
const after = messages.length > 0 ? messages[0].created_at : undefined;
|
||||
|
||||
const { data, error }: Unwrap<typeof apiMessagesGetUserMessages> = yield call(
|
||||
wrap,
|
||||
apiMessagesGetUserMessages,
|
||||
{ username, after }
|
||||
);
|
||||
const data: Unwrap<typeof apiGetUserMessages> = yield call(apiGetUserMessages, {
|
||||
username,
|
||||
after,
|
||||
});
|
||||
|
||||
yield put(messagesSet({ is_loading_messages: false }));
|
||||
yield put(messagesSet({ is_loading_messages: false }));
|
||||
|
||||
if (error) {
|
||||
return yield put(
|
||||
if (!data.messages || !data.messages.length) return;
|
||||
|
||||
const newMessages = [...data.messages, ...messages].sort(sortCreatedAtDesc);
|
||||
yield put(messagesSet({ messages: newMessages }));
|
||||
} catch (error) {
|
||||
messagesSet({
|
||||
error: error || ERRORS.EMPTY_RESPONSE,
|
||||
});
|
||||
} finally {
|
||||
yield put(
|
||||
messagesSet({
|
||||
error: error || ERRORS.EMPTY_RESPONSE,
|
||||
is_loading_messages: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (!data.messages || !data.messages.length) return;
|
||||
|
||||
const newMessages = [...data.messages, ...messages].sort(sortCreatedAtDesc);
|
||||
yield put(messagesSet({ messages: newMessages }));
|
||||
}
|
||||
|
||||
export default function*() {
|
||||
|
|
26
src/redux/messages/types.ts
Normal file
26
src/redux/messages/types.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { IMessage } from '~/redux/types';
|
||||
|
||||
export type ApiGetUserMessagesRequest = {
|
||||
username: string;
|
||||
after?: string;
|
||||
before?: string;
|
||||
};
|
||||
export type ApiGetUserMessagesResponse = { messages: IMessage[] };
|
||||
|
||||
export type ApiSendMessageRequest = {
|
||||
username: string;
|
||||
message: Partial<IMessage>;
|
||||
};
|
||||
export type ApiSendMessageResult = {
|
||||
message: IMessage;
|
||||
};
|
||||
|
||||
export type ApiDeleteMessageRequest = {
|
||||
username: string;
|
||||
id: number;
|
||||
is_locked: boolean;
|
||||
};
|
||||
|
||||
export type ApiDeleteMessageResult = {
|
||||
message: IMessage;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue