62 lines
2.3 KiB
TypeScript
62 lines
2.3 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,
|
|
}
|
|
}
|
|
|
|
/** 看板上现在摆着的工单,和它从哪来:面板这次会话里加载好的(loaded)、上次存下的快照(saved)。 */
|
|
export interface BoardIssues {
|
|
issues: Issue[]
|
|
from: 'loaded' | 'saved'
|
|
}
|
|
|
|
/**
|
|
* 看板上现在摆着的工单:面板这次会话里加载好了就用它最近一次加载的,否则用上次存下的快照
|
|
* (重开窗口时看板先画的也是它);都没有时 undefined,看板还没加载过。
|
|
*/
|
|
export function boardIssues(loaded: Issue[] | undefined, persisted: unknown): BoardIssues | undefined {
|
|
if (loaded)
|
|
return { issues: loaded, from: 'loaded' }
|
|
const snapshot = parseKanbanSnapshot(persisted)
|
|
return snapshot ? { issues: snapshot.issues, from: 'saved' } : undefined
|
|
}
|
|
|
|
/** 写入 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>`
|
|
}
|