Sticker fixes
Some layout fixes
This commit is contained in:
parent
5ead8cca2f
commit
3e978a8244
@ -63,6 +63,24 @@ export class AnimationIntersector {
|
||||
return found;
|
||||
}
|
||||
|
||||
public removeAnimation(player: AnimationItem) {
|
||||
//console.log('destroy animation');
|
||||
const {el, animation} = player;
|
||||
animation.remove();
|
||||
|
||||
if(animation instanceof HTMLVideoElement) {
|
||||
animation.src = '';
|
||||
animation.load();
|
||||
}
|
||||
|
||||
for(const group in this.byGroups) {
|
||||
this.byGroups[group].findAndSplice(p => p == player);
|
||||
}
|
||||
|
||||
this.observer.unobserve(el);
|
||||
this.visible.delete(player);
|
||||
}
|
||||
|
||||
public addAnimation(animation: RLottiePlayer | HTMLVideoElement, group = '') {
|
||||
const player = {
|
||||
el: animation instanceof RLottiePlayer ? animation.el : animation,
|
||||
@ -98,20 +116,7 @@ export class AnimationIntersector {
|
||||
const {el, animation, group} = player;
|
||||
//return;
|
||||
if((destroy || (!isInDOM(el) && !this.lockedGroups[group]))/* && false */) {
|
||||
//console.log('destroy animation');
|
||||
animation.remove();
|
||||
|
||||
if(animation instanceof HTMLVideoElement) {
|
||||
animation.src = '';
|
||||
animation.load();
|
||||
}
|
||||
|
||||
for(const group in this.byGroups) {
|
||||
this.byGroups[group].findAndSplice(p => p == player);
|
||||
}
|
||||
|
||||
this.observer.unobserve(el);
|
||||
this.visible.delete(player);
|
||||
this.removeAnimation(player);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -161,7 +166,6 @@ export class AnimationIntersector {
|
||||
}
|
||||
|
||||
const animationIntersector = new AnimationIntersector();
|
||||
// @ts-ignore
|
||||
if(process.env.NODE_ENV == 'development') {
|
||||
(window as any).animationIntersector = animationIntersector;
|
||||
}
|
||||
|
@ -13,7 +13,8 @@ import apiManager from "../../../lib/mtproto/mtprotoworker";
|
||||
import StickyIntersector from "../../stickyIntersector";
|
||||
import appDocsManager, {MyDocument} from "../../../lib/appManagers/appDocsManager";
|
||||
import animationIntersector from "../../animationIntersector";
|
||||
import LazyLoadQueue, { LazyLoadQueueRepeat } from "../../lazyLoadQueue";
|
||||
import { LazyLoadQueueRepeat } from "../../lazyLoadQueue";
|
||||
import mediaSizes from "../../../helpers/mediaSizes";
|
||||
|
||||
export default class StickersTab implements EmoticonsTab {
|
||||
public content: HTMLElement;
|
||||
@ -81,6 +82,7 @@ export default class StickersTab implements EmoticonsTab {
|
||||
renderSticker(doc: MyDocument, div?: HTMLDivElement) {
|
||||
if(!div) {
|
||||
div = document.createElement('div');
|
||||
div.classList.add('grid-item');
|
||||
|
||||
if(doc.sticker == 2) {
|
||||
this.animatedDivs.add(div);
|
||||
@ -92,13 +94,10 @@ export default class StickersTab implements EmoticonsTab {
|
||||
}
|
||||
}
|
||||
|
||||
// * This will wrap only a thumb
|
||||
wrapSticker({
|
||||
doc,
|
||||
div,
|
||||
/* width: 80,
|
||||
height: 80,
|
||||
play: false,
|
||||
loop: false, */
|
||||
lazyLoadQueue: EmoticonsDropdown.lazyLoadQueue,
|
||||
group: EMOTICONSSTICKERGROUP,
|
||||
onlyThumb: doc.sticker == 2
|
||||
@ -183,12 +182,14 @@ export default class StickersTab implements EmoticonsTab {
|
||||
processVisibleDiv = (div: HTMLElement) => {
|
||||
const docID = div.dataset.docID;
|
||||
const doc = appDocsManager.getDoc(docID);
|
||||
|
||||
const size = mediaSizes.active.esgSticker.width;
|
||||
|
||||
const promise = wrapSticker({
|
||||
doc,
|
||||
div: div as HTMLDivElement,
|
||||
width: 80,
|
||||
height: 80,
|
||||
width: size,
|
||||
height: size,
|
||||
lazyLoadQueue: null,
|
||||
group: EMOTICONSSTICKERGROUP,
|
||||
onlyThumb: false,
|
||||
|
@ -31,7 +31,7 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
|
||||
let prevTabContent: HTMLElement = null;
|
||||
let prevId = -1;
|
||||
|
||||
const selectTab = (id: number) => {
|
||||
const selectTab = (id: number, animate = true) => {
|
||||
if(id == prevId) return false;
|
||||
|
||||
//console.log('selectTab id:', id);
|
||||
@ -39,7 +39,8 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
|
||||
const p = prevTabContent;
|
||||
const tabContent = content.children[id] as HTMLElement;
|
||||
|
||||
if(content.dataset.slider == 'none') {
|
||||
// * means animation isn't needed
|
||||
if(content.dataset.slider == 'none' || !animate) {
|
||||
if(p) {
|
||||
p.classList.remove('active');
|
||||
}
|
||||
@ -53,6 +54,10 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
|
||||
return;
|
||||
}
|
||||
|
||||
if(prevTabContent) {
|
||||
prevTabContent.classList.remove('to');
|
||||
}
|
||||
|
||||
const toRight = prevId < id;
|
||||
if(!tabContent) {
|
||||
//prevTabContent.classList.remove('active');
|
||||
@ -64,6 +69,8 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
|
||||
} else {
|
||||
slideNavigation(tabContent, prevTabContent, width, toRight);
|
||||
}
|
||||
|
||||
tabContent.classList.add('to');
|
||||
} else {
|
||||
tabContent.classList.add('active');
|
||||
}
|
||||
@ -76,6 +83,10 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
|
||||
p.style.filter = '';
|
||||
p.classList.remove('active');
|
||||
|
||||
if(tabContent) {
|
||||
tabContent.classList.remove('to');
|
||||
}
|
||||
|
||||
delete hideTimeouts[_prevId];
|
||||
|
||||
if(onTransitionEnd) onTransitionEnd();
|
||||
|
@ -324,7 +324,7 @@ export default class AppSharedMediaTab implements SliderTab {
|
||||
const media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document);
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('media-item');
|
||||
div.classList.add('grid-item');
|
||||
//console.log(message, photo);
|
||||
|
||||
const isPhoto = media._ == 'photo';
|
||||
@ -387,7 +387,7 @@ export default class AppSharedMediaTab implements SliderTab {
|
||||
const willHaveThumb = !isDownloaded && sizes && sizes[0].bytes;
|
||||
if(willHaveThumb) {
|
||||
thumb = new Image();
|
||||
thumb.classList.add('media-image', 'thumbnail');
|
||||
thumb.classList.add('grid-item-media', 'thumbnail');
|
||||
thumb.dataset.mid = '' + message.mid;
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, thumb, false, false);
|
||||
div.append(thumb);
|
||||
@ -396,7 +396,7 @@ export default class AppSharedMediaTab implements SliderTab {
|
||||
const needBlur = !isDownloaded || !willHaveThumb;
|
||||
const img = new Image();
|
||||
img.dataset.mid = '' + message.mid;
|
||||
img.classList.add('media-image');
|
||||
img.classList.add('grid-item-media');
|
||||
if(needBlur) img.style.opacity = '0';
|
||||
div.append(img);
|
||||
|
||||
@ -690,7 +690,7 @@ export default class AppSharedMediaTab implements SliderTab {
|
||||
for(let i = 0; i < 1500; ++i) {
|
||||
let div = document.createElement('div');
|
||||
div.insertAdjacentHTML('beforeend', `<img class="media-image" src="assets/img/camomile.jpg">`);
|
||||
div.classList.add('media-item');
|
||||
div.classList.add('grid-item');
|
||||
div.dataset.id = '' + (i / 3 | 0);
|
||||
//div.innerText = '' + (i / 3 | 0);
|
||||
this.sharedMedia.contentMedia.append(div);
|
||||
|
@ -1,10 +1,11 @@
|
||||
import EventListenerBase from "./eventListenerBase";
|
||||
|
||||
type Size = {width: number, height: number};
|
||||
type Size = Partial<{width: number, height: number}>;
|
||||
type Sizes = {
|
||||
regular: Size,
|
||||
webpage: Size,
|
||||
album: Size
|
||||
album: Size,
|
||||
esgSticker: Size
|
||||
};
|
||||
|
||||
export enum ScreenSize {
|
||||
@ -13,7 +14,7 @@ export enum ScreenSize {
|
||||
large
|
||||
}
|
||||
|
||||
const MOBILE_SIZE = 896;
|
||||
const MOBILE_SIZE = 600;
|
||||
const MEDIUM_SIZE = 1275;
|
||||
const LARGE_SIZE = 1680;
|
||||
|
||||
@ -21,7 +22,7 @@ class MediaSizes extends EventListenerBase<{
|
||||
changeScreen: (from: ScreenSize, to: ScreenSize) => void
|
||||
}> {
|
||||
private screenSizes: {key: ScreenSize, value: number}[] = [
|
||||
{key: ScreenSize.mobile, value: MOBILE_SIZE - 1},
|
||||
{key: ScreenSize.mobile, value: MOBILE_SIZE},
|
||||
{key: ScreenSize.medium, value: MEDIUM_SIZE},
|
||||
{key: ScreenSize.large, value: LARGE_SIZE}
|
||||
];
|
||||
@ -39,7 +40,8 @@ class MediaSizes extends EventListenerBase<{
|
||||
album: {
|
||||
width: 293,
|
||||
height: 0
|
||||
}
|
||||
},
|
||||
esgSticker: {}
|
||||
},
|
||||
desktop: {
|
||||
regular: {
|
||||
@ -53,7 +55,8 @@ class MediaSizes extends EventListenerBase<{
|
||||
album: {
|
||||
width: 451,
|
||||
height: 0
|
||||
}
|
||||
},
|
||||
esgSticker: {}
|
||||
}
|
||||
};
|
||||
|
||||
@ -80,17 +83,24 @@ class MediaSizes extends EventListenerBase<{
|
||||
}
|
||||
}
|
||||
|
||||
if(this.activeScreen != activeScreen && this.activeScreen !== undefined) {
|
||||
//console.log('changeScreen', this.activeScreen, activeScreen);
|
||||
this.setListenerResult('changeScreen', this.activeScreen, activeScreen);
|
||||
}
|
||||
|
||||
const wasScreen = this.activeScreen;
|
||||
this.activeScreen = activeScreen;
|
||||
|
||||
this.isMobile = this.activeScreen == ScreenSize.mobile;
|
||||
|
||||
this.active = this.isMobile ? this.sizes.handhelds : this.sizes.desktop;
|
||||
|
||||
//console.time('esg');
|
||||
const computedStyle = window.getComputedStyle(document.documentElement);
|
||||
this.active.esgSticker.width = parseFloat(computedStyle.getPropertyValue('--esg-sticker-size'));
|
||||
//console.timeEnd('esg');
|
||||
|
||||
if(wasScreen != activeScreen) {
|
||||
//console.log('changeScreen', this.activeScreen, activeScreen);
|
||||
|
||||
if(wasScreen !== undefined) {
|
||||
this.setListenerResult('changeScreen', this.activeScreen, activeScreen);
|
||||
}
|
||||
}
|
||||
|
||||
/* if(this.isMobile) {
|
||||
for(let i in this.active) {
|
||||
// @ts-ignore
|
||||
|
@ -618,7 +618,7 @@ export class AppDialogsManager {
|
||||
//selectTab(0);
|
||||
(this.folders.menu.firstElementChild.firstElementChild as HTMLElement).click();
|
||||
|
||||
/* false && */appStateManager.loadSavedState().then(() => {
|
||||
/* false && */appStateManager.getState().then(() => {
|
||||
return appMessagesManager.filtersStorage.getDialogFilters();
|
||||
}).then(filters => {
|
||||
for(const filterID in filters) {
|
||||
|
@ -8,7 +8,7 @@ import appProfileManager from "./appProfileManager";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
import appSidebarRight, { AppSidebarRight } from './appSidebarRight';
|
||||
import appSidebarRight, { AppSidebarRight, RIGHT_COLUMN_ACTIVE_CLASSNAME } from './appSidebarRight';
|
||||
|
||||
import { logger, LogLevels } from "../logger";
|
||||
import appMediaViewer from "./appMediaViewer";
|
||||
@ -46,9 +46,11 @@ import { isAndroid, isApple, isSafari } from '../../helpers/userAgent';
|
||||
|
||||
appSidebarLeft; // just to include
|
||||
|
||||
const testScroll = false;
|
||||
const TEST_SCROLL = false;
|
||||
|
||||
const ANIMATIONGROUP = 'chat';
|
||||
const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
|
||||
|
||||
const ANIMATION_GROUP = 'chat';
|
||||
|
||||
export class AppImManager {
|
||||
public columnEl = document.getElementById('column-center') as HTMLDivElement;
|
||||
@ -138,14 +140,20 @@ export class AppImManager {
|
||||
|
||||
private cleanupID = 0;
|
||||
|
||||
public selectTab = horizontalMenu(null, document.getElementById('main-columns'));
|
||||
private mainColumns: HTMLElement;
|
||||
public _selectTab: ReturnType<typeof horizontalMenu>;
|
||||
private closeBtn = this.topbar.querySelector('.sidebar-close-button') as HTMLButtonElement;
|
||||
public hideRightSidebar = false;
|
||||
|
||||
constructor() {
|
||||
this.log = logger('IM', LogLevels.log | LogLevels.warn | LogLevels.debug | LogLevels.error);
|
||||
this.chatInputC = new ChatInput();
|
||||
this.preloader = new ProgressivePreloader(null, false);
|
||||
|
||||
this.mainColumns = document.getElementById('main-columns');
|
||||
this._selectTab = horizontalMenu(null, this.mainColumns);
|
||||
this.selectTab(0);
|
||||
|
||||
parseMenuButtonsTo(this.menuButtons, this.columnEl.querySelector('.chat-more-button').firstElementChild.children);
|
||||
|
||||
this.chatAudio = new ChatAudio();
|
||||
@ -553,7 +561,19 @@ export class AppImManager {
|
||||
|
||||
this.closeBtn.addEventListener('click', (e) => {
|
||||
cancelEvent(e);
|
||||
this.setPeer(0);
|
||||
|
||||
if(mediaSizes.isMobile) {
|
||||
this.setPeer(0);
|
||||
} else {
|
||||
const isNowOpen = document.body.classList.toggle(LEFT_COLUMN_ACTIVE_CLASSNAME);
|
||||
|
||||
if(isNowOpen && document.body.classList.contains(RIGHT_COLUMN_ACTIVE_CLASSNAME)) {
|
||||
appSidebarRight.toggleSidebar(false, false);
|
||||
this.hideRightSidebar = isNowOpen;
|
||||
} else if(this.hideRightSidebar) {
|
||||
appSidebarRight.toggleSidebar(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.searchBtn.addEventListener('click', (e) => {
|
||||
@ -702,6 +722,12 @@ export class AppImManager {
|
||||
});
|
||||
}
|
||||
|
||||
public selectTab(id: number) {
|
||||
document.body.classList.toggle(LEFT_COLUMN_ACTIVE_CLASSNAME, id == 0);
|
||||
|
||||
this._selectTab(id, mediaSizes.isMobile);
|
||||
}
|
||||
|
||||
onDatePick = (timestamp: number) => {
|
||||
const peerID = this.peerID;
|
||||
appMessagesManager.requestHistory(peerID, 0, 2, -1, timestamp).then(history => {
|
||||
@ -773,7 +799,7 @@ export class AppImManager {
|
||||
|
||||
public loadMoreHistory(top: boolean, justLoad = false) {
|
||||
//this.log('loadMoreHistory', top);
|
||||
if(!this.peerID || testScroll || this.setPeerPromise || (top && this.getHistoryTopPromise) || (!top && this.getHistoryBottomPromise)) return;
|
||||
if(!this.peerID || TEST_SCROLL || this.setPeerPromise || (top && this.getHistoryTopPromise) || (!top && this.getHistoryBottomPromise)) return;
|
||||
|
||||
// warning, если иды только отрицательные то вниз не попадёт (хотя мб и так не попадёт)
|
||||
let history = Object.keys(this.bubbles).map(id => +id).filter(id => id > 0).sort((a, b) => a - b);
|
||||
@ -1000,6 +1026,10 @@ export class AppImManager {
|
||||
return !!this.bubbles[id]?.parentElement;
|
||||
})];
|
||||
}
|
||||
|
||||
/* public selectTab() {
|
||||
|
||||
} */
|
||||
|
||||
public setPeer(peerID: number, lastMsgID?: number) {
|
||||
//console.time('appImManager setPeer');
|
||||
@ -1012,11 +1042,18 @@ export class AppImManager {
|
||||
this.cleanup(true);
|
||||
this.peerID = $rootScope.selectedPeerID = 0;
|
||||
$rootScope.$broadcast('peer_changed', this.peerID);
|
||||
if(mediaSizes.isMobile) {
|
||||
this.selectTab(0);
|
||||
}
|
||||
|
||||
this.selectTab(0);
|
||||
|
||||
document.body.classList.add(LEFT_COLUMN_ACTIVE_CLASSNAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
document.body.classList.remove(LEFT_COLUMN_ACTIVE_CLASSNAME);
|
||||
if(this.hideRightSidebar) {
|
||||
appSidebarRight.toggleSidebar(true);
|
||||
this.hideRightSidebar = false;
|
||||
}
|
||||
|
||||
const samePeer = this.peerID == peerID;
|
||||
|
||||
@ -1107,14 +1144,12 @@ export class AppImManager {
|
||||
|
||||
this.preloader.attach(this.bubblesContainer);
|
||||
|
||||
if(mediaSizes.isMobile) {
|
||||
this.selectTab(1);
|
||||
}
|
||||
this.selectTab(1);
|
||||
}
|
||||
|
||||
//console.timeEnd('appImManager setPeer pre promise');
|
||||
|
||||
animationIntersector.lockGroup(ANIMATIONGROUP);
|
||||
animationIntersector.lockGroup(ANIMATION_GROUP);
|
||||
this.setPeerPromise = Promise.all([
|
||||
promise.then(() => {
|
||||
////this.log('setPeer removing preloader');
|
||||
@ -1127,16 +1162,14 @@ export class AppImManager {
|
||||
this.finishPeerChange();
|
||||
}
|
||||
|
||||
if(mediaSizes.isMobile) {
|
||||
this.selectTab(1);
|
||||
}
|
||||
this.selectTab(1);
|
||||
} else {
|
||||
this.preloader.detach();
|
||||
}
|
||||
|
||||
this.scrollable.container.append(this.chatInner);
|
||||
animationIntersector.unlockGroup(ANIMATIONGROUP);
|
||||
animationIntersector.checkAnimations(false, ANIMATIONGROUP/* , true */);
|
||||
animationIntersector.unlockGroup(ANIMATION_GROUP);
|
||||
animationIntersector.checkAnimations(false, ANIMATION_GROUP/* , true */);
|
||||
//this.scrollable.attachSentinels();
|
||||
//this.scrollable.container.insertBefore(this.chatInner, this.scrollable.container.lastElementChild);
|
||||
|
||||
@ -1305,7 +1338,7 @@ export class AppImManager {
|
||||
//bubble.remove();
|
||||
});
|
||||
|
||||
animationIntersector.checkAnimations(false, ANIMATIONGROUP);
|
||||
animationIntersector.checkAnimations(false, ANIMATION_GROUP);
|
||||
this.deleteEmptyDateGroups();
|
||||
}
|
||||
|
||||
@ -1844,7 +1877,7 @@ export class AppImManager {
|
||||
isOut: isOut,
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
middleware: null,
|
||||
group: ANIMATIONGROUP
|
||||
group: ANIMATION_GROUP
|
||||
});
|
||||
|
||||
preloader.attach(attachmentDiv, false);
|
||||
@ -1956,7 +1989,7 @@ export class AppImManager {
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
middleware: this.getMiddleware(),
|
||||
isOut,
|
||||
group: ANIMATIONGROUP
|
||||
group: ANIMATION_GROUP
|
||||
});
|
||||
//}
|
||||
} else {
|
||||
@ -2042,7 +2075,7 @@ export class AppImManager {
|
||||
div: attachmentDiv,
|
||||
middleware: this.getMiddleware(),
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
group: ANIMATIONGROUP,
|
||||
group: ANIMATION_GROUP,
|
||||
//play: !!message.pending || !multipleRender,
|
||||
play: true,
|
||||
loop: true,
|
||||
@ -2078,7 +2111,7 @@ export class AppImManager {
|
||||
isOut: isOut,
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
middleware: this.getMiddleware(),
|
||||
group: ANIMATIONGROUP
|
||||
group: ANIMATION_GROUP
|
||||
});
|
||||
}
|
||||
|
||||
@ -2390,7 +2423,7 @@ export class AppImManager {
|
||||
const realLoadCount = Object.keys(this.bubbles).length > 0 ? Math.max(40, pageCount) : pageCount;//const realLoadCount = 50;
|
||||
let loadCount = realLoadCount;
|
||||
|
||||
if(testScroll) {
|
||||
if(TEST_SCROLL) {
|
||||
//loadCount = 1;
|
||||
if(Object.keys(this.bubbles).length > 0)
|
||||
return {cached: false, promise: Promise.resolve(true)};
|
||||
|
@ -2471,8 +2471,9 @@ export class AppMessagesManager {
|
||||
|
||||
let messageWrapped = '';
|
||||
if(text) {
|
||||
if(text.length > 40) {
|
||||
text = text.substr(0, 35) + '...';
|
||||
// * 80 for chatlist in landscape orientation
|
||||
if(text.length > 80) {
|
||||
text = text.substr(0, 75) + '...';
|
||||
}
|
||||
|
||||
let entities = RichTextProcessor.parseEntities(text.replace(/\n/g, ' '), {noLinebreakers: true});
|
||||
|
@ -8,7 +8,7 @@ import AppPrivateSearchTab from "../../components/sidebarRight/search";
|
||||
import AppSharedMediaTab from "../../components/sidebarRight/sharedMedia";
|
||||
import AppForwardTab from "../../components/sidebarRight/forward";
|
||||
|
||||
const COLUMN_ACTIVE_CLASSNAME = 'is-right-column-shown';
|
||||
export const RIGHT_COLUMN_ACTIVE_CLASSNAME = 'is-right-column-shown';
|
||||
|
||||
const sharedMediaTab = new AppSharedMediaTab();
|
||||
const searchTab = new AppPrivateSearchTab();
|
||||
@ -54,7 +54,7 @@ export class AppSidebarRight extends SidebarSlider {
|
||||
this.gifsTab = gifsTab;
|
||||
|
||||
mediaSizes.addListener('changeScreen', (from, to) => {
|
||||
if(from !== undefined && to == ScreenSize.medium) {
|
||||
if(from !== undefined && to == ScreenSize.medium && from !== ScreenSize.mobile) {
|
||||
this.toggleSidebar(false);
|
||||
}
|
||||
});
|
||||
@ -78,10 +78,10 @@ export class AppSidebarRight extends SidebarSlider {
|
||||
return res;
|
||||
} */
|
||||
|
||||
public toggleSidebar(enable?: boolean) {
|
||||
public toggleSidebar(enable?: boolean, saveStatus = true) {
|
||||
/////this.log('sidebarEl', this.sidebarEl, enable, isElementInViewport(this.sidebarEl));
|
||||
|
||||
const active = document.body.classList.contains(COLUMN_ACTIVE_CLASSNAME);
|
||||
const active = document.body.classList.contains(RIGHT_COLUMN_ACTIVE_CLASSNAME);
|
||||
let willChange: boolean;
|
||||
if(enable !== undefined) {
|
||||
if(enable) {
|
||||
@ -97,19 +97,25 @@ export class AppSidebarRight extends SidebarSlider {
|
||||
|
||||
if(!willChange) return Promise.resolve();
|
||||
|
||||
if(saveStatus) {
|
||||
appImManager.hideRightSidebar = false;
|
||||
}
|
||||
|
||||
if(!active && !this.historyTabIDs.length) {
|
||||
this.selectTab(AppSidebarRight.SLIDERITEMSIDS.sharedMedia);
|
||||
}
|
||||
|
||||
document.body.classList.toggle(RIGHT_COLUMN_ACTIVE_CLASSNAME, enable);
|
||||
//console.log('sidebar selectTab', enable, willChange);
|
||||
if(mediaSizes.isMobile) {
|
||||
appImManager.selectTab(active ? 1 : 2);
|
||||
return Promise.resolve();
|
||||
appImManager._selectTab(active ? 1 : 2);
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, 250); // delay of slider animation
|
||||
});
|
||||
}
|
||||
|
||||
document.body.classList.toggle(COLUMN_ACTIVE_CLASSNAME, enable);
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, 200);
|
||||
setTimeout(resolve, 200); // delay for third column open
|
||||
});
|
||||
//return Promise.resolve();
|
||||
|
||||
|
@ -7,6 +7,7 @@ import appUsersManager from './appUsersManager';
|
||||
import apiUpdatesManager from './apiUpdatesManager';
|
||||
import { copy } from '../utils';
|
||||
import { logger } from '../logger';
|
||||
import type { AppStickersManager } from './appStickersManager';
|
||||
|
||||
const REFRESH_EVERY = 24 * 60 * 60 * 1000; // 1 day
|
||||
|
||||
@ -22,14 +23,18 @@ type State = Partial<{
|
||||
stateCreatedTime: number,
|
||||
recentEmoji: string[],
|
||||
topPeers: number[],
|
||||
recentSearch: number[]
|
||||
recentSearch: number[],
|
||||
stickerSets: AppStickersManager['stickerSets']
|
||||
}>;
|
||||
|
||||
const REFRESH_KEYS = ['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', 'stateCreatedTime',
|
||||
'updates', 'maxSeenMsgID', 'filters', 'topPeers'] as any as Array<keyof State>;
|
||||
|
||||
export class AppStateManager {
|
||||
public loaded: Promise<State>;
|
||||
private log = logger('STATE'/* , LogLevels.error */);
|
||||
|
||||
private state: State = {};
|
||||
private state: State;
|
||||
|
||||
constructor() {
|
||||
this.loadSavedState();
|
||||
@ -37,13 +42,12 @@ export class AppStateManager {
|
||||
|
||||
public loadSavedState() {
|
||||
if(this.loaded) return this.loaded;
|
||||
return this.loaded = new Promise((resolve, reject) => {
|
||||
return this.loaded = new Promise((resolve) => {
|
||||
AppStorage.get<State>('state').then((state) => {
|
||||
const time = Date.now();
|
||||
if((state?.stateCreatedTime ?? 0) + REFRESH_EVERY < time) {
|
||||
this.log('will refresh state', state.stateCreatedTime, time);
|
||||
(['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', 'stateCreatedTime',
|
||||
'updates', 'maxSeenMsgID', 'filters', 'topPeers'] as any as Array<keyof State>).forEach(key => {
|
||||
REFRESH_KEYS.forEach(key => {
|
||||
delete state[key];
|
||||
});
|
||||
//state = {};
|
||||
@ -131,10 +135,12 @@ export class AppStateManager {
|
||||
}
|
||||
|
||||
public getState() {
|
||||
return this.loadSavedState();
|
||||
return this.state === undefined ? this.loadSavedState() : Promise.resolve(this.state);
|
||||
}
|
||||
|
||||
public saveState() {
|
||||
if(this.state === undefined) return;
|
||||
|
||||
const messages: any[] = [];
|
||||
const dialogs: Dialog[] = [];
|
||||
const peers = this.state.peers;
|
||||
|
@ -1,12 +1,11 @@
|
||||
import AppStorage from '../storage';
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import appDocsManager from './appDocsManager';
|
||||
import { $rootScope } from '../utils';
|
||||
import { StickerSet, InputStickerSet, StickerSetCovered, MessagesRecentStickers, Document, InputFileLocation, MessagesStickerSet, PhotoSize } from '../../layer';
|
||||
import { Modify } from '../../types';
|
||||
import appStateManager from './appStateManager';
|
||||
|
||||
class AppStickersManager {
|
||||
export class AppStickersManager {
|
||||
private stickerSets: {
|
||||
[stickerSetID: string]: MessagesStickerSet
|
||||
} = {};
|
||||
@ -27,14 +26,14 @@ class AppStickersManager {
|
||||
};
|
||||
|
||||
constructor() {
|
||||
AppStorage.get<AppStickersManager['stickerSets']>('stickerSets').then((sets) => {
|
||||
if(sets) {
|
||||
for(let id in sets) {
|
||||
let set = sets[id];
|
||||
appStateManager.getState().then(({stickerSets}) => {
|
||||
if(stickerSets) {
|
||||
for(let id in stickerSets) {
|
||||
let set = stickerSets[id];
|
||||
this.saveStickers(set.documents);
|
||||
}
|
||||
|
||||
this.stickerSets = sets;
|
||||
this.stickerSets = stickerSets;
|
||||
}
|
||||
|
||||
//if(!this.stickerSets['emoji']) {
|
||||
@ -130,9 +129,8 @@ class AppStickersManager {
|
||||
}
|
||||
}
|
||||
|
||||
AppStorage.set({
|
||||
stickerSets: savedSets
|
||||
});
|
||||
appStateManager.pushToState('stickerSets', savedSets);
|
||||
appStateManager.saveState();
|
||||
|
||||
this.saveSetsTimeout = 0;
|
||||
}, 100);
|
||||
@ -258,14 +256,9 @@ class AppStickersManager {
|
||||
|
||||
return hashed.result.concat(foundSaved);
|
||||
}
|
||||
|
||||
public async cleanup() { // if logout
|
||||
await AppStorage.remove('stickerSets');
|
||||
}
|
||||
}
|
||||
|
||||
const appStickersManager = new AppStickersManager();
|
||||
// @ts-ignore
|
||||
if(process.env.NODE_ENV != 'production') {
|
||||
(window as any).appStickersManager = appStickersManager;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { logger, LogLevels } from "./logger";
|
||||
import animationIntersector from "../components/animationIntersector";
|
||||
import apiManager from "./mtproto/mtprotoworker";
|
||||
import { copy } from "./utils";
|
||||
import EventListenerBase from "../helpers/eventListenerBase";
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { isApple, isSafari } from "../helpers/userAgent";
|
||||
@ -21,7 +20,8 @@ type RLottieOptions = {
|
||||
height?: number,
|
||||
group?: string,
|
||||
noCache?: true,
|
||||
needUpscale?: true
|
||||
needUpscale?: true,
|
||||
skipRatio?: number
|
||||
};
|
||||
|
||||
export class RLottiePlayer extends EventListenerBase<{
|
||||
@ -36,6 +36,7 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
public curFrame: number;
|
||||
public frameCount: number;
|
||||
public fps: number;
|
||||
public skipDelta: number;
|
||||
|
||||
public worker: QueryableWorker;
|
||||
|
||||
@ -89,6 +90,16 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
}
|
||||
}
|
||||
|
||||
// Skip ratio
|
||||
let skipRatio: number;
|
||||
if(options.skipRatio !== undefined) skipRatio = options.skipRatio;
|
||||
else if(mediaSizes.isMobile && this.width < 100 && this.height < 100) {
|
||||
skipRatio = 0.5;
|
||||
}
|
||||
|
||||
this.skipDelta = skipRatio !== undefined ? 1 / skipRatio | 0 : 1;
|
||||
|
||||
// Pixel ratio
|
||||
const pixelRatio = window.devicePixelRatio;
|
||||
if(pixelRatio > 1) {
|
||||
//this.cachingEnabled = true;//this.width < 100 && this.height < 100;
|
||||
@ -108,8 +119,9 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
}
|
||||
}
|
||||
|
||||
// Cache frames params
|
||||
if(!options.noCache) {
|
||||
// проверка на размер уже после скейлинга, сделано для попапа и сайдбарfа, где стикеры 80х80 и 68х68, туда нужно 75%
|
||||
// проверка на размер уже после скейлинга, сделано для попапа и сайдбара, где стикеры 80х80 и 68х68, туда нужно 75%
|
||||
if(isApple && this.width > 100 && this.height > 100) {
|
||||
this.cachingDelta = 2; //2 // 50%
|
||||
} else if(this.width < 100 && this.height < 100) {
|
||||
@ -146,12 +158,8 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
this.worker.sendQuery(methodName, this.reqId, ...args);
|
||||
}
|
||||
|
||||
public loadFromData(json: any) {
|
||||
this.sendQuery('loadFromData', json, this.width, this.height, {
|
||||
paused: this.paused,
|
||||
direction: this.direction,
|
||||
speed: this.speed
|
||||
});
|
||||
public loadFromData(jsonString: string) {
|
||||
this.sendQuery('loadFromData', jsonString, this.width, this.height);
|
||||
}
|
||||
|
||||
public play() {
|
||||
@ -276,7 +284,10 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
}
|
||||
|
||||
private mainLoopForwards() {
|
||||
this.requestFrame(this.curFrame++);
|
||||
const frame = this.curFrame;
|
||||
this.curFrame += this.skipDelta;
|
||||
|
||||
this.requestFrame(frame);
|
||||
if(this.curFrame >= this.frameCount) {
|
||||
//this.playedTimes++;
|
||||
|
||||
@ -292,7 +303,10 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
}
|
||||
|
||||
private mainLoopBackwards() {
|
||||
this.requestFrame(this.curFrame--);
|
||||
const frame = this.curFrame;
|
||||
this.curFrame -= this.skipDelta;
|
||||
|
||||
this.requestFrame(frame);
|
||||
if(this.curFrame < 0) {
|
||||
//this.playedTimes++;
|
||||
|
||||
@ -311,7 +325,7 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
//window.cancelAnimationFrame(this.rafId);
|
||||
clearTimeout(this.rafId);
|
||||
|
||||
this.frInterval = 1000 / this.fps / this.speed;
|
||||
this.frInterval = 1000 / this.fps / this.speed * this.skipDelta;
|
||||
this.frThen = Date.now() - this.frInterval;
|
||||
|
||||
//console.trace('setMainLoop', this.frInterval, this.direction, this, JSON.stringify(this.listenerResults), this.listenerResults);
|
||||
@ -337,7 +351,7 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
this.curFrame = this.direction == 1 ? 0 : frameCount - 1;
|
||||
this.frameCount = frameCount;
|
||||
this.fps = fps;
|
||||
this.frInterval = 1000 / this.fps / this.speed;
|
||||
this.frInterval = 1000 / this.fps / this.speed * this.skipDelta;
|
||||
this.frThen = Date.now() - this.frInterval;
|
||||
//this.sendQuery('renderFrame', 0);
|
||||
|
||||
@ -522,9 +536,6 @@ class LottieLoader {
|
||||
|
||||
if(this.loadPromise) return this.loadPromise;
|
||||
|
||||
const onFrame = this.onFrame.bind(this);
|
||||
const onPlayerLoaded = this.onPlayerLoaded.bind(this);
|
||||
|
||||
return this.loadPromise = new Promise((resolve, reject) => {
|
||||
let remain = this.workersLimit;
|
||||
for(let i = 0; i < this.workersLimit; ++i) {
|
||||
@ -533,8 +544,9 @@ class LottieLoader {
|
||||
worker.addListener('ready', () => {
|
||||
this.log('worker #' + i + ' ready');
|
||||
|
||||
worker.addListener('frame', onFrame);
|
||||
worker.addListener('loaded', onPlayerLoaded);
|
||||
worker.addListener('frame', this.onFrame);
|
||||
worker.addListener('loaded', this.onPlayerLoaded);
|
||||
worker.addListener('error', this.onPlayerError);
|
||||
|
||||
--remain;
|
||||
if(!remain) {
|
||||
@ -630,7 +642,7 @@ class LottieLoader {
|
||||
return player;
|
||||
}
|
||||
|
||||
private onPlayerLoaded(reqId: number, frameCount: number, fps: number) {
|
||||
private onPlayerLoaded = (reqId: number, frameCount: number, fps: number) => {
|
||||
const rlPlayer = this.players[reqId];
|
||||
if(!rlPlayer) {
|
||||
this.log.warn('onPlayerLoaded on destroyed player:', reqId, frameCount);
|
||||
@ -642,9 +654,9 @@ class LottieLoader {
|
||||
//rlPlayer.addListener('firstFrame', () => {
|
||||
//animationIntersector.addAnimation(player, group);
|
||||
//}, true);
|
||||
}
|
||||
};
|
||||
|
||||
private onFrame(reqId: number, frameNo: number, frame: Uint8ClampedArray) {
|
||||
private onFrame = (reqId: number, frameNo: number, frame: Uint8ClampedArray) => {
|
||||
const rlPlayer = this.players[reqId];
|
||||
if(!rlPlayer) {
|
||||
this.log.warn('onFrame on destroyed player:', reqId, frameNo);
|
||||
@ -653,7 +665,18 @@ class LottieLoader {
|
||||
|
||||
rlPlayer.clamped = frame;
|
||||
rlPlayer.renderFrame(frame, frameNo);
|
||||
}
|
||||
};
|
||||
|
||||
private onPlayerError = (reqId: number, error: Error) => {
|
||||
const rlPlayer = this.players[reqId];
|
||||
if(rlPlayer) {
|
||||
// ! will need refactoring later, this is not the best way to remove the animation
|
||||
const animations = animationIntersector.getAnimations(rlPlayer.el);
|
||||
animations.forEach(animation => {
|
||||
animationIntersector.checkAnimation(animation, true, true);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
public onDestroy(reqId: number) {
|
||||
delete this.players[reqId];
|
||||
|
@ -32,6 +32,7 @@ export class RLottieItem {
|
||||
worker.Api.resize(this.handle, this.width, this.height);
|
||||
} catch(e) {
|
||||
console.error('init RLottieItem error:', e);
|
||||
reply('error', this.reqId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +61,7 @@ export class RLottieItem {
|
||||
} catch(e) {
|
||||
console.error('Render error:', e);
|
||||
this.dead = true;
|
||||
reply('error', this.reqId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,8 +98,8 @@ Module.onRuntimeInitialized = function() {
|
||||
worker.init();
|
||||
};
|
||||
|
||||
var items: {[reqId: string]: RLottieItem} = {};
|
||||
var queryableFunctions = {
|
||||
const items: {[reqId: string]: RLottieItem} = {};
|
||||
const queryableFunctions = {
|
||||
loadFromData: function(reqId: number, jsString: string, width: number, height: number) {
|
||||
try {
|
||||
// ! WARNING, с этой проверкой не все стикеры работают, например - ДУРКА
|
||||
@ -108,14 +110,19 @@ var queryableFunctions = {
|
||||
const match = jsString.match(/"fr":\s*?(\d+?),/);
|
||||
const frameRate = +match?.[1] || DEFAULT_FPS;
|
||||
|
||||
console.log('Rendering sticker:', reqId, frameRate, 'now rendered:', Object.keys(items).length);
|
||||
//console.log('Rendering sticker:', reqId, frameRate, 'now rendered:', Object.keys(items).length);
|
||||
|
||||
items[reqId] = new RLottieItem(reqId, jsString, width, height, frameRate);
|
||||
} catch(e) {
|
||||
console.error('Invalid file for sticker:', jsString);
|
||||
reply('error', reqId, e);
|
||||
}
|
||||
},
|
||||
destroy: function(reqId: number) {
|
||||
if(!items.hasOwnProperty(reqId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
items[reqId].destroy();
|
||||
delete items[reqId];
|
||||
},
|
||||
@ -143,10 +150,10 @@ function defaultReply(message: any) {
|
||||
* let the calling scope pass in the global scope object.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var _isSafari: boolean = null;
|
||||
let _isSafari: boolean = null;
|
||||
function isSafari(scope: any) {
|
||||
if(_isSafari == null) {
|
||||
var userAgent = scope.navigator ? scope.navigator.userAgent : null;
|
||||
const userAgent = scope.navigator ? scope.navigator.userAgent : null;
|
||||
_isSafari = !!scope.safari ||
|
||||
!!(userAgent && (/\b(iPad|iPhone|iPod)\b/.test(userAgent) || (!!userAgent.match('Safari') && !userAgent.match('Chrome'))));
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
border-left: 1px solid #DADCE0;
|
||||
border-right: 1px solid #DADCE0;
|
||||
|
||||
.sidebar-close-button, .menu-search {
|
||||
.menu-search {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -45,6 +45,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(no-floating-left-sidebar) {
|
||||
.sidebar-close-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* @include respond-to(wide-screens) {
|
||||
transition: .2s ease-in-out;
|
||||
align-self: start;
|
||||
@ -203,11 +209,22 @@
|
||||
#chat-input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: var(--messages-container-width);
|
||||
padding: .25rem 1rem 0;
|
||||
max-width: 100%;
|
||||
padding-top: .25rem;
|
||||
flex-direction: column;
|
||||
flex: 0 0 auto; /* Forces side columns to stay same width */
|
||||
position: relative;
|
||||
//overflow: hidden;
|
||||
|
||||
/* // * for no ESG top
|
||||
flex: 1 1 auto;
|
||||
height: calc(100% - 56px); */
|
||||
|
||||
@include respond-to(esg-top) {
|
||||
/* flex: 0 0 auto;
|
||||
height: auto; */
|
||||
max-width: var(--messages-container-width);
|
||||
}
|
||||
|
||||
@include respond-to(medium-screens) {
|
||||
width: calc(100% - var(--right-column-width));
|
||||
@ -222,21 +239,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
padding-left: .5rem;
|
||||
padding-right: .5rem;
|
||||
}
|
||||
|
||||
.chat-input-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
max-width: var(--messages-container-width);
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
padding: 0 .5rem;
|
||||
flex: 0 0 auto;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
padding-bottom: 21px;
|
||||
}
|
||||
}
|
||||
@ -313,6 +332,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
transition: .2s color, background-color .2s;
|
||||
}
|
||||
|
||||
#btn-record-cancel, #btn-send {
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
@ -452,6 +475,24 @@
|
||||
position: relative;
|
||||
flex: 3;
|
||||
|
||||
@include respond-to(floating-left-sidebar) {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
transform: translateZ(0);
|
||||
transition: transform var(--layer-transition);
|
||||
|
||||
body.is-left-column-shown & {
|
||||
transform: translate3d(26.5rem, 0, 0);
|
||||
|
||||
.sidebar-close-button {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-background {
|
||||
overflow: hidden;
|
||||
|
||||
@ -595,7 +636,6 @@
|
||||
|
||||
.btn-icon {
|
||||
display: block;
|
||||
transition: .2s color, background-color .2s;
|
||||
flex: 0 0 auto;
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
@ -619,7 +659,7 @@
|
||||
position: absolute !important;
|
||||
top: 100%;
|
||||
width: 100% !important;
|
||||
background: #fff;
|
||||
background: #fff !important;
|
||||
left: 0;
|
||||
// border-top: 1px solid #ccc;
|
||||
max-height: 100% !important;
|
||||
@ -916,9 +956,9 @@
|
||||
//overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
html.is-safari & {
|
||||
/* html.is-safari & > .scrollable {
|
||||
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); // fix safari overflow
|
||||
}
|
||||
} */
|
||||
|
||||
// ! WARNING, НЕЛЬЗЯ СТАВИТЬ ТРАНСФОРМ КРОМЕ TRANSLATEZ(0) НА БЛОК С OVERFLOW, ОН БУДЕТ ПРЫГАТЬ ВВЕРХ ПРИ ВКЛЮЧЕННОМ ПРАВИЛЕ И ЭТО НЕ ИСПРАВИТЬ JS'ОМ!
|
||||
@include respond-to(medium-screens) {
|
||||
@ -1117,7 +1157,8 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-shadow: 0px -1px 5px -1px rgba(0,0,0,0.21);
|
||||
box-shadow: 0px -1px 5px -1px rgba(0, 0, 0, .21);
|
||||
overflow: hidden;
|
||||
|
||||
.chat-search-count {
|
||||
margin-left: 8px;
|
||||
|
@ -797,10 +797,6 @@ $bubble-margin: .25rem;
|
||||
margin-right: -2px;
|
||||
}
|
||||
|
||||
.time {
|
||||
width: unset;
|
||||
}
|
||||
|
||||
/* @include respond-to(handhelds) {
|
||||
.preloader-container .you-spin-me-round {
|
||||
margin-top: 1px;
|
||||
@ -809,6 +805,12 @@ $bubble-margin: .25rem;
|
||||
} */
|
||||
}
|
||||
|
||||
.bubble__container .message.audio-message {
|
||||
.time {
|
||||
width: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
.message.contact-message {
|
||||
min-width: 200px;
|
||||
padding-left: 8px;
|
||||
|
@ -2,35 +2,37 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 282px;
|
||||
//height: 282px;
|
||||
height: unquote('min(282px, calc(var(--vh) * 100 - 135px))');
|
||||
background: #fff;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex: 0 0 auto;
|
||||
flex: 1 1 auto;
|
||||
max-height: 100%;
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
@include respond-to(esg-top) {
|
||||
position: absolute !important;
|
||||
left: 1rem;
|
||||
bottom: calc(85px);
|
||||
width: 420px !important;
|
||||
height: 420px;
|
||||
box-shadow: 0px 5px 10px 5px rgba(16, 35, 47, 0.14);
|
||||
max-height: 420px;
|
||||
box-shadow: 0px 5px 10px 5px rgba(16, 35, 47, .14);
|
||||
z-index: 3;
|
||||
border-radius: 10px;
|
||||
transition: all 0.2s ease-out;
|
||||
transition: all .2s ease-out;
|
||||
transform: scale(0);
|
||||
transform-origin: 0 100%;
|
||||
|
||||
&.active {
|
||||
transition: all 0.2s ease-in;
|
||||
transition: all .2s ease-in;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
/* @include respond-to(handhelds) {
|
||||
width: calc(100% + 1rem);
|
||||
margin-left: -.5rem;
|
||||
}
|
||||
} */
|
||||
|
||||
> .menu-horizontal {
|
||||
//font-weight: 500;
|
||||
@ -92,112 +94,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-category {
|
||||
//padding-top: 1px;
|
||||
position: relative;
|
||||
|
||||
.category-items {
|
||||
display: grid;
|
||||
grid-column-gap: 2.44px;
|
||||
grid-template-columns: repeat(9, 1fr);
|
||||
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.25rem;
|
||||
|
||||
> span {
|
||||
margin: 0;
|
||||
padding: 4px 4px;
|
||||
line-height: inherit;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
|
||||
.emoji {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
vertical-align: unset;
|
||||
}
|
||||
|
||||
html.no-touch &:hover {
|
||||
background-color: rgba(112, 117, 121, 0.08);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
//padding-top: 5px;
|
||||
}
|
||||
|
||||
/* &::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
} */
|
||||
}
|
||||
|
||||
.sticker-category {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
/* &.not-full::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
} */
|
||||
|
||||
.category-items {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
grid-column-gap: 1px;
|
||||
|
||||
> div {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* overflow: hidden; */
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
/* margin: 3.5px 0;
|
||||
margin-right: 6.25px; */
|
||||
padding: 1px 2.5px;
|
||||
justify-content: center;
|
||||
border-radius: 12px;
|
||||
padding: 0;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
// width: 64px;
|
||||
//height: 64px;
|
||||
height: 75px;
|
||||
justify-self: center;
|
||||
padding: 0;
|
||||
min-width: 64px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
html.no-touch &:hover {
|
||||
background-color: rgba(112, 117, 121, 0.08);
|
||||
}
|
||||
|
||||
/* &:nth-child(5n+5) {
|
||||
margin-right: 0;
|
||||
} */
|
||||
|
||||
> img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
animation: fadeIn .2s ease forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
min-height: 100%;
|
||||
/* display: flex; */
|
||||
@ -221,12 +117,16 @@
|
||||
flex: unset;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.category-items > span {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.category-items {
|
||||
grid-template-columns: repeat(auto-fill, 40px);
|
||||
|
||||
> span {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
justify-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.category-title {
|
||||
padding: 12px 6px 6px 10px;
|
||||
@ -238,7 +138,6 @@
|
||||
|
||||
.emoji-category .category-items {
|
||||
grid-column-gap: unset;
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,7 +146,7 @@
|
||||
.menu-horizontal {
|
||||
height: 48px;
|
||||
border-bottom: none;
|
||||
padding: 2px 2px 2px 2px;
|
||||
padding: 2px;
|
||||
width: 100%;
|
||||
box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, 0.21);
|
||||
z-index: 4;
|
||||
@ -258,6 +157,97 @@
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-category {
|
||||
//padding-top: 1px;
|
||||
position: relative;
|
||||
|
||||
.category-items {
|
||||
display: grid;
|
||||
grid-column-gap: 2.44px;
|
||||
grid-template-columns: repeat(auto-fill, 42px);
|
||||
justify-content: space-between;
|
||||
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.25rem;
|
||||
|
||||
> span {
|
||||
margin: 0;
|
||||
padding: 4px 4px;
|
||||
line-height: inherit;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
|
||||
.emoji {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
vertical-align: unset;
|
||||
}
|
||||
|
||||
html.no-touch &:hover {
|
||||
background-color: rgba(112, 117, 121, .08);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* &:first-child {
|
||||
//padding-top: 5px;
|
||||
} */
|
||||
|
||||
/* &::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
} */
|
||||
}
|
||||
|
||||
.sticker-category {
|
||||
position: relative;
|
||||
|
||||
/* &::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
} */
|
||||
|
||||
/* &.not-full::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
} */
|
||||
|
||||
.category-items {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, var(--esg-sticker-size)); // 64px
|
||||
grid-column-gap: 1px;
|
||||
justify-content: space-between;
|
||||
|
||||
> .grid-item {
|
||||
html.no-touch &:hover {
|
||||
border-radius: 12px;
|
||||
background-color: rgba(112, 117, 121, .08);
|
||||
}
|
||||
|
||||
/* &:nth-child(5n+5) {
|
||||
margin-right: 0;
|
||||
} */
|
||||
|
||||
> img, > .rlottie {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
> img {
|
||||
animation: fadeIn .2s ease forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-horizontal {
|
||||
li {
|
||||
border-radius: 50%;
|
||||
@ -273,7 +263,7 @@
|
||||
.menu-horizontal {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
box-shadow: 0px -2px 5px -1px rgba(0, 0, 0, 0.21);
|
||||
box-shadow: 0px -2px 5px -1px rgba(0, 0, 0, .21);
|
||||
|
||||
li {
|
||||
font-size: 1.5rem;
|
||||
@ -291,7 +281,7 @@
|
||||
&.active {
|
||||
.scrollable {
|
||||
padding: 0;
|
||||
box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, 0.21);
|
||||
box-shadow: 0px 1px 5px -1px rgba(0, 0, 0, .21);
|
||||
}
|
||||
|
||||
.menu-horizontal {
|
||||
@ -320,7 +310,7 @@
|
||||
|
||||
&.active {
|
||||
&:not(.tgico-recent) {
|
||||
background-color: rgba(112, 117, 121, 0.08);
|
||||
background-color: rgba(112, 117, 121, .08);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,30 @@
|
||||
// ! -.5 because of border-left and border-right on whole page
|
||||
max-width: calc(#{$large-screen} / 4);
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@include respond-to(floating-left-sidebar) {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: calc(var(--vh, 1vh) * 100);
|
||||
width: 26.5rem;
|
||||
transform: translate3d(-5rem, 0, 0);
|
||||
transition: transform var(--layer-transition);
|
||||
|
||||
body.is-left-column-shown & {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(no-floating-left-sidebar) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@include respond-to(before-medium-screens) {
|
||||
flex: 2;
|
||||
}
|
||||
@ -243,18 +267,15 @@
|
||||
content: $tgico-close;
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
transform: translateY(0px);
|
||||
position: fixed !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-menu-toggle {
|
||||
@include respond-to(handhelds) {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
bottom: 14px;
|
||||
right: 14px;
|
||||
|
||||
transform: translateY(0px);
|
||||
position: fixed !important;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +89,10 @@
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 13px;
|
||||
padding-bottom: 13px;
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
margin-top: 15px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,6 +267,7 @@
|
||||
> div {
|
||||
//height: 100%;
|
||||
position: relative;
|
||||
min-height: 150px;
|
||||
|
||||
/* > div:not(:empty) + .content-empty {
|
||||
display: none;
|
||||
@ -301,15 +302,6 @@
|
||||
padding: 7.5px 7.5px 7.5px 6.5px;
|
||||
}
|
||||
|
||||
.media-item {
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
//background-color: #000;
|
||||
}
|
||||
|
||||
.video-time {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
@ -323,13 +315,7 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.media-image {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
.grid-item-media {
|
||||
opacity: 1;
|
||||
transition: opacity .2s ease;
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
@include respond-to(until-floating-left-sidebar) {
|
||||
.chats-container ul li > .rp {
|
||||
.c-ripple {
|
||||
--ripple-duration: .2s;
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
&-close-button {
|
||||
padding-left: 10px;
|
||||
overflow: inherit !important;
|
||||
}
|
||||
|
||||
&-content {
|
||||
|
@ -61,6 +61,26 @@
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(floating-left-sidebar) {
|
||||
.main-column {
|
||||
height: calc(var(--vh, 1vh) * 100) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* @include respond-to(until-floating-left-sidebar) {
|
||||
.main-column {
|
||||
display: flex !important;
|
||||
|
||||
&.active {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
&.to {
|
||||
z-index: 4;
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
.preloader {
|
||||
width: 50px;
|
||||
|
@ -17,12 +17,14 @@ $lightgrey: #dadce0;
|
||||
$light: rgba($color-gray, 0.08);
|
||||
|
||||
//$small-screen: 720px;
|
||||
$small-screen: 896px;
|
||||
$small-screen: 600px;
|
||||
//$small-screen: 900px;
|
||||
$medium-screen: 1275px;
|
||||
$large-screen: 1680px;
|
||||
//$large-screen: 16800px;
|
||||
|
||||
$floating-left-sidebar: 925px;
|
||||
|
||||
@mixin respond-to($media) {
|
||||
@if $media == handhelds {
|
||||
@media only screen and (max-width: $small-screen) { @content; }
|
||||
@ -49,6 +51,20 @@ $large-screen: 1680px;
|
||||
@else if $media == not-handhelds {
|
||||
@media only screen and (min-width: $small-screen + 1) { @content; }
|
||||
}
|
||||
|
||||
@else if $media == floating-left-sidebar {
|
||||
@media only screen and (min-width: $small-screen + 1) and (max-width: $floating-left-sidebar) { @content; }
|
||||
}
|
||||
@else if $media == until-floating-left-sidebar {
|
||||
@media only screen and (max-width: $floating-left-sidebar) { @content; }
|
||||
}
|
||||
@else if $media == no-floating-left-sidebar {
|
||||
@media only screen and (min-width: $floating-left-sidebar + 1) { @content; }
|
||||
}
|
||||
|
||||
@else if $media == esg-top { // topbar + chat input + margin bottom + height of ESG
|
||||
@media only screen and (min-height: 570px) and (min-width: $small-screen + 1) { @content; }
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
@ -61,9 +77,11 @@ $large-screen: 1680px;
|
||||
--message-beside-button-margin: 2.875rem;
|
||||
--message-time-background: rgba(0, 0, 0, .35);
|
||||
--messages-container-width: 728px;
|
||||
--esg-sticker-size: 80px;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
--right-column-width: 100vw;
|
||||
--esg-sticker-size: 68px;
|
||||
}
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
@ -173,9 +191,9 @@ html, body {
|
||||
width: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
//@include respond-to(handhelds) {
|
||||
height: calc(var(--vh, 1vh) * 100);
|
||||
}
|
||||
//}
|
||||
|
||||
/* @include respond-to(handhelds) {
|
||||
//overflow-y: auto;
|
||||
@ -228,8 +246,8 @@ input, textarea, button, select, a, div {
|
||||
//}
|
||||
}
|
||||
|
||||
.disable-hover,
|
||||
.disable-hover * {
|
||||
.disable-hover/* ,
|
||||
.disable-hover * */ {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
@ -676,16 +694,12 @@ hr {
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
&:before, &:after {
|
||||
content: '';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
-webkit-transition: border .25s, background-color .25s, width .20s .1s, height .20s .1s, top .20s .1s, left .20s .1s;
|
||||
transition: border .25s, background-color .25s, width .20s .1s, height .20s .1s, top .20s .1s, left .20s .1s;
|
||||
}
|
||||
|
||||
@ -711,9 +725,7 @@ hr {
|
||||
border: 2px solid transparent;
|
||||
left: 6px;
|
||||
top: 10px;
|
||||
-webkit-transform: rotateZ(45deg);
|
||||
transform: rotateZ(45deg);
|
||||
-webkit-transform-origin: 100% 100%;
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
@ -726,9 +738,7 @@ hr {
|
||||
border-left: 2px solid transparent;
|
||||
border-right: 2px solid #fff;
|
||||
border-bottom: 2px solid #fff;
|
||||
-webkit-transform: rotateZ(45deg);
|
||||
transform: rotateZ(45deg);
|
||||
-webkit-transform-origin: 100% 100%;
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
@ -1132,6 +1142,25 @@ img.emoji {
|
||||
}
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
&-media {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-o-object-fit: cover;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
// *:not(input):not(textarea) {
|
||||
// -webkit-user-select: none; /* disable selection/Copy of UIWebView */
|
||||
// -webkit-touch-callout: none; /* disable the IOS popup when long-press on a link */
|
||||
|
Loading…
x
Reference in New Issue
Block a user