Voice recorder check support

Delay for open cached chat
This commit is contained in:
morethanwords 2020-06-06 13:53:23 +03:00
parent c7b7427f19
commit 6356b9152c
14 changed files with 260 additions and 175 deletions

View File

@ -59,14 +59,7 @@ export class ChatInput {
public editMsgID = 0; public editMsgID = 0;
public noWebPage = false; public noWebPage = false;
private recorder = new Recorder({ private recorder: any;
//encoderBitRate: 32,
//encoderPath: "../dist/encoderWorker.min.js",
encoderSampleRate: 48000,
monitorGain: 0,
numberOfChannels: 1,
recordingGain: 1
});
private recording = false; private recording = false;
private recordCanceled = false; private recordCanceled = false;
private recordTimeEl = this.inputContainer.querySelector('.record-time') as HTMLDivElement; private recordTimeEl = this.inputContainer.querySelector('.record-time') as HTMLDivElement;
@ -92,6 +85,21 @@ export class ChatInput {
this.replyElements.titleEl = this.replyElements.container.querySelector('.reply-title') as HTMLDivElement; this.replyElements.titleEl = this.replyElements.container.querySelector('.reply-title') as HTMLDivElement;
this.replyElements.subtitleEl = this.replyElements.container.querySelector('.reply-subtitle') as HTMLDivElement; this.replyElements.subtitleEl = this.replyElements.container.querySelector('.reply-subtitle') as HTMLDivElement;
try {
this.recorder = new Recorder({
//encoderBitRate: 32,
//encoderPath: "../dist/encoderWorker.min.js",
encoderSampleRate: 48000,
monitorGain: 0,
numberOfChannels: 1,
recordingGain: 1
});
} catch(err) {
this.btnSend.classList.remove('tgico-microphone2');
this.btnSend.classList.add('tgico-send');
console.error('Recorder constructor error:', err);
}
this.messageInput.addEventListener('keydown', (e: KeyboardEvent) => { this.messageInput.addEventListener('keydown', (e: KeyboardEvent) => {
if(e.key == 'Enter') { if(e.key == 'Enter') {
/* if(e.ctrlKey || e.metaKey) { /* if(e.ctrlKey || e.metaKey) {
@ -144,13 +152,17 @@ export class ChatInput {
if(!value.trim() && !this.serializeNodes(Array.from(this.messageInput.childNodes)).trim()) { if(!value.trim() && !this.serializeNodes(Array.from(this.messageInput.childNodes)).trim()) {
this.messageInput.innerHTML = ''; this.messageInput.innerHTML = '';
this.btnSend.classList.remove('tgico-send'); if(this.recorder) {
this.btnSend.classList.add('tgico-microphone2'); this.btnSend.classList.remove('tgico-send');
this.btnSend.classList.add('tgico-microphone2');
}
appMessagesManager.setTyping('sendMessageCancelAction'); appMessagesManager.setTyping('sendMessageCancelAction');
} else if(!this.btnSend.classList.contains('tgico-send')) { } else if(!this.btnSend.classList.contains('tgico-send') || !this.recorder) {
this.btnSend.classList.add('tgico-send'); if(this.recorder) {
this.btnSend.classList.remove('tgico-microphone2'); this.btnSend.classList.add('tgico-send');
this.btnSend.classList.remove('tgico-microphone2');
}
let time = Date.now(); let time = Date.now();
if(time - this.lastTimeType >= 6000) { if(time - this.lastTimeType >= 6000) {
@ -462,7 +474,7 @@ export class ChatInput {
}); });
this.btnSend.addEventListener('click', () => { this.btnSend.addEventListener('click', () => {
if(this.btnSend.classList.contains('tgico-send')) { if(this.btnSend.classList.contains('tgico-send') || !this.recorder) {
if(this.recording) { if(this.recording) {
this.recorder.stop(); this.recorder.stop();
} else { } else {
@ -527,74 +539,76 @@ export class ChatInput {
opusDecodeController.setKeepAlive(false); opusDecodeController.setKeepAlive(false);
}); });
this.recorder.onstop = () => { if(this.recorder) {
this.recording = false; this.recorder.onstop = () => {
this.inputContainer.classList.remove('is-recording'); this.recording = false;
this.btnSend.classList.remove('tgico-send'); this.inputContainer.classList.remove('is-recording');
this.recordRippleEl.style.transform = ''; this.btnSend.classList.remove('tgico-send');
}; this.recordRippleEl.style.transform = '';
};
this.recorder.ondataavailable = (typedArray: Uint8Array) => {
if(this.recordCanceled) return; this.recorder.ondataavailable = (typedArray: Uint8Array) => {
if(this.recordCanceled) return;
const duration = (Date.now() - this.recordStartTime) / 1000 | 0;
const dataBlob = new Blob([typedArray], {type: 'audio/ogg'}); const duration = (Date.now() - this.recordStartTime) / 1000 | 0;
/* const fileName = new Date().toISOString() + ".opus"; const dataBlob = new Blob([typedArray], {type: 'audio/ogg'});
console.log('Recorder data received', typedArray, dataBlob); */ /* const fileName = new Date().toISOString() + ".opus";
console.log('Recorder data received', typedArray, dataBlob); */
/* var url = URL.createObjectURL( dataBlob );
/* var url = URL.createObjectURL( dataBlob );
var audio = document.createElement('audio');
audio.controls = true; var audio = document.createElement('audio');
audio.src = url; audio.controls = true;
audio.src = url;
var link = document.createElement('a');
link.href = url; var link = document.createElement('a');
link.download = fileName; link.href = url;
link.innerHTML = link.download; link.download = fileName;
link.innerHTML = link.download;
var li = document.createElement('li');
li.appendChild(link); var li = document.createElement('li');
li.appendChild(audio); li.appendChild(link);
li.appendChild(audio);
document.body.append(li);
document.body.append(li);
return; */
return; */
let perf = performance.now();
opusDecodeController.decode(typedArray, true).then(result => { let perf = performance.now();
console.log('WAVEFORM!:', /* waveform, */performance.now() - perf); opusDecodeController.decode(typedArray, true).then(result => {
console.log('WAVEFORM!:', /* waveform, */performance.now() - perf);
opusDecodeController.setKeepAlive(false);
opusDecodeController.setKeepAlive(false);
let peerID = appImManager.peerID;
// тут objectURL ставится уже с audio/wav let peerID = appImManager.peerID;
appMessagesManager.sendFile(peerID, dataBlob, { // тут objectURL ставится уже с audio/wav
isVoiceMessage: true, appMessagesManager.sendFile(peerID, dataBlob, {
isMedia: true, isVoiceMessage: true,
duration, isMedia: true,
waveform: result.waveform, duration,
objectURL: result.url waveform: result.waveform,
objectURL: result.url
});
}); });
});
/* const url = URL.createObjectURL(dataBlob);
/* const url = URL.createObjectURL(dataBlob);
var audio = document.createElement('audio');
var audio = document.createElement('audio'); audio.controls = true;
audio.controls = true; audio.src = url;
audio.src = url;
var link = document.createElement('a');
var link = document.createElement('a'); link.href = url;
link.href = url; link.download = fileName;
link.download = fileName; link.innerHTML = link.download;
link.innerHTML = link.download;
var li = document.createElement('li');
var li = document.createElement('li'); li.appendChild(link);
li.appendChild(link); li.appendChild(audio);
li.appendChild(audio);
recordingslist.appendChild(li); */
recordingslist.appendChild(li); */ };
}; }
let emoticonsDisplayTimeout = 0; let emoticonsDisplayTimeout = 0;
this.toggleEmoticons.onmouseover = (e) => { this.toggleEmoticons.onmouseover = (e) => {
@ -650,8 +664,11 @@ export class ChatInput {
} else { } else {
this.editMsgID = 0; this.editMsgID = 0;
this.messageInput.innerHTML = ''; this.messageInput.innerHTML = '';
this.btnSend.classList.remove('tgico-send');
this.btnSend.classList.add('tgico-microphone2'); if(this.recorder) {
this.btnSend.classList.remove('tgico-send');
this.btnSend.classList.add('tgico-microphone2');
}
} }
} }
@ -686,8 +703,11 @@ export class ChatInput {
this.replyElements.container.classList.remove('active'); this.replyElements.container.classList.remove('active');
this.willSendWebPage = null; this.willSendWebPage = null;
this.messageInput.innerText = ''; this.messageInput.innerText = '';
this.btnSend.classList.remove('tgico-send');
this.btnSend.classList.add('tgico-microphone2'); if(this.recorder) {
this.btnSend.classList.remove('tgico-send');
this.btnSend.classList.add('tgico-microphone2');
}
} }
} }

View File

@ -13,7 +13,7 @@ export default class LazyLoadQueue {
private unlockResolve: () => void = null; private unlockResolve: () => void = null;
private log = console.log.bind(console, '[LL]:'); private log = console.log.bind(console, '[LL]:');
private debug = false; private debug = true;
private observer: IntersectionObserver; private observer: IntersectionObserver;

View File

@ -1,9 +1,9 @@
import { whichChild, findUpTag, cancelEvent } from "../lib/utils"; import { whichChild, findUpTag, cancelEvent } from "../lib/utils";
import Config from "../lib/config"; import Config, { touchSupport } from "../lib/config";
let rippleClickID = 0; let rippleClickID = 0;
export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) { export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) {
return; //return;
if(elem.querySelector('.c-ripple')) return; if(elem.querySelector('.c-ripple')) return;
let r = document.createElement('div'); let r = document.createElement('div');
@ -95,30 +95,32 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
//}); //});
}; };
let touchEnd = () => {
handler && handler();
};
let touchStartFired = false; let touchStartFired = false;
elem.addEventListener('touchstart', (e) => { if(touchSupport) {
if(e.touches.length > 1) { let touchEnd = () => {
return;
}
console.log('touchstart', e);
touchStartFired = true;
let {clientX, clientY} = e.touches[0];
drawRipple(clientX, clientY);
window.addEventListener('touchend', touchEnd, {once: true});
window.addEventListener('touchmove', (e) => {
e.cancelBubble = true;
e.stopPropagation();
handler && handler(); handler && handler();
window.removeEventListener('touchend', touchEnd); };
}, {once: true});
}); elem.addEventListener('touchstart', (e) => {
if(e.touches.length > 1) {
return;
}
console.log('touchstart', e);
touchStartFired = true;
let {clientX, clientY} = e.touches[0];
drawRipple(clientX, clientY);
window.addEventListener('touchend', touchEnd, {once: true});
window.addEventListener('touchmove', (e) => {
e.cancelBubble = true;
e.stopPropagation();
handler && handler();
window.removeEventListener('touchend', touchEnd);
}, {once: true});
}, {passive: true});
}
elem.addEventListener('mousedown', (e) => { elem.addEventListener('mousedown', (e) => {
if(elem.dataset.ripple == '0') { if(elem.dataset.ripple == '0') {

View File

@ -291,6 +291,8 @@ export class AppDialogsManager {
private contextMenu = new DialogsContextMenu([this.chatList, this.chatListArchived]); private contextMenu = new DialogsContextMenu([this.chatList, this.chatListArchived]);
private debug = false;
constructor() { constructor() {
this.chatsPreloader = putPreloader(null, true); this.chatsPreloader = putPreloader(null, true);
@ -493,7 +495,7 @@ export class AppDialogsManager {
else this.loadedAll = true; else this.loadedAll = true;
} }
this.log('getDialogs ' + loadCount + ' dialogs by offset:', offsetIndex, result, this.scroll.length, archived); this.debug && this.log('getDialogs ' + loadCount + ' dialogs by offset:', offsetIndex, result, this.scroll.length, archived);
this.scroll.onScroll(); this.scroll.onScroll();
} catch(err) { } catch(err) {
this.log.error(err); this.log.error(err);
@ -585,7 +587,7 @@ export class AppDialogsManager {
(dialog.folder_id == 1 ? this.scrollArchived : this.scroll).reorder(); (dialog.folder_id == 1 ? this.scrollArchived : this.scroll).reorder();
this.log('setDialogPosition:', dialog, dom, pos); this.debug && this.log('setDialogPosition:', dialog, dom, pos);
} }
public setPinnedDelimiter() { public setPinnedDelimiter() {

View File

@ -15,7 +15,6 @@ import lottieLoader from "../lottieLoader";
import appMediaViewer from "./appMediaViewer"; import appMediaViewer from "./appMediaViewer";
import appSidebarLeft from "./appSidebarLeft"; import appSidebarLeft from "./appSidebarLeft";
import appChatsManager from "./appChatsManager"; import appChatsManager from "./appChatsManager";
import apiUpdatesManager from './apiUpdatesManager';
import { wrapDocument, wrapPhoto, wrapVideo, wrapSticker, wrapReply, wrapAlbum, wrapPoll } from '../../components/wrappers'; import { wrapDocument, wrapPhoto, wrapVideo, wrapSticker, wrapReply, wrapAlbum, wrapPoll } from '../../components/wrappers';
import ProgressivePreloader from '../../components/preloader'; import ProgressivePreloader from '../../components/preloader';
import { openBtnMenu, formatPhoneNumber, positionMenu, ripple, parseMenuButtonsTo, horizontalMenu } from '../../components/misc'; import { openBtnMenu, formatPhoneNumber, positionMenu, ripple, parseMenuButtonsTo, horizontalMenu } from '../../components/misc';
@ -31,13 +30,13 @@ import AvatarElement from '../../components/avatar';
import appInlineBotsManager from './AppInlineBotsManager'; import appInlineBotsManager from './AppInlineBotsManager';
import StickyIntersector from '../../components/stickyIntersector'; import StickyIntersector from '../../components/stickyIntersector';
import { PopupPeerButton, PopupPeer } from '../../components/popup'; import { PopupPeerButton, PopupPeer } from '../../components/popup';
import { mediaSizes } from '../config'; import { mediaSizes, touchSupport } from '../config';
console.log('appImManager included!'); console.log('appImManager included33!');
appSidebarLeft; // just to include appSidebarLeft; // just to include
let testScroll = false; const testScroll = true;
const IGNOREACTIONS = ['messageActionChannelMigrateFrom']; const IGNOREACTIONS = ['messageActionChannelMigrateFrom'];
@ -195,14 +194,7 @@ class ChatContextMenu {
}); });
this.buttons.pin.addEventListener('click', () => { this.buttons.pin.addEventListener('click', () => {
apiManager.invokeApi('messages.updatePinnedMessage', { appMessagesManager.updatePinnedMessage($rootScope.selectedPeerID, this.msgID);
flags: 0,
peer: appPeersManager.getInputPeerByID($rootScope.selectedPeerID),
id: this.msgID
}).then(updates => {
/////this.log('pinned updates:', updates);
apiUpdatesManager.processUpdateMessage(updates);
});
}); });
} }
} }
@ -765,6 +757,7 @@ export class AppImManager {
public setPinnedMessage(message: any) { public setPinnedMessage(message: any) {
/////this.log('setting pinned message', message); /////this.log('setting pinned message', message);
return;
this.pinnedMessageContainer.dataset.mid = '' + message.mid; this.pinnedMessageContainer.dataset.mid = '' + message.mid;
this.topbar.classList.add('is-pinned-shown'); this.topbar.classList.add('is-pinned-shown');
this.pinnedMessageContent.innerHTML = message.rReply; this.pinnedMessageContent.innerHTML = message.rReply;
@ -826,16 +819,18 @@ export class AppImManager {
this.onScrollRAF = window.requestAnimationFrame(() => { this.onScrollRAF = window.requestAnimationFrame(() => {
lottieLoader.checkAnimations(false, 'chat'); lottieLoader.checkAnimations(false, 'chat');
if(this.isScrollingTimeout) { if(!touchSupport) {
clearTimeout(this.isScrollingTimeout); if(this.isScrollingTimeout) {
} else if(!this.chatInner.classList.contains('is-scrolling')) { clearTimeout(this.isScrollingTimeout);
this.chatInner.classList.add('is-scrolling'); } else if(!this.chatInner.classList.contains('is-scrolling')) {
this.chatInner.classList.add('is-scrolling');
}
this.isScrollingTimeout = setTimeout(() => {
this.chatInner.classList.remove('is-scrolling');
this.isScrollingTimeout = 0;
}, 300);
} }
this.isScrollingTimeout = setTimeout(() => {
this.chatInner.classList.remove('is-scrolling');
this.isScrollingTimeout = 0;
}, 300);
if(this.scroll.scrollHeight - Math.round(this.scroll.scrollTop + this.scroll.offsetHeight) <= 1/* <= 5 */) { if(this.scroll.scrollHeight - Math.round(this.scroll.scrollTop + this.scroll.offsetHeight) <= 1/* <= 5 */) {
this.scroll.parentElement.classList.add('scrolled-down'); this.scroll.parentElement.classList.add('scrolled-down');
@ -861,6 +856,27 @@ export class AppImManager {
this.scroll.addEventListener('scroll', this.onScroll.bind(this)); this.scroll.addEventListener('scroll', this.onScroll.bind(this));
this.scroll.parentElement.classList.add('scrolled-down'); this.scroll.parentElement.classList.add('scrolled-down');
if(touchSupport) {
this.scroll.addEventListener('touchmove', () => {
if(this.isScrollingTimeout) {
clearTimeout(this.isScrollingTimeout);
} else if(!this.chatInner.classList.contains('is-scrolling')) {
this.chatInner.classList.add('is-scrolling');
}
this.scroll.addEventListener('touchend', () => {
if(this.isScrollingTimeout) {
clearTimeout(this.isScrollingTimeout);
}
this.isScrollingTimeout = setTimeout(() => {
this.chatInner.classList.remove('is-scrolling');
this.isScrollingTimeout = 0;
}, 300);
}, {passive: true})
}, {passive: true});
}
} }
public setPeerStatus(needClear = false) { public setPeerStatus(needClear = false) {
@ -1026,10 +1042,6 @@ export class AppImManager {
this.log('setPeer peerID:', this.peerID, dialog, lastMsgID, topMessage); this.log('setPeer peerID:', this.peerID, dialog, lastMsgID, topMessage);
if(mediaSizes.isMobile) {
this.selectTab(1);
}
const isJump = lastMsgID != topMessage; const isJump = lastMsgID != topMessage;
// add last message, bc in getHistory will load < max_id // add last message, bc in getHistory will load < max_id
const additionMsgID = isJump ? 0 : topMessage; const additionMsgID = isJump ? 0 : topMessage;
@ -1066,6 +1078,10 @@ export class AppImManager {
//oldChatInner.remove(); //oldChatInner.remove();
!samePeer && this.finishPeerChange(); !samePeer && this.finishPeerChange();
this.preloader.attach(this.bubblesContainer); this.preloader.attach(this.bubblesContainer);
if(mediaSizes.isMobile) {
this.selectTab(1);
}
} }
//console.timeEnd('appImManager setPeer pre promise'); //console.timeEnd('appImManager setPeer pre promise');
@ -1083,6 +1099,10 @@ export class AppImManager {
if(pinned && !pinned.deleted) { if(pinned && !pinned.deleted) {
this.setPinnedMessage(pinned); this.setPinnedMessage(pinned);
} }
if(mediaSizes.isMobile) {
this.selectTab(1);
}
} else { } else {
this.preloader.detach(); this.preloader.detach();
} }

View File

@ -1678,6 +1678,17 @@ export class AppMessagesManager {
public getPinnedMessage(peerID: number) { public getPinnedMessage(peerID: number) {
return this.getMessage(this.pinnedMessages[peerID] || 0); return this.getMessage(this.pinnedMessages[peerID] || 0);
} }
public updatePinnedMessage(peerID: number, msgID: number) {
apiManager.invokeApi('messages.updatePinnedMessage', {
flags: 0,
peer: appPeersManager.getInputPeerByID(peerID),
id: msgID
}).then(updates => {
/////console.log('pinned updates:', updates);
apiUpdatesManager.processUpdateMessage(updates);
});
}
public saveMessages(apiMessages: any[], options: { public saveMessages(apiMessages: any[], options: {
isNew?: boolean, isNew?: boolean,

View File

@ -89,12 +89,16 @@ class MediaSizes {
export const mediaSizes = new MediaSizes(); export const mediaSizes = new MediaSizes();
// @ts-ignore
export const touchSupport = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch);
const Config = { const Config = {
Emoji, Emoji,
LatinizeMap, LatinizeMap,
TLD, TLD,
Countries, Countries,
MediaSizes: mediaSizes MediaSizes: mediaSizes,
touchSupport
}; };
(window as any).Config = Config; (window as any).Config = Config;
export default Config; export default Config;

View File

@ -146,9 +146,9 @@ export default class Socket extends MTTransport {
this.ws = new WebSocket(this.url, 'binary'); this.ws = new WebSocket(this.url, 'binary');
this.ws.binaryType = 'arraybuffer'; this.ws.binaryType = 'arraybuffer';
this.ws.onopen = this.handleOpen; this.ws.addEventListener('open', this.handleOpen);
this.ws.onclose = this.handleClose; this.ws.addEventListener('close', this.handleClose);
this.ws.onmessage = this.handleMessage; this.ws.addEventListener('message', this.handleMessage);
}; };
handleOpen = () => { handleOpen = () => {

View File

@ -17,9 +17,13 @@ export default class Page {
if(!this.installed) { if(!this.installed) {
if(this.onFirstMount) { if(this.onFirstMount) {
let res = this.onFirstMount(...args); try {
if(res instanceof Promise) { const res = this.onFirstMount(...args);
await res; if(res instanceof Promise) {
await res;
}
} catch(err) {
console.error('PAGE MOUNT ERROR:', err);
} }
} }

View File

@ -5,7 +5,48 @@ import Page from "./page";
let onFirstMount = () => { let onFirstMount = () => {
//return; //return;
let promise = import('../lib/appManagers/appImManager')/* Promise.resolve() */.then(() => {//import('../lib/services').then(services => { const promise = import('../lib/appManagers/appImManager');
promise.finally(() => {
//alert('pageIm!');
//AudioContext && global.navigator && global.navigator.mediaDevices && global.navigator.mediaDevices.getUserMedia && global.WebAssembly;
/* // @ts-ignore
var AudioContext = globalThis.AudioContext || globalThis.webkitAudioContext;
alert('AudioContext:' + typeof(AudioContext));
// @ts-ignore
alert('global.navigator:' + typeof(navigator));
alert('navigator.mediaDevices:' + typeof(navigator.mediaDevices));
alert('navigator.mediaDevices.getUserMedia:' + typeof(navigator.mediaDevices?.getUserMedia));
alert('global.WebAssembly:' + typeof(WebAssembly)); */
// @ts-ignore
if(process.env.NODE_ENV != 'production') {
import('../lib/services');
}
//(Array.from(document.getElementsByClassName('rp')) as HTMLElement[]).forEach(el => ripple(el));
Array.from(document.getElementsByClassName('btn-menu-toggle')).forEach((el) => {
el.addEventListener('click', (e) => {
//console.log('click pageIm');
if(!el.classList.contains('btn-menu-toggle')) return false;
//window.removeEventListener('mousemove', onMouseMove);
let openedMenu = el.querySelector('.btn-menu') as HTMLDivElement;
e.cancelBubble = true;
if(el.classList.contains('menu-open')) {
el.classList.remove('menu-open');
openedMenu.classList.remove('active');
} else {
openBtnMenu(openedMenu);
}
});
});
})
//let promise = /* Promise.resolve() */.then(() => {//import('../lib/services').then(services => {
/* fetch('assets/img/camomile.jpg') /* fetch('assets/img/camomile.jpg')
.then(res => res.blob()) .then(res => res.blob())
.then(blob => { .then(blob => {
@ -44,32 +85,7 @@ let onFirstMount = () => {
toggleEmoticons.classList.toggle('active'); toggleEmoticons.classList.toggle('active');
}; */ }; */
//});
// @ts-ignore
if(process.env.NODE_ENV != 'production') {
import('../lib/services');
}
//(Array.from(document.getElementsByClassName('rp')) as HTMLElement[]).forEach(el => ripple(el));
Array.from(document.getElementsByClassName('btn-menu-toggle')).forEach((el) => {
el.addEventListener('click', (e) => {
//console.log('click pageIm');
if(!el.classList.contains('btn-menu-toggle')) return false;
//window.removeEventListener('mousemove', onMouseMove);
let openedMenu = el.querySelector('.btn-menu') as HTMLDivElement;
e.cancelBubble = true;
if(el.classList.contains('menu-open')) {
el.classList.remove('menu-open');
openedMenu.classList.remove('active');
} else {
openBtnMenu(openedMenu);
}
});
});
});
return promise; return promise;
}; };

View File

@ -4,9 +4,9 @@ a {
html { html {
line-height: 1.5; line-height: 1.5;
font-weight: normal; font-weight: normal;
} }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
line-height: 1.3; line-height: 1.3;
} }

View File

@ -599,6 +599,7 @@ $time-background: rgba(0, 0, 0, .35);
overflow: hidden; overflow: hidden;
position: relative; position: relative;
padding: 0 .5rem; padding: 0 .5rem;
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); // fix safari overflow
> .scrollable { > .scrollable {
padding: 0 .75rem; padding: 0 .75rem;
@ -683,7 +684,7 @@ $time-background: rgba(0, 0, 0, .35);
} }
&.is-scrolling .is-sticky { &.is-scrolling .is-sticky {
opacity: 1; opacity: 0.99999; // 0.99999 сделано для сафари, т.к. без этого будет прыжок при скролле в самом низу или верху
} }
} }

View File

@ -90,10 +90,11 @@
//z-index: 3; //z-index: 3;
z-index: 2; z-index: 2;
pointer-events: none; pointer-events: none;
transition: opacity .3s ease;
opacity: 0.99999; // for safari
&.is-sticky { &.is-sticky {
transition: opacity .3s ease; opacity: 0.00001; // for safari
opacity: 0;
} }
} }

View File

@ -211,6 +211,10 @@ input {
caret-color: $button-primary-background; caret-color: $button-primary-background;
} }
input, textarea {
-webkit-appearance: none;
}
.subtitle { .subtitle {
/* font-weight: 500; */ /* font-weight: 500; */
color: #707579; color: #707579;