Browse Source

Sticker fixes

Some layout fixes
master
morethanwords 4 years ago
parent
commit
3e978a8244
  1. 34
      src/components/animationIntersector.ts
  2. 15
      src/components/emoticonsDropdown/tabs/stickers.ts
  3. 15
      src/components/horizontalMenu.ts
  4. 8
      src/components/sidebarRight/sharedMedia.ts
  5. 36
      src/helpers/mediaSizes.ts
  6. 2
      src/lib/appManagers/appDialogsManager.ts
  7. 81
      src/lib/appManagers/appImManager.ts
  8. 5
      src/lib/appManagers/appMessagesManager.ts
  9. 22
      src/lib/appManagers/appSidebarRight.ts
  10. 18
      src/lib/appManagers/appStateManager.ts
  11. 25
      src/lib/appManagers/appStickersManager.ts
  12. 67
      src/lib/lottieLoader.ts
  13. 17
      src/lib/rlottie/rlottie.worker.ts
  14. 67
      src/scss/partials/_chat.scss
  15. 10
      src/scss/partials/_chatBubble.scss
  16. 242
      src/scss/partials/_emojiDropdown.scss
  17. 35
      src/scss/partials/_leftSidebar.scss
  18. 22
      src/scss/partials/_rightSidebar.scss
  19. 2
      src/scss/partials/_ripple.scss
  20. 1
      src/scss/partials/_sidebar.scss
  21. 20
      src/scss/partials/pages/_chats.scss
  22. 55
      src/scss/style.scss

34
src/components/animationIntersector.ts

@ -63,6 +63,24 @@ export class AnimationIntersector { @@ -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 { @@ -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 { @@ -161,7 +166,6 @@ export class AnimationIntersector {
}
const animationIntersector = new AnimationIntersector();
// @ts-ignore
if(process.env.NODE_ENV == 'development') {
(window as any).animationIntersector = animationIntersector;
}

15
src/components/emoticonsDropdown/tabs/stickers.ts

@ -13,7 +13,8 @@ import apiManager from "../../../lib/mtproto/mtprotoworker"; @@ -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 { @@ -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 { @@ -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 { @@ -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,

15
src/components/horizontalMenu.ts

@ -31,7 +31,7 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick? @@ -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? @@ -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? @@ -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? @@ -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? @@ -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();

8
src/components/sidebarRight/sharedMedia.ts

@ -324,7 +324,7 @@ export default class AppSharedMediaTab implements SliderTab { @@ -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 { @@ -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 { @@ -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 { @@ -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);

36
src/helpers/mediaSizes.ts

@ -1,10 +1,11 @@ @@ -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 { @@ -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<{ @@ -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<{ @@ -39,7 +40,8 @@ class MediaSizes extends EventListenerBase<{
album: {
width: 293,
height: 0
}
},
esgSticker: {}
},
desktop: {
regular: {
@ -53,7 +55,8 @@ class MediaSizes extends EventListenerBase<{ @@ -53,7 +55,8 @@ class MediaSizes extends EventListenerBase<{
album: {
width: 451,
height: 0
}
},
esgSticker: {}
}
};
@ -80,17 +83,24 @@ class MediaSizes extends EventListenerBase<{ @@ -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

2
src/lib/appManagers/appDialogsManager.ts

@ -618,7 +618,7 @@ export class AppDialogsManager { @@ -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) {

81
src/lib/appManagers/appImManager.ts

@ -8,7 +8,7 @@ import appProfileManager from "./appProfileManager"; @@ -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'; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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)};

5
src/lib/appManagers/appMessagesManager.ts

@ -2471,8 +2471,9 @@ export class AppMessagesManager { @@ -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});

22
src/lib/appManagers/appSidebarRight.ts

@ -8,7 +8,7 @@ import AppPrivateSearchTab from "../../components/sidebarRight/search"; @@ -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 { @@ -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 { @@ -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 { @@ -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();

18
src/lib/appManagers/appStateManager.ts

@ -7,6 +7,7 @@ import appUsersManager from './appUsersManager'; @@ -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<{ @@ -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 { @@ -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 { @@ -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;

25
src/lib/appManagers/appStickersManager.ts

@ -1,12 +1,11 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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;
}

67
src/lib/lottieLoader.ts

@ -1,7 +1,6 @@ @@ -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 = { @@ -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<{ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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];

17
src/lib/rlottie/rlottie.worker.ts

@ -32,6 +32,7 @@ export class RLottieItem { @@ -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 { @@ -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() { @@ -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 = { @@ -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) { @@ -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'))));
}

67
src/scss/partials/_chat.scss

@ -34,7 +34,7 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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;

10
src/scss/partials/_chatBubble.scss

@ -797,10 +797,6 @@ $bubble-margin: .25rem; @@ -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; @@ -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;

242
src/scss/partials/_emojiDropdown.scss

@ -2,35 +2,37 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -238,7 +138,6 @@
.emoji-category .category-items {
grid-column-gap: unset;
grid-template-columns: repeat(8, 1fr);
}
}
}
@ -247,7 +146,7 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -320,7 +310,7 @@
&.active {
&:not(.tgico-recent) {
background-color: rgba(112, 117, 121, 0.08);
background-color: rgba(112, 117, 121, .08);
}
}

35
src/scss/partials/_leftSidebar.scss

@ -6,6 +6,30 @@ @@ -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 @@ @@ -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;
}
}

22
src/scss/partials/_rightSidebar.scss

@ -89,10 +89,10 @@ @@ -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 @@ @@ -267,6 +267,7 @@
> div {
//height: 100%;
position: relative;
min-height: 150px;
/* > div:not(:empty) + .content-empty {
display: none;
@ -301,15 +302,6 @@ @@ -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 @@ @@ -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;

2
src/scss/partials/_ripple.scss

@ -74,7 +74,7 @@ @@ -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;

1
src/scss/partials/_sidebar.scss

@ -40,6 +40,7 @@ @@ -40,6 +40,7 @@
&-close-button {
padding-left: 10px;
overflow: inherit !important;
}
&-content {

20
src/scss/partials/pages/_chats.scss

@ -61,6 +61,26 @@ @@ -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;

55
src/scss/style.scss

@ -17,12 +17,14 @@ $lightgrey: #dadce0; @@ -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; @@ -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; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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…
Cancel
Save