| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | import { MonitorIcon, MoonIcon, SunIcon, TerminalIcon } from "lucide-react"; |
| 2 | 2 | import { useCallback, useEffect, useMemo, useState } from "react"; |
| 3 | 3 | import { useMutation, useQueries, useQueryClient } from "@tanstack/react-query"; |
| 4 | | import type { GitStatusResult } from "@t3tools/contracts"; |
| 4 | import { gitStatusResultSchema, type GitStatusResult } from "@t3tools/contracts"; |
| 5 | 5 | import { isElectron } from "../env"; |
| 6 | 6 | import { useTheme } from "../hooks/useTheme"; |
| 7 | 7 | import { DEFAULT_MODEL } from "../model-logic"; |
| ... | ... | @@ -153,29 +153,49 @@ export default function Sidebar() { |
| 153 | 153 | })), |
| 154 | 154 | [projectCwdById, state.threads], |
| 155 | 155 | ); |
| 156 | const threadGitStatusCwds = useMemo( |
| 157 | () => |
| 158 | [ |
| 159 | ...new Set( |
| 160 | threadGitTargets |
| 161 | .filter((target) => target.branch !== null) |
| 162 | .map((target) => target.cwd) |
| 163 | .filter((cwd): cwd is string => cwd !== null), |
| 164 | ), |
| 165 | ], |
| 166 | [threadGitTargets], |
| 167 | ); |
| 156 | 168 | const threadGitStatusQueries = useQueries({ |
| 157 | | queries: threadGitTargets.map((target) => { |
| 158 | | const base = gitStatusQueryOptions(api, target.cwd); |
| 169 | queries: threadGitStatusCwds.map((cwd) => { |
| 170 | const base = gitStatusQueryOptions(api, cwd); |
| 159 | 171 | return { |
| 160 | 172 | ...base, |
| 161 | | enabled: Boolean(base.enabled && target.branch !== null), |
| 173 | enabled: Boolean(base.enabled), |
| 162 | 174 | staleTime: 30_000, |
| 163 | 175 | refetchInterval: 60_000, |
| 164 | 176 | }; |
| 165 | 177 | }), |
| 166 | 178 | }); |
| 167 | 179 | const mergedPrByThreadId = useMemo(() => { |
| 180 | const statusByCwd = new Map<string, GitStatusResult>(); |
| 181 | for (let index = 0; index < threadGitStatusCwds.length; index += 1) { |
| 182 | const cwd = threadGitStatusCwds[index]; |
| 183 | if (!cwd) continue; |
| 184 | const parsed = gitStatusResultSchema.safeParse(threadGitStatusQueries[index]?.data); |
| 185 | if (parsed.success) { |
| 186 | statusByCwd.set(cwd, parsed.data); |
| 187 | } |
| 188 | } |
| 189 | |
| 168 | 190 | const map = new Map<string, boolean>(); |
| 169 | | for (let index = 0; index < threadGitTargets.length; index += 1) { |
| 170 | | const target = threadGitTargets[index]; |
| 171 | | if (!target) continue; |
| 172 | | const status = threadGitStatusQueries[index]?.data as GitStatusResult | undefined; |
| 191 | for (const target of threadGitTargets) { |
| 192 | const status = target.cwd ? statusByCwd.get(target.cwd) : undefined; |
| 173 | 193 | const branchMatches = |
| 174 | 194 | target.branch !== null && status?.branch !== null && status?.branch === target.branch; |
| 175 | 195 | map.set(target.threadId, branchMatches && status?.openPr === null && status?.mergedPr !== null); |
| 176 | 196 | } |
| 177 | 197 | return map; |
| 178 | | }, [threadGitStatusQueries, threadGitTargets]); |
| 198 | }, [threadGitStatusCwds, threadGitStatusQueries, threadGitTargets]); |
| 179 | 199 | |
| 180 | 200 | const handleNewThread = useCallback( |
| 181 | 201 | (projectId: string) => { |