From 3e978a8244f599fc57a226dc201bd51076fdb711 Mon Sep 17 00:00:00 2001 From: morethanwords Date: Sat, 26 Sep 2020 01:47:43 +0300 Subject: [PATCH] Sticker fixes Some layout fixes --- src/components/animationIntersector.ts | 34 +-- .../emoticonsDropdown/tabs/stickers.ts | 15 +- src/components/horizontalMenu.ts | 15 +- src/components/sidebarRight/sharedMedia.ts | 8 +- src/helpers/mediaSizes.ts | 36 ++- src/lib/appManagers/appDialogsManager.ts | 2 +- src/lib/appManagers/appImManager.ts | 81 ++++-- src/lib/appManagers/appMessagesManager.ts | 5 +- src/lib/appManagers/appSidebarRight.ts | 22 +- src/lib/appManagers/appStateManager.ts | 18 +- src/lib/appManagers/appStickersManager.ts | 25 +- src/lib/lottieLoader.ts | 67 +++-- src/lib/rlottie/rlottie.worker.ts | 17 +- src/scss/partials/_chat.scss | 67 ++++- src/scss/partials/_chatBubble.scss | 10 +- src/scss/partials/_emojiDropdown.scss | 242 +++++++++--------- src/scss/partials/_leftSidebar.scss | 35 ++- src/scss/partials/_rightSidebar.scss | 22 +- src/scss/partials/_ripple.scss | 2 +- src/scss/partials/_sidebar.scss | 1 + src/scss/partials/pages/_chats.scss | 20 ++ src/scss/style.scss | 55 +++- 22 files changed, 492 insertions(+), 307 deletions(-) diff --git a/src/components/animationIntersector.ts b/src/components/animationIntersector.ts index 1c8ae277..5844f42b 100644 --- a/src/components/animationIntersector.ts +++ b/src/components/animationIntersector.ts @@ -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; } diff --git a/src/components/emoticonsDropdown/tabs/stickers.ts b/src/components/emoticonsDropdown/tabs/stickers.ts index c03d50ef..1eb032c5 100644 --- a/src/components/emoticonsDropdown/tabs/stickers.ts +++ b/src/components/emoticonsDropdown/tabs/stickers.ts @@ -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, diff --git a/src/components/horizontalMenu.ts b/src/components/horizontalMenu.ts index 2a58ef62..9d448a81 100644 --- a/src/components/horizontalMenu.ts +++ b/src/components/horizontalMenu.ts @@ -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(); diff --git a/src/components/sidebarRight/sharedMedia.ts b/src/components/sidebarRight/sharedMedia.ts index 75ca3c89..1df01e13 100644 --- a/src/components/sidebarRight/sharedMedia.ts +++ b/src/components/sidebarRight/sharedMedia.ts @@ -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', ``); - 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); diff --git a/src/helpers/mediaSizes.ts b/src/helpers/mediaSizes.ts index 4aafa600..6295f2e3 100644 --- a/src/helpers/mediaSizes.ts +++ b/src/helpers/mediaSizes.ts @@ -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 diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts index 575c9266..06cfcfcd 100644 --- a/src/lib/appManagers/appDialogsManager.ts +++ b/src/lib/appManagers/appDialogsManager.ts @@ -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) { diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index a59652ff..b06b60e6 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -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; 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)}; diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index 94dc8415..bb248b5b 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -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}); diff --git a/src/lib/appManagers/appSidebarRight.ts b/src/lib/appManagers/appSidebarRight.ts index 241bcea1..0f1f1c6c 100644 --- a/src/lib/appManagers/appSidebarRight.ts +++ b/src/lib/appManagers/appSidebarRight.ts @@ -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(); diff --git a/src/lib/appManagers/appStateManager.ts b/src/lib/appManagers/appStateManager.ts index eb684725..eea64ed0 100644 --- a/src/lib/appManagers/appStateManager.ts +++ b/src/lib/appManagers/appStateManager.ts @@ -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; + export class AppStateManager { public loaded: Promise; 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').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).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; diff --git a/src/lib/appManagers/appStickersManager.ts b/src/lib/appManagers/appStickersManager.ts index 402bbd77..87b6768a 100644 --- a/src/lib/appManagers/appStickersManager.ts +++ b/src/lib/appManagers/appStickersManager.ts @@ -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('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; } diff --git a/src/lib/lottieLoader.ts b/src/lib/lottieLoader.ts index caab0be6..3a3b0bec 100644 --- a/src/lib/lottieLoader.ts +++ b/src/lib/lottieLoader.ts @@ -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]; diff --git a/src/lib/rlottie/rlottie.worker.ts b/src/lib/rlottie/rlottie.worker.ts index 0ea361a9..ad3f822b 100644 --- a/src/lib/rlottie/rlottie.worker.ts +++ b/src/lib/rlottie/rlottie.worker.ts @@ -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')))); } diff --git a/src/scss/partials/_chat.scss b/src/scss/partials/_chat.scss index 3fefdfbe..e63f6ad8 100644 --- a/src/scss/partials/_chat.scss +++ b/src/scss/partials/_chat.scss @@ -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; diff --git a/src/scss/partials/_chatBubble.scss b/src/scss/partials/_chatBubble.scss index 5bdcf616..4f55897e 100644 --- a/src/scss/partials/_chatBubble.scss +++ b/src/scss/partials/_chatBubble.scss @@ -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; diff --git a/src/scss/partials/_emojiDropdown.scss b/src/scss/partials/_emojiDropdown.scss index 1fb32356..9affe825 100644 --- a/src/scss/partials/_emojiDropdown.scss +++ b/src/scss/partials/_emojiDropdown.scss @@ -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); } } diff --git a/src/scss/partials/_leftSidebar.scss b/src/scss/partials/_leftSidebar.scss index 7f06afcb..e81e4159 100644 --- a/src/scss/partials/_leftSidebar.scss +++ b/src/scss/partials/_leftSidebar.scss @@ -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; } } diff --git a/src/scss/partials/_rightSidebar.scss b/src/scss/partials/_rightSidebar.scss index 77319dbe..241854e5 100644 --- a/src/scss/partials/_rightSidebar.scss +++ b/src/scss/partials/_rightSidebar.scss @@ -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; diff --git a/src/scss/partials/_ripple.scss b/src/scss/partials/_ripple.scss index d42178f3..9d7ac0cc 100644 --- a/src/scss/partials/_ripple.scss +++ b/src/scss/partials/_ripple.scss @@ -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; diff --git a/src/scss/partials/_sidebar.scss b/src/scss/partials/_sidebar.scss index 0a335ce8..63c17def 100644 --- a/src/scss/partials/_sidebar.scss +++ b/src/scss/partials/_sidebar.scss @@ -40,6 +40,7 @@ &-close-button { padding-left: 10px; + overflow: inherit !important; } &-content { diff --git a/src/scss/partials/pages/_chats.scss b/src/scss/partials/pages/_chats.scss index 3fec8e7b..539b24d2 100644 --- a/src/scss/partials/pages/_chats.scss +++ b/src/scss/partials/pages/_chats.scss @@ -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; diff --git a/src/scss/style.scss b/src/scss/style.scss index e2c99e89..c14a246a 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -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 */