
Handle instant peer changing correctly Display unread badge only in chats Delay opening on ESG hover Lazy load sticker sets thumbs Fix onchanging profile info flick Hide shared media menu tabs Scroll on click to shared media tab Fix media tabs scroll position Fix voice messages playback in search on iOS Hover & play on waveform Better input fields border animation Don't lock scroll on horizontal scrollables if unnecessary Restrict editing & deleting outgoing messages Display avatars in notifications Open chat on notification click Don't close country selector on scrolling Select single country by enter Fix jumping text in context menus Changed preloader color
121 lines
4.1 KiB
TypeScript
121 lines
4.1 KiB
TypeScript
/*
|
|
* https://github.com/morethanwords/tweb
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
*/
|
|
|
|
import { whichChild } from "../helpers/dom";
|
|
import { TransitionSlider } from "./transition";
|
|
import { ScrollableX } from "./scrollable";
|
|
import rootScope from "../lib/rootScope";
|
|
import { fastRaf } from "../helpers/schedulers";
|
|
import { FocusDirection } from "../helpers/fastSmoothScroll";
|
|
import findUpAsChild from "../helpers/dom/findUpAsChild";
|
|
|
|
export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?: (id: number, tabContent: HTMLDivElement, animate: boolean) => void | boolean, onTransitionEnd?: () => void, transitionTime = 250, scrollableX?: ScrollableX) {
|
|
const selectTab = TransitionSlider(content, tabs || content.dataset.animation === 'tabs' ? 'tabs' : 'navigation', transitionTime, onTransitionEnd);
|
|
|
|
if(tabs) {
|
|
const proxy = new Proxy(selectTab, {
|
|
apply: (target, that, args) => {
|
|
const id = +args[0];
|
|
const animate = args[1] !== undefined ? args[1] : true;
|
|
|
|
const el = (tabs.querySelector(`[data-tab="${id}"]`) || tabs.children[id]) as HTMLElement;
|
|
selectTarget(el, id, animate);
|
|
}
|
|
});
|
|
|
|
const selectTarget = (target: HTMLElement, id: number, animate = true) => {
|
|
const tabContent = content.children[id] as HTMLDivElement;
|
|
|
|
if(onClick) {
|
|
const canChange = onClick(id, tabContent, animate);
|
|
if(canChange !== undefined && !canChange) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(scrollableX) {
|
|
scrollableX.scrollIntoViewNew(target.parentElement.children[id] as HTMLElement, 'center', undefined, undefined, animate ? undefined : FocusDirection.Static, transitionTime, 'x');
|
|
}
|
|
|
|
if(!rootScope.settings.animationsEnabled) {
|
|
animate = false;
|
|
}
|
|
|
|
const prevId = selectTab.prevId();
|
|
if(target.classList.contains('active') || id === prevId) {
|
|
return false;
|
|
}
|
|
|
|
const prev = tabs.querySelector(tagName.toLowerCase() + '.active') as HTMLElement;
|
|
|
|
fastRaf(() => {
|
|
prev && prev.classList.remove('active');
|
|
});
|
|
|
|
// stripe from ZINCHUK
|
|
if(useStripe && prevId !== -1 && animate) {
|
|
fastRaf(() => {
|
|
const indicator = target.querySelector('i')!;
|
|
const currentIndicator = target.parentElement.children[prevId].querySelector('i')!;
|
|
|
|
currentIndicator.classList.remove('animate');
|
|
indicator.classList.remove('animate');
|
|
|
|
// We move and resize our indicator so it repeats the position and size of the previous one.
|
|
const shiftLeft = currentIndicator.parentElement.parentElement.offsetLeft - indicator.parentElement.parentElement.offsetLeft;
|
|
const scaleFactor = currentIndicator.clientWidth / indicator.clientWidth;
|
|
indicator.style.transform = `translate3d(${shiftLeft}px, 0, 0) scale3d(${scaleFactor}, 1, 1)`;
|
|
|
|
//console.log(`translate3d(${shiftLeft}px, 0, 0) scale3d(${scaleFactor}, 1, 1)`);
|
|
|
|
requestAnimationFrame(() => {
|
|
// Now we remove the transform to let it animate to its own position and size.
|
|
indicator.classList.add('animate');
|
|
indicator.style.transform = 'none';
|
|
});
|
|
});
|
|
}
|
|
// stripe END
|
|
|
|
fastRaf(() => {
|
|
target.classList.add('active');
|
|
});
|
|
|
|
selectTab(id, animate);
|
|
};
|
|
|
|
const useStripe = !tabs.classList.contains('no-stripe');
|
|
|
|
//const tagName = tabs.classList.contains('menu-horizontal-div') ? 'BUTTON' : 'LI';
|
|
const tagName = tabs.firstElementChild.tagName;
|
|
tabs.addEventListener('click', function(e) {
|
|
let target = e.target as HTMLElement;
|
|
|
|
target = findUpAsChild(target, tabs);
|
|
|
|
//console.log('tabs click:', target);
|
|
|
|
if(!target) return false;
|
|
|
|
let id: number;
|
|
if(target.dataset.tab) {
|
|
id = +target.dataset.tab;
|
|
if(id === -1) {
|
|
return false;
|
|
}
|
|
} else {
|
|
id = whichChild(target);
|
|
}
|
|
|
|
selectTarget(target, id);
|
|
});
|
|
|
|
return proxy;
|
|
}
|
|
|
|
return selectTab;
|
|
}
|