From 4c4cf275ac58bc52a3afafb3b5171fb9ca658b4f Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Fri, 12 Mar 2021 02:39:57 +0400 Subject: [PATCH] Shared media: save scroll position --- src/components/appSearchSuper..ts | 93 +++++++++++++++---- .../sidebarRight/tabs/sharedMedia.ts | 22 +++++ src/scss/partials/_leftSidebar.scss | 4 + src/scss/partials/_rightSidebar.scss | 31 ++++++- 4 files changed, 131 insertions(+), 19 deletions(-) diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index 849c8150..4e803dbe 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -22,8 +22,9 @@ import { ripple } from "./ripple"; import Scrollable, { ScrollableX } from "./scrollable"; import { wrapDocument, wrapPhoto, wrapVideo } from "./wrappers"; import useHeavyAnimationCheck, { getHeavyAnimationPromise } from "../hooks/useHeavyAnimationCheck"; +import { isMobileSafari } from "../helpers/userAgent"; -const testScroll = false; +//const testScroll = false; export type SearchSuperType = MyInputMessagesFilter/* | 'chats' */; export type SearchSuperContext = { @@ -80,6 +81,8 @@ export default class AppSearchSuper { private searchGroupMedia: SearchGroup; + public goingHard: Partial<{[type in MyInputMessagesFilter]: {scrollTop: number, scrollHeight: number}}> = {}; + constructor(public types: {inputFilter: SearchSuperType, name: string}[], public scrollable: Scrollable, public searchGroups?: {[group in SearchGroupType]: SearchGroup}, public asChatList = false, public groupByMonth = true) { this.container = document.createElement('div'); this.container.classList.add('search-super'); @@ -116,10 +119,25 @@ export default class AppSearchSuper { for(const type of types) { const container = document.createElement('div'); - container.classList.add('search-super-container-' + type.name.toLowerCase()); + container.classList.add('search-super-container-' + type.name.toLowerCase()/* , 'scrollable', 'scrollable-y' */); const content = document.createElement('div'); - content.classList.add('search-super-content-' + type.name.toLowerCase()); + content.classList.add('search-super-content-' + type.name.toLowerCase()/* , 'scrollable', 'scrollable-y' */); + + //content.style.overflowY = 'hidden'; + /* container.style.overflow = 'visible'; + const v = 236; + content.style.top = (v * -1) + 'px'; + content.style.paddingTop = v + 'px'; + content.style.height = `calc(100% + ${v}px)`; + content.style.maxHeight = `calc(100% + ${v}px)`; + content.addEventListener('scroll', (e) => { + const scrollTop = content.scrollTop; + if(scrollTop <= v) { + //this.scrollable.scrollTop = scrollTop; + (this.container.previousElementSibling as HTMLElement).style.transform = `translateY(-${scrollTop}px)`; + } + }); */ container.append(content); @@ -141,21 +159,44 @@ export default class AppSearchSuper { } }; //this.scroll.attachSentinels(undefined, 400); - + this.selectTab = horizontalMenu(this.tabsMenu, this.tabsContainer, (id, tabContent) => { if(this.prevTabId === id) return; if(this.prevTabId !== -1) { this.onTransitionStart(); } - - this.type = this.types[id].inputFilter; + + this.goingHard[this.type] = {scrollTop: this.scrollable.scrollTop, scrollHeight: this.scrollable.scrollHeight}; + + const newType = this.types[id].inputFilter; this.tabSelected = tabContent.firstElementChild as HTMLDivElement; - if(this.prevTabId !== -1 && nav.offsetTop) { - this.scrollable.scrollTop -= nav.offsetTop; + if(this.goingHard[newType] === undefined) { + const rect = this.container.getBoundingClientRect(); + const rect2 = this.container.parentElement.getBoundingClientRect(); + const diff = rect.y - rect2.y; + + if(this.scrollable.scrollTop > diff) { + this.goingHard[newType] = {scrollTop: diff, scrollHeight: 0}; + } + } + + if(this.goingHard[newType]) { + const diff = this.goingHard[this.type].scrollTop - this.goingHard[newType].scrollTop; + //console.log('what you gonna do', this.goingHard, diff); + + if(diff/* && diff < 0 */) { + this.tabSelected.style.transform = `translateY(${diff}px)`; + } } + this.type = newType; + + /* if(this.prevTabId !== -1 && nav.offsetTop) { + this.scrollable.scrollTop -= nav.offsetTop; + } */ + /* this.log('setVirtualContainer', id, this.sharedMediaSelected, this.sharedMediaSelected.childElementCount); this.scroll.setVirtualContainer(this.sharedMediaSelected); */ @@ -167,6 +208,13 @@ export default class AppSearchSuper { this.prevTabId = id; }, () => { this.scrollable.onScroll(); + + //console.log('what y', this.tabSelected.style.transform); + if(this.goingHard[this.type] !== undefined) { + this.tabSelected.style.transform = ''; + this.scrollable.scrollTop = this.goingHard[this.type].scrollTop; + } + this.onTransitionEnd(); }, undefined, navScrollable); @@ -217,7 +265,18 @@ export default class AppSearchSuper { private onTransitionEnd = () => { // Jolly Cobra's // Workaround for scrollable content flickering during animation. const container = this.scrollable.container; + + if(isMobileSafari) { // ! safari doesn't respect sticky header, so it flicks when overflow is changing + container.style.display = 'none'; + } + container.style.overflowY = ''; + + if(isMobileSafari) { + void container.offsetLeft; // reflow + container.style.display = ''; + } + container.style.paddingRight = '0'; this.container.classList.remove('sliding'); }; @@ -747,9 +806,9 @@ export default class AppSearchSuper { } public load(single = false, justLoad = false) { - if(testScroll/* || 1 === 1 */) { - return; - } + // if(testScroll/* || 1 === 1 */) { + // return; + // } //return; @@ -950,6 +1009,7 @@ export default class AppSearchSuper { this.cleanupObj.cleaned = true; this.cleanupObj = {cleaned: false}; + this.goingHard = {}; } public cleanupHTML() { @@ -969,11 +1029,11 @@ export default class AppSearchSuper { if(!this.historyStorage || !this.historyStorage[type]) { const parent = this.tabs[type].parentElement; - if(!testScroll) { + //if(!testScroll) { if(!parent.querySelector('.preloader')) { putPreloader(parent, true); } - } + //} const empty = parent.querySelector('.content-empty'); if(empty) { @@ -984,8 +1044,9 @@ export default class AppSearchSuper { this.monthContainers = {}; this.searchGroupMedia.clear(); + this.scrollable.scrollTop = 0; - if(testScroll) { + /* if(testScroll) { for(let i = 0; i < 1500; ++i) { let div = document.createElement('div'); div.insertAdjacentHTML('beforeend', ``); @@ -994,7 +1055,7 @@ export default class AppSearchSuper { //div.innerText = '' + (i / 3 | 0); this.tabs.inputMessagesFilterPhotoVideo.append(div); } - } + } */ } // * will change .cleaned in cleanup() and new instance will be created @@ -1035,4 +1096,4 @@ export default class AppSearchSuper { this.cleanup(); } -} \ No newline at end of file +} diff --git a/src/components/sidebarRight/tabs/sharedMedia.ts b/src/components/sidebarRight/tabs/sharedMedia.ts index f6a2013a..144dda49 100644 --- a/src/components/sidebarRight/tabs/sharedMedia.ts +++ b/src/components/sidebarRight/tabs/sharedMedia.ts @@ -104,8 +104,30 @@ export default class AppSharedMediaTab implements SliderTab { const isSharedMedia = top <= HEADER_HEIGHT; closeIcon.classList.toggle('state-back', isSharedMedia); transition(+isSharedMedia); + + if(!isSharedMedia) { + this.searchSuper.goingHard = {}; + } + + //this.searchSuper.container.style.position = 'relative'; + //this.searchSuper.container.style.zIndex = '500'; + //this.scroll.container.style.overflowY = isSharedMedia ? 'hidden' : ''; + //this.scroll.container.style.zIndex = '1'; + //this.searchSuper.tabs[this.searchSuper.type].style.overflowY = isSharedMedia ? '' : 'hidden'; }; + //this.scroll.container.style.overflowY = 'hidden'; + + /* this.scroll.container.addEventListener('scroll', (e) => { + this.searchSuper.tabs[this.searchSuper.type].scrollTop = this.scroll.container.scrollTop + 1; + console.log('writings on the wall', e, this.scroll.container.scrollTop, this.searchSuper.scrollable.container.scrollTop); + }); */ + + /* this.scroll.container.addEventListener('wheel', (e) => { + cancelEvent(e); + this.scroll.scrollTop += e.deltaY; + }); */ + const transition = TransitionSlider(this.closeBtn.nextElementSibling as HTMLElement, 'slide-fade', 400, null, false); transition(0); diff --git a/src/scss/partials/_leftSidebar.scss b/src/scss/partials/_leftSidebar.scss index 186fbb74..d8b773ec 100644 --- a/src/scss/partials/_leftSidebar.scss +++ b/src/scss/partials/_leftSidebar.scss @@ -178,6 +178,10 @@ .search-super-tabs-scrollable { position: relative !important; + &:before { + display: none; + } + .menu-horizontal-div-item { flex: 1 0 auto !important; } diff --git a/src/scss/partials/_rightSidebar.scss b/src/scss/partials/_rightSidebar.scss index e20c405f..997be695 100644 --- a/src/scss/partials/_rightSidebar.scss +++ b/src/scss/partials/_rightSidebar.scss @@ -227,13 +227,17 @@ } #shared-media-container { - .search-super { + /* .search-super { top: 100%; min-height: calc((var(--vh, 1vh) * 100) - 100% - 56px); &.sliding { max-height: calc((var(--vh, 1vh) * 100) - 100% - 56px); } + } */ + .search-super { + top: 100%; + min-height: calc((var(--vh, 1vh) * 100) - 56px); } .sidebar-header .transition { @@ -271,8 +275,12 @@ } } - &.sliding { + /* &.sliding { max-height: 100%; + } */ + + &.sliding { + max-height: none !important; } &-tabs { @@ -287,10 +295,22 @@ box-shadow: none !important; position: -webkit-sticky !important; position: sticky !important; - top: -1px; + //top: -1px; + top: 0px; z-index: 2; background-color: #fff; + &:before { + position: absolute; + width: 100%; + height: 1px; + left: 0; + top: -1px; + background-color: inherit; + display: block; + content: " "; + } + .scrollable { position: relative; } @@ -324,6 +344,11 @@ } */ } + /* .scrollable-y { + height: auto; + position: absolute !important; + } */ + /* > div > div:not(.scroll-padding) { height: 100%; } */