diff --git a/src/background/bulk-state.ts b/src/background/bulk-state.ts index 07f7464..3bf1d1f 100644 --- a/src/background/bulk-state.ts +++ b/src/background/bulk-state.ts @@ -1,4 +1,4 @@ -// bulk state-change handlers: close, open, delete, lock, pin, unpin. +// bulk state-change handlers: close, open, delete, lock, unlock, pin, unpin. import { onMessage } from '@/lib/messages' import { gql } from '@/lib/graphql-client' @@ -6,6 +6,7 @@ import { CLOSE_ISSUE, REOPEN_ISSUE, LOCK_ISSUE, + UNLOCK_ISSUE, PIN_ISSUE, UNPIN_ISSUE, DELETE_PROJECT_ITEM, @@ -388,6 +389,71 @@ export function registerBulkStateHandlers(): void { } }) + onMessage('bulkUnlock', async ({ data, sender }) => { + logger.log('[rgp:bg] bulkUnlock received', { itemCount: data.itemIds.length }) + if (isBulkFull()) { + console.warn('[rgp:bg] max concurrent bulk reached, rejecting bulkUnlock') + return + } + acquireBulk() + const processId = `unlock-${Date.now()}-${Math.random().toString(36).slice(2, 7)}` + const label = `Unlock · ${data.itemIds.length} item${data.itemIds.length !== 1 ? 's' : ''}` + const tabId = sender.tab?.id + try { + await broadcastQueue( + { + total: data.itemIds.length, + completed: 0, + paused: false, + status: 'Resolving items...', + processId, + label, + }, + tabId, + ) + const resolvedItems = await resolveProjectItemIds(data.itemIds, data.projectId, tabId) + if (resolvedItems.length === 0) { + console.error('[rgp:bg] no valid items resolved for bulkUnlock, aborting') + return + } + const tasks: QueueTask[] = resolvedItems.map(({ domId, issueNodeId }) => ({ + id: `unlock-${domId}`, + run: async () => { + await gql(UNLOCK_ISSUE, { lockableId: issueNodeId }) + await sleep(1000) + }, + })) + await processQueue( + tasks, + async (state) => { + await broadcastQueue( + { + total: state.total, + completed: state.completed, + paused: state.paused, + retryAfter: state.retryAfter, + status: + state.completed < resolvedItems.length + ? `Unlocking item ${state.completed + 1} of ${resolvedItems.length}…` + : `Unlocking ${resolvedItems.length} item${resolvedItems.length !== 1 ? 's' : ''}…`, + processId, + label, + failedItems: state.failedItems, + }, + tabId, + ) + }, + processId, + ) + await broadcastQueue( + { total: 0, completed: 0, paused: false, status: 'Done!', processId, label }, + tabId, + ) + } finally { + releaseBulk() + } + }) + onMessage('bulkUnpin', async ({ data, sender }) => { logger.log('[rgp:bg] bulkUnpin received', { itemCount: data.itemIds.length }) if (isBulkFull()) { diff --git a/src/features/bulk-actions-bar.tsx b/src/features/bulk-actions-bar.tsx index 142b73c..acea503 100644 --- a/src/features/bulk-actions-bar.tsx +++ b/src/features/bulk-actions-bar.tsx @@ -650,7 +650,7 @@ export function BulkActionsBar({ projectId, owner, isOrg, number, getFields }: P selectionStore.clear() return case 'unlock': - sendMessage('bulkLock', { itemIds, projectId: resolvedProjectId, lockReason: null }) + sendMessage('bulkUnlock', { itemIds, projectId: resolvedProjectId }) return } } diff --git a/src/lib/graphql-mutations.ts b/src/lib/graphql-mutations.ts index a92af76..8fcd372 100644 --- a/src/lib/graphql-mutations.ts +++ b/src/lib/graphql-mutations.ts @@ -157,6 +157,16 @@ export const LOCK_ISSUE = ` } ` +export const UNLOCK_ISSUE = ` + mutation UnlockIssue($lockableId: ID!) { + unlockLockable(input: { lockableId: $lockableId }) { + unlockedRecord { + ... on Issue { id locked } + } + } + } +` + export const PIN_ISSUE = ` mutation PinIssue($issueId: ID!) { pinIssue(input: { issueId: $issueId }) { diff --git a/src/lib/messages.ts b/src/lib/messages.ts index 4f56c98..98b405f 100644 --- a/src/lib/messages.ts +++ b/src/lib/messages.ts @@ -264,6 +264,7 @@ interface ProtocolMap { projectId: string lockReason: 'OFF_TOPIC' | 'TOO_HEATED' | 'RESOLVED' | 'SPAM' | null }): void + bulkUnlock(data: { itemIds: string[]; projectId: string }): void bulkPin(data: { itemIds: string[]; projectId: string }): void bulkUnpin(data: { itemIds: string[]; projectId: string }): void bulkDelete(data: { itemIds: string[]; projectId: string }): void diff --git a/src/lib/schemas-messages.ts b/src/lib/schemas-messages.ts index 07f06c8..e8993fb 100644 --- a/src/lib/schemas-messages.ts +++ b/src/lib/schemas-messages.ts @@ -355,6 +355,13 @@ export const Messages = { }), output: Schema.Void, }, + bulkUnlock: { + input: Schema.Struct({ + itemIds: Schema.Array(Schema.String), + projectId: Schema.String, + }), + output: Schema.Void, + }, bulkPin: { input: Schema.Struct({ itemIds: Schema.Array(Schema.String),