From 6cbb497a016d11660b7640d6dea0cbfb9c25a8c0 Mon Sep 17 00:00:00 2001 From: Kristina <kristin.fefelova@gmail.com> Date: Thu, 29 Feb 2024 18:38:22 +0400 Subject: [PATCH] UBERF-5712: fix jumping when scroll in bottom and add auto scroll to new content (#4830) Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com> --- .../reactions/ReactionsPresenter.svelte | 8 +-- .../src/components/Channel.svelte | 2 + .../src/components/ChannelScrollView.svelte | 51 ++++++++++++++++++- .../src/components/ChannelView.svelte | 2 +- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/plugins/activity-resources/src/components/reactions/ReactionsPresenter.svelte b/plugins/activity-resources/src/components/reactions/ReactionsPresenter.svelte index 4614fbc6da..1a9925fdce 100644 --- a/plugins/activity-resources/src/components/reactions/ReactionsPresenter.svelte +++ b/plugins/activity-resources/src/components/reactions/ReactionsPresenter.svelte @@ -30,14 +30,16 @@ $: hasReactions = object?.reactions && object.reactions > 0 $: if (object && hasReactions) { - reactionsQuery.query(activity.class.Reaction, { attachedTo: object._id }, (res?: Reaction[]) => { - reactions = res || [] + reactionsQuery.query(activity.class.Reaction, { attachedTo: object._id }, (res: Reaction[]) => { + reactions = res }) + } else { + reactionsQuery.unsubscribe() } const handleClick = (ev: CustomEvent) => { if (readonly) return - updateDocReactions(client, reactions, object, ev.detail) + void updateDocReactions(client, reactions, object, ev.detail) } </script> diff --git a/plugins/chunter-resources/src/components/Channel.svelte b/plugins/chunter-resources/src/components/Channel.svelte index 505567cea3..15c7374bd7 100644 --- a/plugins/chunter-resources/src/components/Channel.svelte +++ b/plugins/chunter-resources/src/components/Channel.svelte @@ -27,6 +27,7 @@ export let context: DocNotifyContext export let object: Doc | undefined export let filters: Ref<ActivityMessagesFilter>[] = [] + export let isAsideOpened = false const client = getClient() const hierarchy = client.getHierarchy() @@ -70,6 +71,7 @@ {selectedMessageId} {collection} provider={dataProvider} + {isAsideOpened} loadMoreAllowed={!isDocChannel} /> {/if} diff --git a/plugins/chunter-resources/src/components/ChannelScrollView.svelte b/plugins/chunter-resources/src/components/ChannelScrollView.svelte index d3ac2ab699..2bcb5e074c 100644 --- a/plugins/chunter-resources/src/components/ChannelScrollView.svelte +++ b/plugins/chunter-resources/src/components/ChannelScrollView.svelte @@ -28,7 +28,7 @@ } from '@hcengineering/activity-resources' import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources' import { get } from 'svelte/store' - import { tick } from 'svelte' + import { tick, beforeUpdate, afterUpdate } from 'svelte' import ActivityMessagesSeparator from './ChannelMessagesSeparator.svelte' import { filterChatMessages, getClosestDate, readChannelMessages } from '../utils' @@ -49,6 +49,7 @@ export let showEmbedded = false export let skipLabels = false export let loadMoreAllowed = true + export let isAsideOpened = false const dateSelectorHeight = 30 const headerHeight = 50 @@ -83,6 +84,8 @@ let messagesCount = 0 + let wasAsideOpened = isAsideOpened + $: messages = $messagesStore $: isLoading = $isLoadingStore @@ -90,7 +93,7 @@ $: notifyContext = $contextByDocStore.get(objectId) - $: filterChatMessages(messages, filters, objectClass, selectedFilters).then((filteredMessages) => { + $: void filterChatMessages(messages, filters, objectClass, selectedFilters).then((filteredMessages) => { displayMessages = filteredMessages }) @@ -224,10 +227,12 @@ } else if (shouldLoadMoreDown() && provider.canLoadMore('forward', messages[messages.length - 1]?.createdOn)) { shouldScrollToNew = false void provider.loadMore('forward', messages[messages.length - 1]?.createdOn, limit) + isScrollAtBottom = false } } function handleScroll ({ autoScrolling }: ScrollParams) { + saveScrollPosition() if (autoScrolling) { return } @@ -458,6 +463,48 @@ loadMore() } } + + let prevScrollHeight = 0 + let isScrollAtBottom = false + + function saveScrollPosition (): void { + if (!scrollElement) { + return + } + + const { offsetHeight, scrollHeight, scrollTop } = scrollElement + + prevScrollHeight = scrollHeight + isScrollAtBottom = scrollHeight === scrollTop + offsetHeight + } + + beforeUpdate(() => { + if (!scrollElement) return + + if (scrollElement.scrollHeight === scrollElement.clientHeight) { + isScrollAtBottom = true + } + }) + + afterUpdate(() => { + if (!scrollElement) return + const { scrollHeight } = scrollElement + + if (!isInitialScrolling && prevScrollHeight < scrollHeight && isScrollAtBottom) { + scrollToBottom() + } + }) + + async function compensateAside (isOpened: boolean) { + if (!isInitialScrolling && isScrollAtBottom && !wasAsideOpened && isOpened) { + await wait() + scrollToBottom() + } + + wasAsideOpened = isOpened + } + + $: void compensateAside(isAsideOpened) </script> {#if isLoading} diff --git a/plugins/chunter-resources/src/components/ChannelView.svelte b/plugins/chunter-resources/src/components/ChannelView.svelte index 8083294e92..1f5b3dec96 100644 --- a/plugins/chunter-resources/src/components/ChannelView.svelte +++ b/plugins/chunter-resources/src/components/ChannelView.svelte @@ -77,7 +77,7 @@ <div class="popupPanel-body" class:asideShown={withAside && isAsideShown}> <div class="popupPanel-body__main"> {#key context._id} - <ChannelComponent {context} {object} {filters} /> + <ChannelComponent {context} {object} {filters} isAsideOpened={(withAside && isAsideShown) || isThreadOpened} /> {/key} </div>