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