ability to pin chat messages (#11964)
parent
94f07c149a
commit
54706b1182
@ -0,0 +1,66 @@
|
|||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- chats
|
||||||
|
summary: pin a chat message
|
||||||
|
description: This operation pins an existing chat message in a chat room
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: roomId
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
description: a valid chat room id
|
||||||
|
example: 1
|
||||||
|
- in: path
|
||||||
|
name: mid
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
description: a valid chat message id
|
||||||
|
example: 1
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Chat message successfully pinned
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: ../../../../../components/schemas/Status.yaml#/Status
|
||||||
|
response:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- chats
|
||||||
|
summary: unpin a chat message
|
||||||
|
description: This operation unpins a chat message in a room
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: roomId
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
description: a valid chat room id
|
||||||
|
example: 1
|
||||||
|
- in: path
|
||||||
|
name: mid
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
description: a valid chat message id
|
||||||
|
example: 1
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Chat message successfully unpinned
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
$ref: ../../../../../components/schemas/Status.yaml#/Status
|
||||||
|
response:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
@ -0,0 +1,86 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
define('forum/chats/pinned-messages', ['api', 'alerts'], function (api, alerts) {
|
||||||
|
const pinnedMessages = {};
|
||||||
|
let container;
|
||||||
|
pinnedMessages.init = function (_container) {
|
||||||
|
container = _container;
|
||||||
|
$('[component="chat/pinned/messages/btn"]').on('click', async () => {
|
||||||
|
const pinnedMessagesContainer = container.find('[component="chat/messages/pinned/container"]');
|
||||||
|
if (!pinnedMessagesContainer.hasClass('hidden')) {
|
||||||
|
return pinnedMessagesContainer.addClass('hidden');
|
||||||
|
}
|
||||||
|
const userListEl = container.find('[component="chat/user/list"]');
|
||||||
|
userListEl.addClass('hidden');
|
||||||
|
await pinnedMessages.refreshList();
|
||||||
|
pinnedMessagesContainer.removeClass('hidden');
|
||||||
|
});
|
||||||
|
|
||||||
|
handleInfiniteScroll(container);
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleInfiniteScroll(container) {
|
||||||
|
const listEl = container.find('[component="chat/messages/pinned"]');
|
||||||
|
listEl.on('scroll', utils.debounce(async () => {
|
||||||
|
const bottom = (listEl[0].scrollHeight - listEl.height()) * 0.85;
|
||||||
|
if (listEl.scrollTop() > bottom) {
|
||||||
|
const lastIndex = listEl.find('[data-index]').last().attr('data-index');
|
||||||
|
const data = await loadData(parseInt(lastIndex, 10) + 1);
|
||||||
|
if (data && data.length) {
|
||||||
|
const html = await parseMessages(data);
|
||||||
|
container.find('[component="chat/messages/pinned"]').append(html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 200));
|
||||||
|
}
|
||||||
|
|
||||||
|
pinnedMessages.refreshList = async function () {
|
||||||
|
const data = await loadData(0);
|
||||||
|
|
||||||
|
if (!data.length) {
|
||||||
|
container.find('[component="chat/messages/pinned/empty"]').removeClass('hidden');
|
||||||
|
container.find('[component="chat/messages/pinned"]').html('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
container.find('[component="chat/messages/pinned/empty"]').addClass('hidden');
|
||||||
|
const html = await parseMessages(data);
|
||||||
|
container.find('[component="chat/messages/pinned"]').html(html);
|
||||||
|
html.find('.timeago').timeago();
|
||||||
|
};
|
||||||
|
|
||||||
|
async function parseMessages(data) {
|
||||||
|
return await app.parseAndTranslate('partials/chats/pinned-messages', 'messages', {
|
||||||
|
isOwner: ajaxify.data.isOwner,
|
||||||
|
isAdminOrGlobalMod: ajaxify.data.isAdminOrGlobalMod,
|
||||||
|
messages: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadData(start) {
|
||||||
|
const data = await socket.emit('modules.chats.loadPinnedMessages', {
|
||||||
|
roomId: ajaxify.data.roomId,
|
||||||
|
start: start,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinnedMessages.pin = function (mid, roomId) {
|
||||||
|
api.put(`/chats/${roomId}/messages/${mid}/pin`, {}).then(() => {
|
||||||
|
$(`[component="chat/message"][data-mid="${mid}"]`).toggleClass('pinned', true);
|
||||||
|
pinnedMessages.refreshList();
|
||||||
|
}).catch(alerts.error);
|
||||||
|
};
|
||||||
|
|
||||||
|
pinnedMessages.unpin = function (mid, roomId) {
|
||||||
|
api.del(`/chats/${roomId}/messages/${mid}/pin`, {}).then(() => {
|
||||||
|
$(`[component="chat/message"][data-mid="${mid}"]`).toggleClass('pinned', false);
|
||||||
|
container.find(`[component="chat/messages/pinned"] [data-mid="${mid}"]`).remove();
|
||||||
|
if (!container.find(`[component="chat/messages/pinned"] [data-mid]`).length) {
|
||||||
|
container.find('[component="chat/messages/pinned/empty"]').removeClass('hidden');
|
||||||
|
}
|
||||||
|
}).catch(alerts.error);
|
||||||
|
};
|
||||||
|
|
||||||
|
return pinnedMessages;
|
||||||
|
});
|
@ -0,0 +1,36 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const db = require('../database');
|
||||||
|
|
||||||
|
module.exports = function (Messaging) {
|
||||||
|
Messaging.pinMessage = async (mid, roomId) => {
|
||||||
|
const isMessageInRoom = await db.isSortedSetMember(`chat:room:${roomId}:mids`, mid);
|
||||||
|
if (isMessageInRoom) {
|
||||||
|
await db.sortedSetAdd(`chat:room:${roomId}:mids:pinned`, Date.now(), mid);
|
||||||
|
await Messaging.setMessageFields(mid, { pinned: 1 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Messaging.unpinMessage = async (mid, roomId) => {
|
||||||
|
const isMessageInRoom = await db.isSortedSetMember(`chat:room:${roomId}:mids`, mid);
|
||||||
|
if (isMessageInRoom) {
|
||||||
|
await db.sortedSetRemove(`chat:room:${roomId}:mids:pinned`, mid);
|
||||||
|
await Messaging.setMessageFields(mid, { pinned: 0 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Messaging.getPinnedMessages = async (roomId, uid, start, stop) => {
|
||||||
|
const mids = await db.getSortedSetRevRange(`chat:room:${roomId}:mids:pinned`, start, stop);
|
||||||
|
if (!mids.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageData = await Messaging.getMessagesData(mids, uid, roomId, true);
|
||||||
|
messageData.forEach((msg, i) => {
|
||||||
|
if (msg) {
|
||||||
|
msg.index = start + i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return messageData;
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in New Issue