Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chat: use resizeObserver to update scrollbar size and position #28111

Merged

Conversation

EugeniyKiyashko
Copy link
Contributor

No description provided.

@EugeniyKiyashko EugeniyKiyashko changed the title Chat: use resizeObserver to update scrollbar size Chat: use resizeObserver to update scrollbar size and position Sep 26, 2024
@EugeniyKiyashko EugeniyKiyashko requested a review from a team September 26, 2024 10:44
@EugeniyKiyashko EugeniyKiyashko requested review from marker-dao and a team September 26, 2024 11:42
@EugeniyKiyashko EugeniyKiyashko merged commit 4f27749 into DevExpress:24_2 Sep 27, 2024
278 checks passed
@@ -50,7 +63,47 @@ class MessageList extends Widget<Properties> {

this._renderMessageListContent();

this.update();
this._attachResizeObserverSubscription();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SSR logic]
I believe it should be done in _renderContent, not _initMarkup.
Then u don't need if (hasWindow()) { inside of this method

}

_isAttached(element: Element): boolean {
return !!contains(domAdapter.getBody(), element);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[copypaste, shadowDOM]
I think we should use isElementInDom from utils/dom instead of creating this new method.
Moreover, now the solution does now work in shadowDOM as far as I see


if (this._suppressResizeHandling
&& this._isAttached(target)
&& isElementVisible(target as HTMLElement)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[refactoring]
Can we isolate these conditions? Let it be a first if and return if element is invisible or detached.
Now i don't like we do smth actions in this case + update cached height

_resizeHandler({ contentRect, target }: ResizeObserverEntry): void {
const newHeight = contentRect.height;

if (this._suppressResizeHandling
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[naming, ?excess cache?]
u name it _suppressResizeHandling, but i see u don't suppress, u scroll to last message.
So, what is this for, just for indicating it's a first call, right?

Then maybe we can get rid of this private cache and just do it this way?

const isAfterFirstRendering = this._containerClientHeight === 0; // or even undefined/null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can simplified it this way:

if (!isElementInDom(target) || !isElementVisible(target as HTMLElement)) {
      return;
    }

    if (!isDefined(this._containerClientHeight)) {
      this._scrollContentToLastMessage();
    }

});
});

QUnit.test('should be scrolled to the last message after being rendered inside an invisible element and display correctly when shown', function(assert) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QUnit.test('should be scrolled to the last message after being rendered inside an invisible element and display correctly when shown', function(assert) {
QUnit.test('should be scrolled to the last message after showing if was initially rendered inside an invisible element', function(assert) {


assert.strictEqual(scrollTop !== 0, true);
assert.notEqual(scrollTop, 0);
assert.roughEqual(scrollTop, this.getScrollOffsetMax(), 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor]
please add assertion comments. It's not very informative now
image

this._scrollable.scrollTo({ top: scrollOffsetTopMax });
}

_getScrollContainer(): HTMLElement {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[refactoring]
do we really need it? Maybe subscribe just on root?


this._suppressResizeHandling = false;
} else {
const heightChange = this._containerClientHeight - newHeight;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could u please add a Unit test for this scenario? Smth like "scrollable should keep scrolling position after container resize if scrolling position is not bottom"
It was very difficult for me now to understand without unit tests what it's written for


let { scrollTop } = target;

if (heightChange >= 1 || !isReachedBottom(target as HTMLDivElement, target.scrollTop, 0, 1)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[excess code?]
I don't understand why we need heightChange.
U're trying to say "we need some scroll if we are now on bottom and height is increased" but i see no difference with and without this code


let { scrollTop } = target;

if (heightChange >= 1 || !isReachedBottom(target as HTMLDivElement, target.scrollTop, 0, 1)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (heightChange >= 1 || !isReachedBottom(target as HTMLDivElement, target.scrollTop, 0, 1)) {
const isReachedBottom = isReachedBottom(target as HTMLDivElement, target.scrollTop, 0, 1);
if (!isReachedBottom) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants