diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index c9611cce..849c8150 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -80,7 +80,7 @@ export default class AppSearchSuper { private searchGroupMedia: SearchGroup; - constructor(public types: {inputFilter: SearchSuperType, name: string}[], public scrollable: Scrollable, public searchGroups?: {[group in SearchGroupType]: SearchGroup}, public asChatList = false) { + 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'); @@ -549,7 +549,7 @@ export default class AppSearchSuper { const method = append ? 'append' : 'prepend'; elemsToAppend.forEach(details => { const {element, message} = details; - const monthContainer = this.getMonthContainerByTimestamp(message.date, type); + const monthContainer = this.getMonthContainerByTimestamp(this.groupByMonth ? message.date : 0, type); element.classList.add('search-super-item'); element.dataset.mid = '' + message.mid; element.dataset.peerId = '' + message.peerId; diff --git a/src/components/horizontalMenu.ts b/src/components/horizontalMenu.ts index c83ade0c..77334720 100644 --- a/src/components/horizontalMenu.ts +++ b/src/components/horizontalMenu.ts @@ -1,4 +1,4 @@ -import { findUpTag, whichChild, findUpAsChild } from "../helpers/dom"; +import { whichChild, findUpAsChild } from "../helpers/dom"; import { TransitionSlider } from "./transition"; import { ScrollableX } from "./scrollable"; import rootScope from "../lib/rootScope"; @@ -105,4 +105,4 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick? } return selectTab; -} \ No newline at end of file +} diff --git a/src/components/scrollable.ts b/src/components/scrollable.ts index 61b7f696..eb2efbb5 100644 --- a/src/components/scrollable.ts +++ b/src/components/scrollable.ts @@ -52,6 +52,7 @@ export class ScrollableBase { protected onScroll: () => void; public isHeavyAnimationInProgress = false; + protected needCheckAfterAnimation = false; constructor(public el: HTMLElement, logPrefix = '', public container: HTMLElement = document.createElement('div')) { this.container.classList.add('scrollable'); @@ -74,11 +75,16 @@ export class ScrollableBase { this.isHeavyAnimationInProgress = true; if(this.onScrollMeasure) { + this.needCheckAfterAnimation = true; window.cancelAnimationFrame(this.onScrollMeasure); } }, () => { this.isHeavyAnimationInProgress = false; - this.onScroll(); + + if(this.needCheckAfterAnimation) { + this.onScroll(); + this.needCheckAfterAnimation = false; + } }); } @@ -146,6 +152,7 @@ export default class Scrollable extends ScrollableBase { window.cancelAnimationFrame(this.onScrollMeasure); } + this.needCheckAfterAnimation = true; return; } diff --git a/src/components/sidebarLeft/index.ts b/src/components/sidebarLeft/index.ts index 0ff80cf1..4cc89ef1 100644 --- a/src/components/sidebarLeft/index.ts +++ b/src/components/sidebarLeft/index.ts @@ -418,6 +418,7 @@ export class AppSidebarLeft extends SidebarSlider { this.toolsBtn.classList.remove('active'); this.backBtn.classList.add('active'); this.newBtnMenu.classList.add('is-hidden'); + this.toolsBtn.parentElement.firstElementChild.classList.toggle('state-back', true); transition(1); }; @@ -428,6 +429,7 @@ export class AppSidebarLeft extends SidebarSlider { this.backBtn.addEventListener('click', (e) => { this.toolsBtn.classList.add('active'); this.backBtn.classList.remove('active'); + this.toolsBtn.parentElement.firstElementChild.classList.toggle('state-back', false); transition(0); }); diff --git a/src/components/sidebarRight/index.ts b/src/components/sidebarRight/index.ts index 4e1fe27a..f6f797e9 100644 --- a/src/components/sidebarRight/index.ts +++ b/src/components/sidebarRight/index.ts @@ -103,7 +103,7 @@ export class AppSidebarRight extends SidebarSlider { this.selectTab(AppSidebarRight.SLIDERITEMSIDS.sharedMedia); } - const transitionTime = rootScope.settings.animationsEnabled ? mediaSizes.isMobile ? 250 : 200 : 0; + const transitionTime = rootScope.settings.animationsEnabled ? (mediaSizes.isMobile ? 250 : 200) : 0; const promise = pause(transitionTime); if(transitionTime) { dispatchHeavyAnimationEvent(promise, transitionTime); diff --git a/src/components/sidebarRight/tabs/sharedMedia.ts b/src/components/sidebarRight/tabs/sharedMedia.ts index a71d9a47..b0be4f8d 100644 --- a/src/components/sidebarRight/tabs/sharedMedia.ts +++ b/src/components/sidebarRight/tabs/sharedMedia.ts @@ -11,6 +11,9 @@ import AvatarElement from "../../avatar"; import Scrollable from "../../scrollable"; import { SliderTab } from "../../slider"; import CheckboxField from "../../checkbox"; +import { attachClickEvent, cancelEvent } from "../../../helpers/dom"; +import appSidebarRight from ".."; +import { TransitionSlider } from "../../transition"; let setText = (text: string, el: HTMLDivElement) => { window.requestAnimationFrame(() => { @@ -29,7 +32,7 @@ let setText = (text: string, el: HTMLDivElement) => { // TODO: отредактированное сообщение не изменится export default class AppSharedMediaTab implements SliderTab { public container: HTMLElement; - public closeBtn: HTMLElement; + public closeBtn: HTMLButtonElement; private peerId = 0; private threadId = 0; @@ -62,7 +65,8 @@ export default class AppSharedMediaTab implements SliderTab { public init() { this.container = document.getElementById('shared-media-container'); - this.closeBtn = this.container.querySelector('.sidebar-close-button'); + this.closeBtn = this.container.querySelector('.sidebar-header .btn-icon'); + this.closeBtn.classList.add('sidebar-close-button'); this.profileContentEl = this.container.querySelector('.profile-content'); this.profileElements = { @@ -86,7 +90,37 @@ export default class AppSharedMediaTab implements SliderTab { this.profileElements.notificationsRow.prepend(checkboxField.label); this.scroll = new Scrollable(this.container, 'SR', 400); - + + const HEADER_HEIGHT = 56; + const closeIcon = this.closeBtn.firstElementChild as HTMLElement; + this.scroll.onAdditionalScroll = () => { + const rect = this.searchSuper.nav.getBoundingClientRect(); + if(!rect.width) return; + + //console.log('daddy issues', this.searchSuper.nav.getBoundingClientRect()); + + const top = rect.top; + const isSharedMedia = top <= HEADER_HEIGHT; + closeIcon.classList.toggle('state-back', isSharedMedia); + transition(+isSharedMedia); + }; + + const transition = TransitionSlider(this.closeBtn.nextElementSibling as HTMLElement, 'slide-fade', 400, null, false); + + transition(0); + + attachClickEvent(this.closeBtn, (e) => { + if(this.closeBtn.firstElementChild.classList.contains('state-back')) { + this.scroll.scrollIntoViewNew(this.scroll.container.firstElementChild as HTMLElement, 'start'); + transition(0); + closeIcon.classList.remove('state-back'); + } else if(!this.scroll.isHeavyAnimationInProgress) { + appSidebarRight.closeTab(); + } + }); + + this.container.prepend(this.closeBtn.parentElement); + this.profileElements.notificationsCheckbox.addEventListener('change', () => { //let checked = this.profileElements.notificationsCheckbox.checked; appMessagesManager.mutePeer(this.peerId); @@ -134,7 +168,7 @@ export default class AppSharedMediaTab implements SliderTab { }, { inputFilter: 'inputMessagesFilterMusic', name: 'Music' - }], this.scroll); + }], this.scroll/* , undefined, undefined, false */); this.profileContentEl.append(this.searchSuper.container); } diff --git a/src/components/slider.ts b/src/components/slider.ts index 5d121cf0..c4d81347 100644 --- a/src/components/slider.ts +++ b/src/components/slider.ts @@ -2,6 +2,7 @@ import { attachClickEvent } from "../helpers/dom"; import { horizontalMenu } from "./horizontalMenu"; import ButtonIcon from "./buttonIcon"; import Scrollable from "./scrollable"; +import { TransitionSlider } from "./transition"; export interface SliderTab { onOpen?: () => void, @@ -86,7 +87,7 @@ export default class SidebarSlider { constructor(public sidebarEl: HTMLElement, public tabs: {[id: number]: SliderTab} = {}, private canHideFirst = false) { this.tabsContainer = this.sidebarEl.querySelector('.sidebar-slider'); - this._selectTab = horizontalMenu(null, this.tabsContainer as HTMLDivElement, null, null, TRANSITION_TIME); + this._selectTab = TransitionSlider(this.tabsContainer, 'navigation', TRANSITION_TIME); if(!canHideFirst) { this._selectTab(0); } diff --git a/src/components/transition.ts b/src/components/transition.ts index e26ec4a8..d23cb62a 100644 --- a/src/components/transition.ts +++ b/src/components/transition.ts @@ -46,7 +46,7 @@ function slideTabs(tabContent: HTMLElement, prevTabContent: HTMLElement, toRight }; } -export const TransitionSlider = (content: HTMLElement, type: 'tabs' | 'navigation' | 'zoom-fade' | 'none'/* | 'counter' */, transitionTime: number, onTransitionEnd?: (id: number) => void) => { +export const TransitionSlider = (content: HTMLElement, type: 'tabs' | 'navigation' | 'zoom-fade' | 'slide-fade' | 'none'/* | 'counter' */, transitionTime: number, onTransitionEnd?: (id: number) => void, isHeavy = true) => { let animationFunction: TransitionFunction = null; switch(type) { @@ -62,12 +62,12 @@ export const TransitionSlider = (content: HTMLElement, type: 'tabs' | 'navigatio content.dataset.animation = type; - return Transition(content, animationFunction, transitionTime, onTransitionEnd); + return Transition(content, animationFunction, transitionTime, onTransitionEnd, isHeavy); }; type TransitionFunction = (tabContent: HTMLElement, prevTabContent: HTMLElement, toRight: boolean) => void | (() => void); -const Transition = (content: HTMLElement, animationFunction: TransitionFunction, transitionTime: number, onTransitionEnd?: (id: number) => void) => { +const Transition = (content: HTMLElement, animationFunction: TransitionFunction, transitionTime: number, onTransitionEnd?: (id: number) => void, isHeavy = true) => { const onTransitionEndCallbacks: Map = new Map(); let animationDeferred: CancellablePromise; let animationStarted = 0; @@ -84,10 +84,16 @@ const Transition = (content: HTMLElement, animationFunction: TransitionFunction, const callback = onTransitionEndCallbacks.get(e.target as HTMLElement); if(callback) callback(); - if(!animationDeferred || e.target !== from) return; + if(e.target !== from) { + return; + } - animationDeferred.resolve(); - animationDeferred = undefined; + if(!animationDeferred && isHeavy) return; + + if(animationDeferred) { + animationDeferred.resolve(); + animationDeferred = undefined; + } if(onTransitionEnd) { onTransitionEnd(selectTab.prevId); @@ -180,12 +186,14 @@ const Transition = (content: HTMLElement, animationFunction: TransitionFunction, }); } - if(!animationDeferred) { - animationDeferred = deferredPromise(); - animationStarted = performance.now(); + if(isHeavy) { + if(!animationDeferred) { + animationDeferred = deferredPromise(); + animationStarted = performance.now(); + } + + dispatchHeavyAnimationEvent(animationDeferred, transitionTime * 2); } - - dispatchHeavyAnimationEvent(animationDeferred, transitionTime * 2); } self.prevId = id; diff --git a/src/helpers/blur.ts b/src/helpers/blur.ts index 50d67c48..12c3c98d 100644 --- a/src/helpers/blur.ts +++ b/src/helpers/blur.ts @@ -1,10 +1,12 @@ -import DEBUG from '../config/debug'; +import _DEBUG from '../config/debug'; import fastBlur from '../vendor/fastBlur'; import pushHeavyTask from './heavyQueue'; const RADIUS = 2; const ITERATIONS = 2; +const DEBUG = _DEBUG && false; + function processBlur(dataUri: string, radius: number, iterations: number) { return new Promise((resolve) => { const img = new Image(); diff --git a/src/helpers/fastSmoothScroll.ts b/src/helpers/fastSmoothScroll.ts index b52ffce2..be1229d5 100644 --- a/src/helpers/fastSmoothScroll.ts +++ b/src/helpers/fastSmoothScroll.ts @@ -43,7 +43,7 @@ export default function fastSmoothScroll( return Promise.resolve(); */ } - if(axis === 'y' && isInDOM(element) && container.getBoundingClientRect) { + if(axis === 'y' && element !== container && isInDOM(element) && container.getBoundingClientRect) { const elementRect = element.getBoundingClientRect(); const containerRect = container.getBoundingClientRect(); diff --git a/src/index.hbs b/src/index.hbs index 5eb1af2c..07321ac7 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -98,17 +98,18 @@