| ... | @@ -139,22 +139,27 @@ export function computeThreadMoveAvailability(input: { | ... | @@ -139,22 +139,27 @@ export function computeThreadMoveAvailability(input: { |
| 139 | for (const row of rows) result.set(rowId(row), { canMoveUp: false, canMoveDown: false }); | 139 | for (const row of rows) result.set(rowId(row), { canMoveUp: false, canMoveDown: false }); |
| 140 | return result; | 140 | return result; |
| 141 | } | 141 | } |
| 142 | const orderedIds = rows.map(rowId); | 142 | // Plain loops: this runs per section on every Home rebuild over all shells, |
| 143 | const indexById = new Map(orderedIds.map((id, index) => [id, index] as const)); | 143 | // and the map/filter/spread chains it replaces dominated it with garbage. |
| 144 | const keysById = new Map( | 144 | const orderedIds: string[] = []; |
| 145 | (input.allThreads ?? input.ordered).map( | 145 | const indexById = new Map<string, number>(); |
| 146 | (row) => [rowId(row), rowOrder(row, input.section).key] as const, | 146 | for (const row of rows) { |
| 147 | ), | 147 | const id = rowId(row); |
| 148 | ); | 148 | indexById.set(id, orderedIds.length); |
| 149 | const writableIds = new Set( | 149 | orderedIds.push(id); |
| 150 | (input.allThreads ?? input.ordered) | 150 | } |
| 151 | .filter((row) => input.reorderableEnvironmentIds.has(row.environmentId)) | 151 | const keysById = new Map<string, string | null>(); |
| 152 | .map(rowId), | 152 | const writableIds = new Set<string>(); |
| 153 | ); | 153 | for (const row of input.allThreads ?? input.ordered) { |
| 154 | const visibleIds = new Set(orderedIds); | 154 | const id = rowId(row); |
| 155 | const reservedKeys = new Set( | 155 | keysById.set(id, rowOrder(row, input.section).key); |
| 156 | [...keysById].flatMap(([id, key]) => (!visibleIds.has(id) && key != null ? [key] : [])), | 156 | if (input.reorderableEnvironmentIds.has(row.environmentId)) writableIds.add(id); |
| 157 | ); | 157 | } |
| | 158 | // Read after the loop so a duplicate id reserves only its final key. |
| | 159 | const reservedKeys = new Set<string>(); |
| | 160 | keysById.forEach((key, id) => { |
| | 161 | if (key != null && !indexById.has(id)) reservedKeys.add(key); |
| | 162 | }); |
| 158 | // Mirror of `planPinnedReorder` for adjacent swaps, hoisted so every row is | 163 | // Mirror of `planPinnedReorder` for adjacent swaps, hoisted so every row is |
| 159 | // answered in O(1) amortized instead of one planner probe per row: | 164 | // answered in O(1) amortized instead of one planner probe per row: |
| 160 | // | 165 | // |