| 208 | |
| 209 | /** Measure one file section from the same render plan used by PierreDiffView. */ |
| 210 | export function measureDiffSectionGeometry( |
| 211 | file: DiffFile, |
| 212 | layout: Exclude<LayoutMode, "auto">, |
| 213 | showHunkHeaders: boolean, |
| 214 | theme: AppTheme, |
| 215 | visibleAgentNotes: VisibleAgentNote[] = [], |
| 216 | width = 0, |
| 217 | showLineNumbers = true, |
| 218 | wrapLines = false, |
| 219 | expandedKeys: ReadonlySet<string> = EMPTY_EXPANDED_GAP_KEYS, |
| 220 | sourceStatus: FileSourceStatus | undefined = undefined, |
| 221 | reserveAddNoteColumn = false, |
| 222 | ): DiffSectionGeometry { |
| 223 | if (file.metadata.hunks.length === 0) { |
| 224 | return { |
| 225 | bodyHeight: 1, |
| 226 | hunkAnchorRows: new Map(), |
| 227 | hunkBounds: new Map(), |
| 228 | lineNumberDigits: String(findMaxLineNumber(file)).length, |
| 229 | plannedRows: [], |
| 230 | rowBounds: [], |
| 231 | rowBoundsByKey: new Map(), |
| 232 | rowBoundsByStableKey: new Map(), |
| 233 | }; |
| 234 | } |
| 235 | |
| 236 | // Width, wrapping, and line-number visibility all affect rendered row heights, so they must |
| 237 | // participate in the cache key alongside the structural file/layout inputs. Expansion state |
| 238 | // changes the row stream, so it has to participate too. |
| 239 | const themeCacheKey = [ |
| 240 | theme.id, |
| 241 | theme.syntaxTheme ?? "", |
| 242 | theme.background, |
| 243 | theme.panelAlt, |
| 244 | theme.contextBg, |
| 245 | theme.addedBg, |
| 246 | theme.removedBg, |
| 247 | theme.lineNumberBg, |
| 248 | theme.lineNumberFg, |
| 249 | ].join(":"); |
| 250 | const cacheKey = `${file.id}:${layout}:${showHunkHeaders ? 1 : 0}:${themeCacheKey}:${width}:${showLineNumbers ? 1 : 0}:${wrapLines ? 1 : 0}:${reserveAddNoteColumn ? 1 : 0}${expansionCacheKey(expandedKeys, sourceStatus)}${notesCacheKey(visibleAgentNotes)}`; |
| 251 | const cacheSlot = sectionGeometryCacheSlot(visibleAgentNotes); |
| 252 | const cached = getCachedSectionGeometry(file, cacheSlot, cacheKey); |
| 253 | if (cached) { |
| 254 | return cached; |
| 255 | } |
| 256 | |
| 257 | const sectionRowPlan = buildDiffSectionRowPlan({ |
| 258 | expandedKeys, |
| 259 | file, |
| 260 | layout, |
| 261 | showHunkHeaders, |
| 262 | sourceStatus, |
| 263 | theme, |
| 264 | visibleAgentNotes, |
| 265 | }); |
| 266 | const { plannedRows } = sectionRowPlan; |
| 267 | const hunkAnchorRows = new Map<number, number>(); |