()
| 492 | }; |
| 493 | |
| 494 | private updateVisibleRange(): void { |
| 495 | const scrollTop = this.scrollContainer.scrollTop; |
| 496 | let containerHeight = this.scrollContainer.clientHeight; |
| 497 | |
| 498 | // If container height is 0, try to get a better estimate |
| 499 | if (containerHeight === 0) { |
| 500 | // Try parent element height |
| 501 | containerHeight = this.scrollContainer.parentElement?.clientHeight || 0; |
| 502 | } |
| 503 | if (containerHeight === 0) { |
| 504 | // Fall back to window height as last resort |
| 505 | containerHeight = window.innerHeight; |
| 506 | tasknotesLogger.warn("[VirtualScroller] Using window height as fallback:", { |
| 507 | category: "configuration", |
| 508 | operation: "using-window-height-as-fallback", |
| 509 | details: { value: containerHeight }, |
| 510 | }); |
| 511 | } |
| 512 | |
| 513 | // Use binary search to find visible range based on actual positions |
| 514 | const startIndex = Math.max(0, this.binarySearchPosition(scrollTop) - this.overscan); |
| 515 | |
| 516 | // Find end index by searching from startIndex |
| 517 | let endIndex = startIndex; |
| 518 | const viewportBottom = scrollTop + containerHeight; |
| 519 | |
| 520 | while (endIndex < this.items.length - 1) { |
| 521 | const itemBottom = this.getItemPosition(endIndex) + this.getItemHeight(endIndex); |
| 522 | if (itemBottom > viewportBottom) { |
| 523 | break; |
| 524 | } |
| 525 | endIndex++; |
| 526 | } |
| 527 | |
| 528 | // Add overscan to end |
| 529 | endIndex = Math.min(this.items.length - 1, endIndex + this.overscan); |
| 530 | |
| 531 | const offsetY = this.getItemPosition(startIndex); |
| 532 | |
| 533 | // Only update if range changed |
| 534 | if ( |
| 535 | startIndex !== this.state.startIndex || |
| 536 | endIndex !== this.state.endIndex || |
| 537 | this.items.length !== this.state.totalItems |
| 538 | ) { |
| 539 | this.state = { |
| 540 | startIndex, |
| 541 | endIndex, |
| 542 | totalItems: this.items.length, |
| 543 | offsetY, |
| 544 | }; |
| 545 | this.renderVisibleItems(); |
| 546 | } |
| 547 | } |
| 548 | |
| 549 | private renderVisibleItems(): void { |
| 550 | const { startIndex, endIndex, offsetY } = this.state; |
no test coverage detected