This commit is contained in:
mup 2025-10-17 14:25:18 +02:00
parent ca7746b0b6
commit 9a518eae42

View file

@ -102,9 +102,6 @@ export class TimeView implements Component<TimeViewAttributes> {
oncreate(vnode): any { oncreate(vnode): any {
;(vnode.dom as HTMLElement).style.gridTemplateRows = `repeat(${subRowCount}, 1fr)` ;(vnode.dom as HTMLElement).style.gridTemplateRows = `repeat(${subRowCount}, 1fr)`
}, },
// style: {
// "grid-template-columns": "repeat(8, 1fr)",
// }
}, },
[this.renderEvents(events, timeRange, subRowAsMinutes, subRowCount, timeScale, date, hasAnyConflict)], [this.renderEvents(events, timeRange, subRowAsMinutes, subRowCount, timeScale, date, hasAnyConflict)],
) )
@ -359,6 +356,15 @@ export class TimeView implements Component<TimeViewAttributes> {
* This ensures events that were blocked by shifted events can now expand properly * This ensures events that were blocked by shifted events can now expand properly
*/ */
private applyRetroactiveShifts(gridData: Map<Id, GridEventData>, allColumns: Array<ColumnData>): void { private applyRetroactiveShifts(gridData: Map<Id, GridEventData>, allColumns: Array<ColumnData>): void {
// Cache conflict info to avoid redundant calculations
const conflictCache = new Map<
Id,
{
conflict: { distance: number; id: Id; gridStart: number } | undefined
sumOfSizes: number
}
>()
for (const [eventId, gridInfo] of gridData.entries()) { for (const [eventId, gridInfo] of gridData.entries()) {
const eventIndex = this.eventIdToOriginalColumnArrayIndex.get(eventId) const eventIndex = this.eventIdToOriginalColumnArrayIndex.get(eventId)
if (eventIndex == null) { if (eventIndex == null) {
@ -367,64 +373,89 @@ export class TimeView implements Component<TimeViewAttributes> {
const expectedGridEnd = gridInfo.gridColumnStart + gridInfo.gridColumnEnd const expectedGridEnd = gridInfo.gridColumnStart + gridInfo.gridColumnEnd
let conflict: // Check cache first to avoid redundant conflict finding
| { let cachedConflictInfo = conflictCache.get(eventId)
distance: number let conflict: { distance: number; id: Id; gridStart: number } | undefined
id: string let sumOfSizes = 0
gridStart: number
}
| undefined
for (let i = eventIndex + 1; i < allColumns.length; i++) { if (!cachedConflictInfo) {
const columnData = allColumns[i] // Find conflict and accumulate sizes - preserve original loop logic
for (let i = eventIndex + 1; i < allColumns.length; i++) {
const columnData = allColumns[i]
const overlappingEvents = this.findOverlappingEvents( const overlappingEvents = this.findOverlappingEvents(
{ {
rowStart: gridInfo.start, rowStart: gridInfo.start,
rowEnd: gridInfo.end, rowEnd: gridInfo.end,
}, },
columnData.events, columnData.events,
) )
if (overlappingEvents.size === 0) { if (overlappingEvents.size === 0) {
continue
}
for (const [conflictId, _] of overlappingEvents.entries()) {
const conflictInfo = gridData.get(conflictId)
if (!conflictInfo) {
continue continue
} }
const distance = conflictInfo.gridColumnStart - expectedGridEnd
if (conflict?.distance == null || distance < conflict?.distance) { // Optimization: Accumulate and find closest in single pass
conflict = { for (const [conflictId] of overlappingEvents.entries()) {
distance, const conflictInfo = gridData.get(conflictId)
id: conflictId, if (!conflictInfo) {
gridStart: conflictInfo.gridColumnStart, continue
}
const distance = conflictInfo.gridColumnStart - expectedGridEnd
sumOfSizes += conflictInfo.gridColumnEnd
// Find closest conflict (minimum distance)
if (!conflict || distance < conflict.distance) {
conflict = {
distance,
id: conflictId,
gridStart: conflictInfo.gridColumnStart,
}
} }
} }
} }
// Cache the result
cachedConflictInfo = { conflict, sumOfSizes }
conflictCache.set(eventId, cachedConflictInfo)
} else {
conflict = cachedConflictInfo.conflict
sumOfSizes = cachedConflictInfo.sumOfSizes
} }
if (!conflict) { if (!conflict) {
// Maybe we should set to max here?
continue continue
} }
if (expectedGridEnd < conflict.gridStart) { let newSize: number | null = null
const newSize = gridInfo.gridColumnEnd + conflict.distance
// Case 1: Already exceeds grid bounds
if (gridInfo.gridColumnStart + gridInfo.gridColumnEnd > allColumns.length) {
newSize = Math.max(allColumns.length - gridInfo.gridColumnStart, BASE_EVENT_BUBBLE_SPAN_SIZE)
}
// Case 2: Can expand (no overlap)
else if (expectedGridEnd < conflict.gridStart) {
const expandedSize = gridInfo.gridColumnEnd + conflict.distance
newSize =
gridInfo.gridColumnStart + expandedSize > allColumns.length
? Math.max(allColumns.length - gridInfo.gridColumnStart, BASE_EVENT_BUBBLE_SPAN_SIZE)
: expandedSize
}
// Case 3: Must shrink (overlap detected)
else if (expectedGridEnd > conflict.gridStart) {
const shrinkSize = conflict.gridStart - 1
newSize =
gridInfo.gridColumnStart + shrinkSize + sumOfSizes > allColumns.length
? Math.max(allColumns.length - gridInfo.gridColumnStart, BASE_EVENT_BUBBLE_SPAN_SIZE)
: shrinkSize
}
// Only update if size changed
if (newSize !== null && newSize !== gridInfo.gridColumnEnd) {
gridData.set(eventId, { gridData.set(eventId, {
...gridInfo, ...gridInfo,
gridColumnEnd: gridColumnEnd: newSize,
gridInfo.gridColumnStart + newSize > allColumns.length + 1
? Math.max(allColumns.length - gridInfo.gridColumnStart, BASE_EVENT_BUBBLE_SPAN_SIZE)
: newSize,
})
} else if (expectedGridEnd > conflict.gridStart) {
gridData.set(eventId, {
...gridInfo,
gridColumnEnd: conflict.gridStart - 1,
}) })
} }
} }