add optimistic_id field for messages, allowing us to show our own messages from other clients

This commit is contained in:
hippoz 2022-08-20 00:12:27 +03:00
parent 8b9679b93d
commit 34f945b7f4
Signed by: hippoz
GPG key ID: 7C52899193467641
5 changed files with 38 additions and 13 deletions

View file

@ -60,7 +60,8 @@
messageInput = "";
const res = await request("POST", apiRoute(`channels/${channel.id}/messages`), true, {
content: optimisticMessage.content
content: optimisticMessage.content,
optimistic_id: optimisticMessageId
});
if (res.success && res.ok) {

View file

@ -12,11 +12,11 @@ authWithToken(getItem("auth:token"));
// Remove loading screen
const loadingElement = document.getElementById("pre--loading-screen");
if (loadingElement) {
loadingElement.parentElement.removeChild(loadingElement);
loadingElement.parentElement.removeChild(loadingElement);
}
const app = new Main({
target: document.body
target: document.body
});
window.__waffle.app = app;

View file

@ -162,6 +162,15 @@ class MessageStore extends Store {
}
addMessage(message) {
if (message.optimistic_id) {
const index = this.value.findIndex(e => e.id === message.optimistic_id);
if (index !== -1) {
this.value[index] = message;
this.updated();
return;
}
}
this.value.push(message);
// only dispatch update if collectOldMessages didn't
if (!this.collectOldMessages()) {
@ -255,10 +264,6 @@ class MessagesStoreProvider {
this.storeByChannel = new Map();
gateway.subscribe(GatewayEventType.MessageCreate, (message) => {
// we currently don't care about our own messages
if (gateway.user && message.author_id === gateway.user.id)
return;
const store = this.getStoreOrNull(message.channel_id);
if (store)
store.addMessage(message);

View file

@ -67,13 +67,17 @@ function clientUnsubscribeAll(ws: WebSocket) {
ws.state.dispatchChannels = new Set();
}
export function dispatch(channel: string, message: GatewayPayload) {
export function dispatch(channel: string, message: GatewayPayload | ((ws: WebSocket) => GatewayPayload)) {
const members = dispatchChannels.get(channel);
if (!members) return;
members.forEach(e => {
if (e.state.ready) {
e.send(JSON.stringify(message));
let data = message;
if (typeof message === "function") {
data = message(e);
}
e.send(JSON.stringify(data));
}
});
}

View file

@ -173,12 +173,14 @@ router.post(
authenticateRoute(),
param("id").isNumeric(),
body("content").isLength({ min: 1, max: 4000 }),
body("optimistic_id").optional().isNumeric(),
async (req, res) => {
const validationErrors = validationResult(req);
if (!validationErrors.isEmpty()) {
return res.status(400).json({ ...errors.INVALID_DATA, errors: validationErrors.array() });
}
const optimisticId = parseInt(req.body.optimistic_id);
const channelId = parseInt(req.params.id);
const { content } = req.body;
const authorId = req.user.id;
@ -191,7 +193,7 @@ router.post(
});
}
const returnObject = {
let returnObject: any = {
id: result.rows[0].id,
content,
channel_id: channelId,
@ -200,9 +202,22 @@ router.post(
created_at: createdAt
};
dispatch(`channel:${channelId}`, {
t: GatewayPayloadType.MessageCreate,
d: returnObject
dispatch(`channel:${channelId}`, (ws) => {
let payload: any = returnObject;
if (ws.state && ws.state.user && ws.state.user.id === req.user.id && optimisticId) {
payload = {
...payload,
optimistic_id: optimisticId
}
returnObject = {
...returnObject,
optimistic_id: optimisticId
};
}
return {
t: GatewayPayloadType.MessageCreate,
d: payload
};
});
return res.status(201).send(returnObject);