mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
Keeps a fork issue’s details, metadata and edits bound to the repository the user opened, including same-number issues in fork and upstream. Repairs selected-assignee leakage and delayed failed edits repainting another issue. Fixes #24378 Incorporates and cross-reviews contributor PR #24379, including its source-resolver correction and regression material. Covers the contributor PR’s Project-row identity and retained-dialog mutation findings. The final published head passes focused tests, hidden macOS rendering and current CI; the callback-timing bot thread has an evidence-based response. Co-authored-by: Katsuma Takehisa <k.takehisa@nissogr.com>
141 lines
4.4 KiB
TypeScript
141 lines
4.4 KiB
TypeScript
import { ipcMain } from 'electron'
|
|
import type { GitHubOwnerRepo } from '../../shared/github/pull-request-types'
|
|
import type { GitHubIssueUpdate } from '../../shared/issue-mutation-types'
|
|
import type { TaskSourceContext } from '../../shared/task-source-context'
|
|
import { addIssueComment, listAssignableUsers, listLabels, updateIssue } from '../github/client'
|
|
import type { Store } from '../persistence'
|
|
import {
|
|
assertRegisteredGitHubRepo,
|
|
getGitHubLocalGitOptionArgs,
|
|
getGitHubRepoConnectionId,
|
|
type GitHubRepoScopedArgs
|
|
} from './github-repo-routing'
|
|
import { broadcastGitHubWorkItemMutation } from './github-work-item-mutation-events'
|
|
|
|
export function registerGitHubIssueMutationHandlers(store: Store): void {
|
|
ipcMain.handle(
|
|
'gh:updateIssue',
|
|
async (
|
|
event,
|
|
args: GitHubRepoScopedArgs & {
|
|
number: number
|
|
updates: GitHubIssueUpdate
|
|
ownerRepo?: GitHubOwnerRepo
|
|
}
|
|
) => {
|
|
const repo = assertRegisteredGitHubRepo(args, store)
|
|
if (typeof args.number !== 'number' || !Number.isInteger(args.number) || args.number < 1) {
|
|
return { ok: false, error: 'Invalid issue number' }
|
|
}
|
|
if (!args.updates || typeof args.updates !== 'object') {
|
|
return { ok: false, error: 'Updates object is required' }
|
|
}
|
|
const result = await updateIssue(
|
|
repo.path,
|
|
args.number,
|
|
args.updates,
|
|
getGitHubRepoConnectionId(repo),
|
|
getGitHubLocalGitOptionArgs(store, repo)[0],
|
|
repo.issueSourcePreference,
|
|
...(args.ownerRepo ? [args.ownerRepo] : [])
|
|
)
|
|
if (result.ok) {
|
|
broadcastGitHubWorkItemMutation(
|
|
{ repoPath: repo.path, repoId: repo.id, type: 'issue', number: args.number },
|
|
event.sender.id
|
|
)
|
|
}
|
|
return result
|
|
}
|
|
)
|
|
|
|
ipcMain.handle(
|
|
'gh:addIssueComment',
|
|
async (
|
|
event,
|
|
args: {
|
|
repoPath: string
|
|
repoId?: string
|
|
sourceContext?: TaskSourceContext | null
|
|
number: number
|
|
body: string
|
|
type?: 'issue' | 'pr'
|
|
prRepo?: GitHubOwnerRepo | null
|
|
}
|
|
) => {
|
|
const repo = assertRegisteredGitHubRepo(args, store)
|
|
if (typeof args.number !== 'number' || !Number.isInteger(args.number) || args.number < 1) {
|
|
return { ok: false, error: 'Invalid issue number' }
|
|
}
|
|
if (!args.body?.trim()) {
|
|
return { ok: false, error: 'Comment body required' }
|
|
}
|
|
const result = await addIssueComment(
|
|
repo.path,
|
|
args.number,
|
|
args.body.trim(),
|
|
getGitHubRepoConnectionId(repo),
|
|
args.prRepo ?? null,
|
|
getGitHubLocalGitOptionArgs(store, repo)[0],
|
|
// Why: the issue source selector only scopes issues; PR comments keep their resolution.
|
|
args.type === 'pr' ? undefined : repo.issueSourcePreference
|
|
)
|
|
if (result.ok) {
|
|
broadcastGitHubWorkItemMutation(
|
|
{
|
|
repoPath: repo.path,
|
|
repoId: repo.id,
|
|
type: args.type ?? 'issue',
|
|
number: args.number
|
|
},
|
|
event.sender.id
|
|
)
|
|
}
|
|
return result
|
|
}
|
|
)
|
|
|
|
ipcMain.handle(
|
|
'gh:listLabels',
|
|
(_event, args: GitHubRepoScopedArgs & { ownerRepo?: GitHubOwnerRepo }) => {
|
|
const repo = assertRegisteredGitHubRepo(args, store)
|
|
const localGitOptions = getGitHubLocalGitOptionArgs(store, repo)
|
|
const connectionId = getGitHubRepoConnectionId(repo)
|
|
if (args.ownerRepo) {
|
|
return listLabels(
|
|
repo.path,
|
|
repo.issueSourcePreference,
|
|
connectionId,
|
|
localGitOptions[0],
|
|
args.ownerRepo
|
|
)
|
|
}
|
|
return listLabels(repo.path, repo.issueSourcePreference, connectionId, ...localGitOptions)
|
|
}
|
|
)
|
|
|
|
ipcMain.handle(
|
|
'gh:listAssignableUsers',
|
|
(_event, args: GitHubRepoScopedArgs & { ownerRepo?: GitHubOwnerRepo }) => {
|
|
const repo = assertRegisteredGitHubRepo(args, store)
|
|
const localGitOptions = getGitHubLocalGitOptionArgs(store, repo)
|
|
const connectionId = getGitHubRepoConnectionId(repo)
|
|
if (args.ownerRepo) {
|
|
return listAssignableUsers(
|
|
repo.path,
|
|
repo.issueSourcePreference,
|
|
connectionId,
|
|
localGitOptions[0],
|
|
args.ownerRepo
|
|
)
|
|
}
|
|
return listAssignableUsers(
|
|
repo.path,
|
|
repo.issueSourcePreference,
|
|
connectionId,
|
|
...localGitOptions
|
|
)
|
|
}
|
|
)
|
|
}
|