@hivegpt/hiveai-angular 0.0.612 → 0.0.613

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1614,6 +1614,8 @@ class ChatDrawerComponent {
1614
1614
  /** Guards against our own programmatic scrolls triggering the userHasScrolled detection. */
1615
1615
  this.isProgrammaticScroll = false;
1616
1616
  this.scrollListenerTimer = null;
1617
+ /** Throttle timer for streaming chunk scroll — prevents firing on every chunk. */
1618
+ this.chunkScrollRAF = null;
1617
1619
  /** Connections list from host (e.g. from store selectConnectionsList). Each item has userId. When set, used for Connect/Request Sent/Disconnect button state. */
1618
1620
  this.connectionsList = [];
1619
1621
  /** Pending sent request user IDs from host (e.g. from store selectPendingConnectionsSentList). When set, used for Request Sent state. */
@@ -3758,7 +3760,7 @@ class ChatDrawerComponent {
3758
3760
  }
3759
3761
  this.cdr.detectChanges();
3760
3762
  }
3761
- scrollToBottom(force = false, smooth = true) {
3763
+ scrollToBottom(force = false) {
3762
3764
  if (!force && !this.autoScrollOnNewMessage) {
3763
3765
  return;
3764
3766
  }
@@ -3771,10 +3773,36 @@ class ChatDrawerComponent {
3771
3773
  this.isProgrammaticScroll = true;
3772
3774
  el.scrollTo({
3773
3775
  top: el.scrollHeight,
3774
- behavior: smooth ? 'smooth' : 'auto',
3776
+ behavior: 'smooth',
3777
+ });
3778
+ setTimeout(() => { this.isProgrammaticScroll = false; }, 400);
3779
+ }
3780
+ /**
3781
+ * Lightweight scroll-to-bottom used during streaming chunks.
3782
+ * Coalesces via requestAnimationFrame so we get at most one smooth
3783
+ * nudge per paint frame, no matter how fast chunks arrive.
3784
+ */
3785
+ scrollToBottomStreaming() {
3786
+ if (this.userHasScrolled)
3787
+ return;
3788
+ if (this.chunkScrollRAF !== null)
3789
+ return; // already queued
3790
+ this.chunkScrollRAF = requestAnimationFrame(() => {
3791
+ this.chunkScrollRAF = null;
3792
+ if (this.userHasScrolled)
3793
+ return;
3794
+ const el = this.chatMain?.nativeElement;
3795
+ if (!el)
3796
+ return;
3797
+ // Small gap check: only scroll if we're within a reasonable distance from the bottom
3798
+ const gap = el.scrollHeight - el.scrollTop - el.clientHeight;
3799
+ if (gap <= 0)
3800
+ return; // already at bottom
3801
+ this.isProgrammaticScroll = true;
3802
+ // Use a quick smooth nudge rather than instant jump
3803
+ el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
3804
+ setTimeout(() => { this.isProgrammaticScroll = false; }, 300);
3775
3805
  });
3776
- // Release the guard after the smooth scroll settles
3777
- setTimeout(() => { this.isProgrammaticScroll = false; }, smooth ? 400 : 50);
3778
3806
  }
3779
3807
  /** Scrolls the chat container so the top of the AI message with the given id is visible. */
3780
3808
  scrollToAiMessage(messageId) {
@@ -4687,7 +4715,7 @@ class ChatDrawerComponent {
4687
4715
  }
4688
4716
  else {
4689
4717
  this.cdr.markForCheck();
4690
- setTimeout(() => this.scrollToBottom(true, false), 0);
4718
+ this.scrollToBottomStreaming();
4691
4719
  }
4692
4720
  break;
4693
4721
  }