看板范围默认从「只看我的」改为「团队全部」,同事移交或推进的工单不用 手动切开关就能看见。同事的卡片按 Gitea 归属(assignee 优先,无 assignee 退回创建者)判定为只读:禁止拖列、开会话、实施、合并分支、删 worktree、 删改工单,卡片右上角贴归属人头像,详情面板属性表整体消毒并显示只读徽章。 看 PR 改动、勾已查看、生成文件摘要属于本机审查动作,照常放行。 扩展侧在消息分发前统一拦截需要归属人身份的消息,兜住前端快照过期或工单 刚被重新指派的竞态;webhook 单卡上板时同步归属,避免增量卡漏进门禁。 头像由扩展侧带 token 抓回转 data URI 下发,绕开 webview CSP 对外链图片 的限制,按 URL 进程内缓存。 Claude-Session: https://claude.ai/code/session_01KSgcQwf1mWrb8qeTKFvJbV
45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
import type { Issue } from '../gitea/types'
|
|
|
|
export const KANBAN_SNAPSHOT_KEY = 'superpowers.kanbanSnapshot'
|
|
|
|
export interface KanbanSnapshot {
|
|
issues: Issue[]
|
|
scope: 'mine' | 'all'
|
|
me?: string
|
|
/** Gitea login → 头像 data URI;团队视图下卡片按人贴头像。 */
|
|
avatars?: Record<string, string>
|
|
globalAutoReview: boolean
|
|
youtrackConfigured: boolean
|
|
}
|
|
|
|
function isAvatarMap(raw: unknown): raw is Record<string, string> {
|
|
return !!raw && typeof raw === 'object' && Object.values(raw).every(v => typeof v === 'string')
|
|
}
|
|
|
|
export function parseKanbanSnapshot(raw: unknown): KanbanSnapshot | null {
|
|
if (!raw || typeof raw !== 'object')
|
|
return null
|
|
const obj = raw as Record<string, unknown>
|
|
if (!Array.isArray(obj.issues))
|
|
return null
|
|
if (obj.scope !== 'mine' && obj.scope !== 'all')
|
|
return null
|
|
return {
|
|
issues: obj.issues as Issue[],
|
|
scope: obj.scope,
|
|
me: typeof obj.me === 'string' ? obj.me : undefined,
|
|
avatars: isAvatarMap(obj.avatars) ? obj.avatars : undefined,
|
|
globalAutoReview: obj.globalAutoReview === true,
|
|
youtrackConfigured: obj.youtrackConfigured === true,
|
|
}
|
|
}
|
|
|
|
/** 写入 HTML 的 JSON:小于号换成 \\u003c,避免 script 标签被提前关掉。 */
|
|
export function snapshotToScriptJson(snapshot: KanbanSnapshot): string {
|
|
return JSON.stringify(snapshot).replace(/</g, '\\u003c')
|
|
}
|
|
|
|
export function snapshotScriptTag(nonce: string, snapshot: KanbanSnapshot): string {
|
|
return `<script nonce="${nonce}" type="application/json" id="kanban-snapshot">${snapshotToScriptJson(snapshot)}</script>`
|
|
}
|