diff --git a/keyserver/src/updaters/thread-updaters.js b/keyserver/src/updaters/thread-updaters.js --- a/keyserver/src/updaters/thread-updaters.js +++ b/keyserver/src/updaters/thread-updaters.js @@ -23,6 +23,7 @@ type UpdateThreadRequest, type ServerThreadJoinRequest, type ThreadJoinResult, + type ToggleMessagePinRequest, threadPermissions, threadTypes, } from 'lib/types/thread-types.js'; @@ -841,6 +842,40 @@ await createUpdates(updateDatas); } +async function toggleMessagePinForThread( + viewer: Viewer, + request: ToggleMessagePinRequest, +): Promise { + const { messageID, threadID, isPinned } = request; + + const hasPermission = await checkThreadPermission( + viewer, + threadID, + threadPermissions.MANAGE_PINS, + ); + + // Verify that the viewer has the proper credentials to manage pins + if (!hasPermission) { + throw new ServerError('invalid_credentials'); + } + + // Toggle the pin status: if the message is pinned, unpin it, and vice versa + let togglePinQuery; + if (isPinned) { + togglePinQuery = SQL` + DELETE FROM pinned_messages + WHERE messageID = ${messageID} AND thread = ${threadID} + `; + } else { + togglePinQuery = SQL` + INSERT INTO pinned_messages (messageID, thread, pin_time) + VALUES (${messageID}, ${threadID}, ${Date.now()}) + `; + } + + await dbQuery(togglePinQuery); +} + export { updateRole, removeMembers, @@ -848,4 +883,5 @@ updateThread, joinThread, updateThreadMembers, + toggleMessagePinForThread, }; diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js --- a/lib/types/thread-types.js +++ b/lib/types/thread-types.js @@ -471,6 +471,12 @@ +mostRecentNonLocalMessage: ?string, }; +export type ToggleMessagePinRequest = { + +messageID: string, + +threadID: string, + +isPinned: boolean, +}; + // We can show a max of 3 sidebars inline underneath their parent in the chat // tab. If there are more, we show a button that opens a modal to see the rest export const maxReadSidebars = 3;