From 6d3f49cb314b143556c2b4472ea9f025b8247a07 Mon Sep 17 00:00:00 2001
From: Ruslan Bayandinov <45530296+wazsone@users.noreply.github.com>
Date: Fri, 5 May 2023 11:43:31 +0400
Subject: [PATCH] [TSK-1292] Remember panel scroll positions (#3143)

Signed-off-by: Ruslan Bayandinov <wazsone@ya.ru>
---
 packages/panel/src/components/Panel.svelte | 78 +++++++++++++++++-----
 packages/ui/src/components/Scroller.svelte |  4 +-
 2 files changed, 63 insertions(+), 19 deletions(-)

diff --git a/packages/panel/src/components/Panel.svelte b/packages/panel/src/components/Panel.svelte
index c2f7bfb8c4..10705c2a33 100644
--- a/packages/panel/src/components/Panel.svelte
+++ b/packages/panel/src/components/Panel.svelte
@@ -1,23 +1,26 @@
 <!--
-// Copyright © 2020, 2021 Anticrm Platform Contributors.
-// Copyright © 2021 Hardcore Engineering Inc.
-// 
-// Licensed under the Eclipse Public License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License. You may
-// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
-// 
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// 
-// See the License for the specific language governing permissions and
-// limitations under the License.
--->
+    // Copyright © 2020, 2021 Anticrm Platform Contributors.
+    // Copyright © 2021 Hardcore Engineering Inc.
+    // 
+    // Licensed under the Eclipse Public License, Version 2.0 (the "License");
+    // you may not use this file except in compliance with the License. You may
+    // obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
+    // 
+    // Unless required by applicable law or agreed to in writing, software
+    // distributed under the License is distributed on an "AS IS" BASIS,
+    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    // 
+    // See the License for the specific language governing permissions and
+    // limitations under the License.
+    -->
 <script lang="ts">
+  import { afterUpdate } from 'svelte'
+  import { Writable, writable } from 'svelte/store'
+
   import activity from '@hcengineering/activity'
   import calendar from '@hcengineering/calendar'
-  import type { Doc } from '@hcengineering/core'
-  import type { Asset } from '@hcengineering/platform'
+  import { Doc } from '@hcengineering/core'
+  import { Asset } from '@hcengineering/platform'
   import {
     AnySvelteComponent,
     Component,
@@ -46,6 +49,40 @@
   export let useMaxWidth: boolean | undefined = undefined
   export let isFullSize = false
   export let embedded = false
+
+  let lastHref: string
+  let scroll: HTMLDivElement
+  let timer: number
+  let lastScrollHeight: number = -1
+  let count: number = 0
+
+  const waitCount = 10
+  const PanelScrollTop: Writable<Record<string, number>> = writable<Record<string, number>>({})
+
+  const startScrollHeightCheck = () => {
+    clearTimeout(timer)
+    timer = setTimeout(() => {
+      if (lastScrollHeight <= scroll.scrollHeight && count <= waitCount) {
+        count = lastScrollHeight < scroll.scrollHeight ? 0 : count + 1
+        lastScrollHeight = scroll.scrollHeight
+
+        startScrollHeightCheck()
+      } else {
+        lastScrollHeight = -1
+        count = 0
+
+        scroll.scrollTop = $PanelScrollTop[window.location.href]
+        $PanelScrollTop[window.location.href] = 0
+        lastHref = window.location.href
+      }
+    }, 1)
+  }
+
+  afterUpdate(() => {
+    if (lastHref !== window.location.href) {
+      startScrollHeightCheck()
+    }
+  })
 </script>
 
 <Panel
@@ -150,7 +187,14 @@
       {/if}
     </div>
   {:else}
-    <Scroller>
+    <Scroller
+      bind:divScroll={scroll}
+      on:divScrollTop={(event) => {
+        if (lastHref === window.location.href && event && event.detail !== $PanelScrollTop[lastHref]) {
+          $PanelScrollTop[lastHref] = event.detail
+        }
+      }}
+    >
       <div class="popupPanel-body__main-content py-8 clear-mins" class:max={useMaxWidth}>
         <slot />
         {#if !withoutActivity}
diff --git a/packages/ui/src/components/Scroller.svelte b/packages/ui/src/components/Scroller.svelte
index 380e15c4b3..af6b89b17d 100644
--- a/packages/ui/src/components/Scroller.svelte
+++ b/packages/ui/src/components/Scroller.svelte
@@ -62,7 +62,6 @@
   let divBox: HTMLElement
   let divBar: HTMLElement
   let divBarH: HTMLElement
-  let divScrollContainer: HTMLElement
   let isScrolling: 'vertical' | 'horizontal' | false = false
   let dXY: number
   let belowContent: number | undefined = undefined
@@ -88,6 +87,8 @@
 
   const checkBar = (): void => {
     if (divBar && divScroll) {
+      dispatch('divScrollTop', divScroll.scrollTop)
+
       const trackH = divScroll.clientHeight - shiftTop - shiftBottom - 4
       const scrollH = divScroll.scrollHeight
       const proc = scrollH / trackH
@@ -448,7 +449,6 @@
 <svelte:window on:resize={_resize} />
 
 <div
-  bind:this={divScrollContainer}
   class="scroller-container {orientir} {invertScroll ? 'invert' : 'normal'}"
   class:buttons={buttons === 'normal'}
   class:union={buttons === 'union'}