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,41 @@ await createUpdates(updateDatas); } +async function toggleMessagePinForThread( + viewer: Viewer, + request: ToggleMessagePinRequest, +): Promise { + const { messageID, threadID, action } = request; + + const hasPermission = await checkThreadPermission( + viewer, + threadID, + threadPermissions.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 (action === 'pin') { + togglePinQuery = SQL` + UPDATE messages + SET pinned = 1, pin_time = ${Date.now()} + WHERE id = ${messageID} + `; + } else { + togglePinQuery = SQL` + UPDATE messages + SET pinned = 0, pin_time = NULL + WHERE id = ${messageID} + `; + } + + await dbQuery(togglePinQuery); +} + export { updateRole, removeMembers, @@ -848,4 +884,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 @@ -473,6 +473,12 @@ +mostRecentNonLocalMessage: ?string, }; +export type ToggleMessagePinRequest = { + +messageID: string, + +threadID: string, + +action: 'pin' | 'unpin', +}; + // 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;