Show .mov videos as document if it's not supported
This commit is contained in:
parent
1760ad42d8
commit
ce715fa09f
@ -6,7 +6,7 @@
|
||||
|
||||
import { RLottiePlayer } from "../lib/lottieLoader";
|
||||
import rootScope from "../lib/rootScope";
|
||||
import { isSafari } from "../helpers/userAgent";
|
||||
import { IS_SAFARI } from "../environment/userAgent";
|
||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||
import isInDOM from "../helpers/dom/isInDOM";
|
||||
|
||||
@ -93,7 +93,7 @@ export class AnimationIntersector {
|
||||
const {el, animation} = player;
|
||||
animation.remove();
|
||||
|
||||
if(animation instanceof HTMLVideoElement && isSafari) {
|
||||
if(animation instanceof HTMLVideoElement && IS_SAFARI) {
|
||||
setTimeout(() => { // TODO: очистка по очереди, а не все вместе с этим таймаутом
|
||||
animation.src = '';
|
||||
animation.load();
|
||||
|
@ -8,7 +8,7 @@ import rootScope from "../lib/rootScope";
|
||||
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
import appDocsManager, {MyDocument} from "../lib/appManagers/appDocsManager";
|
||||
import { CancellablePromise, deferredPromise } from "../helpers/cancellablePromise";
|
||||
import { isApple, isSafari } from "../helpers/userAgent";
|
||||
import { IS_APPLE, IS_SAFARI } from "../environment/userAgent";
|
||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||
import appDownloadManager from "../lib/appManagers/appDownloadManager";
|
||||
import simulateEvent from "../helpers/dom/dispatchEvent";
|
||||
@ -16,7 +16,7 @@ import type { SearchSuperContext } from "./appSearchSuper.";
|
||||
import { copy, deepEqual } from "../helpers/object";
|
||||
import { DocumentAttribute, Message, MessageMedia, PhotoSize } from "../layer";
|
||||
import appPhotosManager from "../lib/appManagers/appPhotosManager";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import appAvatarsManager from "../lib/appManagers/appAvatarsManager";
|
||||
import appPeersManager from "../lib/appManagers/appPeersManager";
|
||||
import I18n from "../lib/langPack";
|
||||
@ -34,7 +34,7 @@ type HTMLMediaElement = HTMLAudioElement | HTMLVideoElement;
|
||||
|
||||
const SHOULD_USE_SAFARI_FIX = (() => {
|
||||
try {
|
||||
return isSafari && +navigator.userAgent.match(/ Version\/(\d+)/)[1] < 14;
|
||||
return IS_SAFARI && +navigator.userAgent.match(/ Version\/(\d+)/)[1] < 14;
|
||||
} catch(err) {
|
||||
return false;
|
||||
}
|
||||
@ -296,8 +296,8 @@ class AppMediaPlaybackController {
|
||||
}
|
||||
|
||||
if(!artwork.length) {
|
||||
if(isApple) {
|
||||
if(isTouchSupported) {
|
||||
if(IS_APPLE) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
artwork.push({
|
||||
src: `assets/img/apple-touch-icon-precomposed.png`,
|
||||
sizes: '180x180',
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
import { deferredPromise } from "../helpers/cancellablePromise";
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { isMobileSafari, isSafari } from "../helpers/userAgent";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import { IS_MOBILE_SAFARI, IS_SAFARI } from "../environment/userAgent";
|
||||
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
|
||||
import appImManager from "../lib/appManagers/appImManager";
|
||||
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
@ -52,6 +52,7 @@ import PopupDeleteMessages from "./popups/deleteMessages";
|
||||
import RangeSelector from "./rangeSelector";
|
||||
import windowSize from "../helpers/windowSize";
|
||||
import ListLoader, { ListLoaderOptions } from "../helpers/listLoader";
|
||||
import MEDIA_MIME_TYPES_SUPPORTED from "../environment/mediaMimeTypesSupport";
|
||||
|
||||
const ZOOM_STEP = 0.5;
|
||||
const ZOOM_INITIAL_VALUE = 1;
|
||||
@ -355,7 +356,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
else this.onPrevClick(item);
|
||||
};
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
const swipeHandler = new SwipeHandler({
|
||||
element: this.wholeDiv,
|
||||
onSwipe: (xDiff, yDiff) => {
|
||||
@ -530,7 +531,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
if(target.tagName === 'A') return;
|
||||
cancelEvent(e);
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
if(this.highlightSwitchersTimeout) {
|
||||
clearTimeout(this.highlightSwitchersTimeout);
|
||||
} else {
|
||||
@ -1295,7 +1296,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
} else {
|
||||
window.addEventListener('keydown', this.onKeyDown);
|
||||
window.addEventListener('keyup', this.onKeyUp);
|
||||
if(!isTouchSupported) window.addEventListener('wheel', this.onWheel, {passive: false, capture: true});
|
||||
if(!IS_TOUCH_SUPPORTED) window.addEventListener('wheel', this.onWheel, {passive: false, capture: true});
|
||||
const mainColumns = this.pageEl.querySelector('#main-columns');
|
||||
this.pageEl.insertBefore(this.wholeDiv, mainColumns);
|
||||
void this.wholeDiv.offsetLeft; // reflow
|
||||
@ -1303,7 +1304,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
rootScope.isOverlayActive = true;
|
||||
animationIntersector.checkAnimations(true);
|
||||
|
||||
if(!isMobileSafari) {
|
||||
if(!IS_MOBILE_SAFARI) {
|
||||
appNavigationController.pushItem({
|
||||
type: 'media',
|
||||
onPop: (canAnimate) => {
|
||||
@ -1401,7 +1402,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
}
|
||||
}, {once: true});
|
||||
|
||||
if(isSafari) {
|
||||
if(IS_SAFARI) {
|
||||
// test stream
|
||||
// video.controls = true;
|
||||
video.autoplay = true;
|
||||
@ -1851,7 +1852,7 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
|
||||
}
|
||||
|
||||
public static isMediaCompatibleForDocumentViewer(media: MyPhoto | MyDocument) {
|
||||
return media._ === 'photo' || (['photo', 'video', 'gif'].includes(media.type) || media.mime_type.indexOf('video/') === 0);
|
||||
return media._ === 'photo' || MEDIA_MIME_TYPES_SUPPORTED.has(media.mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||
import { isMobileSafari } from "../helpers/userAgent";
|
||||
import { IS_MOBILE_SAFARI } from "../environment/userAgent";
|
||||
import { logger } from "../lib/logger";
|
||||
import { doubleRaf } from "../helpers/schedulers";
|
||||
import blurActiveElement from "../helpers/dom/blurActiveElement";
|
||||
@ -67,7 +67,7 @@ export class AppNavigationController {
|
||||
}
|
||||
}, {capture: true, passive: false});
|
||||
|
||||
if(isMobileSafari) {
|
||||
if(IS_MOBILE_SAFARI) {
|
||||
const options = {passive: true};
|
||||
window.addEventListener('touchstart', (e) => {
|
||||
if(e.touches.length > 1) return;
|
||||
|
@ -38,7 +38,7 @@ import mediaSizes from "../helpers/mediaSizes";
|
||||
import appImManager from "../lib/appManagers/appImManager";
|
||||
import positionElementByIndex from "../helpers/dom/positionElementByIndex";
|
||||
import cleanSearchText from "../helpers/cleanSearchText";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import handleTabSwipe from "../helpers/dom/handleTabSwipe";
|
||||
import windowSize from "../helpers/windowSize";
|
||||
import { formatPhoneNumber } from "../helpers/formatPhoneNumber";
|
||||
@ -133,7 +133,7 @@ class SearchContextMenu {
|
||||
});
|
||||
};
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
|
||||
} else {
|
||||
attachContextMenuListener(attachTo, onContextMenu as any);
|
||||
@ -326,7 +326,7 @@ export default class AppSearchSuper {
|
||||
this.tabsContainer = document.createElement('div');
|
||||
this.tabsContainer.classList.add('search-super-tabs-container', 'tabs-container');
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
handleTabSwipe(this.tabsContainer, (next) => {
|
||||
const prevId = this.selectTab.prevId();
|
||||
this.selectTab(next ? prevId + 1 : prevId - 1);
|
||||
|
@ -12,7 +12,7 @@ import { MediaProgressLine } from "../lib/mediaPlayer";
|
||||
import appMediaPlaybackController, { MediaItem } from "./appMediaPlaybackController";
|
||||
import { DocumentAttribute } from "../layer";
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { isSafari } from "../helpers/userAgent";
|
||||
import { IS_SAFARI } from "../environment/userAgent";
|
||||
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
import rootScope from "../lib/rootScope";
|
||||
import './middleEllipsis';
|
||||
@ -558,7 +558,7 @@ export default class AudioElement extends HTMLElement {
|
||||
appMediaPlaybackController.resolveWaitingForLoadMedia(this.message.peerId, this.message.mid);
|
||||
appMediaPlaybackController.willBePlayed(this.audio); // prepare for loading audio
|
||||
|
||||
if(isSafari) {
|
||||
if(IS_SAFARI) {
|
||||
this.audio.autoplay = true;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
import attachListNavigation from "../../helpers/dom/attachListNavigation";
|
||||
import EventListenerBase from "../../helpers/eventListenerBase";
|
||||
import { safeAssign } from "../../helpers/object";
|
||||
import { isMobile } from "../../helpers/userAgent";
|
||||
import { IS_MOBILE } from "../../environment/userAgent";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import appNavigationController, { NavigationItem } from "../appNavigationController";
|
||||
import SetTransition from "../singleTransition";
|
||||
@ -68,7 +68,7 @@ export default class AutocompleteHelper extends EventListenerBase<{
|
||||
|
||||
this.detach = detach;
|
||||
this.resetTarget = resetTarget;
|
||||
if(!isMobile && !this.navigationItem) {
|
||||
if(!IS_MOBILE && !this.navigationItem) {
|
||||
this.navigationItem = {
|
||||
type: 'autocomplete-helper',
|
||||
onPop: () => {
|
||||
|
@ -18,7 +18,7 @@ import type { AppMessagesIdsManager } from "../../lib/appManagers/appMessagesIds
|
||||
import type Chat from "./chat";
|
||||
import { CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager";
|
||||
import { getObjectKeysAndSort } from "../../helpers/object";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import { logger } from "../../lib/logger";
|
||||
import rootScope, { BroadcastEvents } from "../../lib/rootScope";
|
||||
import AppMediaViewer from "../appMediaViewer";
|
||||
@ -32,7 +32,7 @@ import StickyIntersector from "../stickyIntersector";
|
||||
import animationIntersector from "../animationIntersector";
|
||||
import RichTextProcessor from "../../lib/richtextprocessor";
|
||||
import mediaSizes from "../../helpers/mediaSizes";
|
||||
import { isAndroid, isApple, isMobile, isSafari } from "../../helpers/userAgent";
|
||||
import { IS_ANDROID, IS_APPLE, IS_MOBILE, IS_SAFARI } from "../../environment/userAgent";
|
||||
import I18n, { i18n, langPack } from "../../lib/langPack";
|
||||
import AvatarElement from "../avatar";
|
||||
import { ripple } from "../ripple";
|
||||
@ -452,7 +452,7 @@ export default class ChatBubbles {
|
||||
});
|
||||
}
|
||||
|
||||
if(!isMobile) {
|
||||
if(!IS_MOBILE) {
|
||||
this.listenerSetter.add(this.bubblesContainer)('dblclick', (e) => {
|
||||
if(this.chat.selection.isSelecting ||
|
||||
!this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId)) {
|
||||
@ -864,7 +864,7 @@ export default class ChatBubbles {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isTouchSupported && findUpClassName(target, 'time')) {
|
||||
if(!IS_TOUCH_SUPPORTED && findUpClassName(target, 'time')) {
|
||||
this.chat.selection.toggleByElement(bubble);
|
||||
return;
|
||||
}
|
||||
@ -878,7 +878,7 @@ export default class ChatBubbles {
|
||||
cancelEvent(e);
|
||||
//console.log('bubble click', e);
|
||||
|
||||
if(isTouchSupported && this.chat.selection.selectedText) {
|
||||
if(IS_TOUCH_SUPPORTED && this.chat.selection.selectedText) {
|
||||
this.chat.selection.selectedText = undefined;
|
||||
return;
|
||||
}
|
||||
@ -1264,7 +1264,7 @@ export default class ChatBubbles {
|
||||
if(this.isHeavyAnimationInProgress && this.scrolledDown) return;
|
||||
//lottieLoader.checkAnimations(false, 'chat');
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
if(this.isScrollingTimeout) {
|
||||
clearTimeout(this.isScrollingTimeout);
|
||||
} else if(!this.chatInner.classList.contains('is-scrolling')) {
|
||||
@ -1313,7 +1313,7 @@ export default class ChatBubbles {
|
||||
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);
|
||||
//this.scrollable.attachSentinels(undefined, 300);
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
this.scrollable.container.addEventListener('touchmove', () => {
|
||||
if(this.isScrollingTimeout) {
|
||||
clearTimeout(this.isScrollingTimeout);
|
||||
@ -2530,7 +2530,7 @@ export default class ChatBubbles {
|
||||
break;
|
||||
}
|
||||
|
||||
const withTail = !isAndroid && canHaveTail && !withReplies && USE_MEDIA_TAILS;
|
||||
const withTail = !IS_ANDROID && canHaveTail && !withReplies && USE_MEDIA_TAILS;
|
||||
if(withTail) bubble.classList.add('with-media-tail');
|
||||
wrapPhoto({
|
||||
photo,
|
||||
@ -2759,7 +2759,7 @@ export default class ChatBubbles {
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
});
|
||||
} else {
|
||||
const withTail = !isAndroid && !isApple && !isRound && canHaveTail && !withReplies && USE_MEDIA_TAILS;
|
||||
const withTail = !IS_ANDROID && !IS_APPLE && !isRound && canHaveTail && !withReplies && USE_MEDIA_TAILS;
|
||||
if(withTail) bubble.classList.add('with-media-tail');
|
||||
wrapVideo({
|
||||
doc,
|
||||
@ -3198,7 +3198,7 @@ export default class ChatBubbles {
|
||||
//this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||
//isTouchSupported && isApple && (this.scrollable.container.style.overflow = '');
|
||||
|
||||
if(isSafari/* && !isAppleMobile */) { // * fix blinking and jumping
|
||||
if(IS_SAFARI/* && !isAppleMobile */) { // * fix blinking and jumping
|
||||
reflowScrollableElement(this.scrollable.container);
|
||||
}
|
||||
|
||||
@ -3376,7 +3376,7 @@ export default class ChatBubbles {
|
||||
|
||||
// ! в хроме, каким-то образом из-за zoom-fade класса начинает прыгать скролл при подгрузке сообщений вверх,
|
||||
// ! т.е. скролл не ставится, так же, как в сафари при translateZ на блок выше scrollable
|
||||
if(!isSafari) {
|
||||
if(!IS_SAFARI) {
|
||||
this.needReflowScroll = true;
|
||||
}
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ import type { AppPollsManager, Poll } from "../../lib/appManagers/appPollsManage
|
||||
import type { AppDocsManager, MyDocument } from "../../lib/appManagers/appDocsManager";
|
||||
import type { AppMessagesIdsManager } from "../../lib/appManagers/appMessagesIdsManager";
|
||||
import type Chat from "./chat";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
|
||||
import { attachContextMenuListener, openBtnMenu, positionMenu } from "../misc";
|
||||
import PopupDeleteMessages from "../popups/deleteMessages";
|
||||
@ -117,7 +117,7 @@ export default class ChatContextMenu {
|
||||
if(chat.selection.isSelecting && !button.withSelection) {
|
||||
good = false;
|
||||
} else {
|
||||
good = contentWrapper || isTouchSupported || true ?
|
||||
good = contentWrapper || IS_TOUCH_SUPPORTED || true ?
|
||||
button.verify() :
|
||||
button.notDirect && button.verify() && button.notDirect();
|
||||
}
|
||||
@ -135,7 +135,7 @@ export default class ChatContextMenu {
|
||||
});
|
||||
};
|
||||
|
||||
if(isTouchSupported/* && false */) {
|
||||
if(IS_TOUCH_SUPPORTED/* && false */) {
|
||||
attachClickEvent(attachTo, (e) => {
|
||||
if(chat.selection.isSelecting) {
|
||||
return;
|
||||
@ -284,7 +284,7 @@ export default class ChatContextMenu {
|
||||
const doc: MyDocument = this.message.media?.document;
|
||||
if(!doc) return false;
|
||||
|
||||
let hasTarget = !!isTouchSupported;
|
||||
let hasTarget = !!IS_TOUCH_SUPPORTED;
|
||||
const isGoodType = !doc.type || !(['gif', 'video', 'sticker'] as MyDocument['type'][]).includes(doc.type);
|
||||
if(isGoodType) hasTarget = hasTarget || !!findUpClassName(this.target, 'document') || !!findUpClassName(this.target, 'audio');
|
||||
return isGoodType && hasTarget;
|
||||
|
@ -19,7 +19,7 @@ import type { AppInlineBotsManager } from '../../lib/appManagers/appInlineBotsMa
|
||||
import type { AppMessagesIdsManager } from '../../lib/appManagers/appMessagesIdsManager';
|
||||
import type Chat from './chat';
|
||||
import Recorder from '../../../public/recorder.min';
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import apiManager from "../../lib/mtproto/mtprotoworker";
|
||||
//import Recorder from '../opus-recorder/dist/recorder.min';
|
||||
import opusDecodeController from "../../lib/opusDecodeController";
|
||||
@ -44,7 +44,7 @@ import rootScope from '../../lib/rootScope';
|
||||
import PopupPinMessage from '../popups/unpinMessage';
|
||||
import { tsNow } from '../../helpers/date';
|
||||
import appNavigationController, { NavigationItem } from '../appNavigationController';
|
||||
import { isMobile, isMobileSafari } from '../../helpers/userAgent';
|
||||
import { IS_MOBILE, IS_MOBILE_SAFARI } from '../../environment/userAgent';
|
||||
import I18n, { i18n, join, LangPackKey } from '../../lib/langPack';
|
||||
import { generateTail } from './bubbles';
|
||||
import findUpClassName from '../../helpers/dom/findUpClassName';
|
||||
@ -79,6 +79,7 @@ import PopupDeleteMessages from '../popups/deleteMessages';
|
||||
import fixSafariStickyInputFocusing, { IS_STICKY_INPUT_BUGGED } from '../../helpers/dom/fixSafariStickyInputFocusing';
|
||||
import { copy } from '../../helpers/object';
|
||||
import PopupPeer from '../popups/peer';
|
||||
import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport';
|
||||
|
||||
const RECORD_MIN_TIME = 500;
|
||||
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
|
||||
@ -331,9 +332,7 @@ export default class ChatInput {
|
||||
this.appImManager.openScheduled(this.chat.peerId);
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.listenerSetter.add(rootScope)('scheduled_new', (e) => {
|
||||
const peerId = e.peerId;
|
||||
|
||||
this.listenerSetter.add(rootScope)('scheduled_new', ({peerId}) => {
|
||||
if(this.chat.peerId !== peerId) {
|
||||
return;
|
||||
}
|
||||
@ -341,9 +340,7 @@ export default class ChatInput {
|
||||
this.btnScheduled.classList.remove('hide');
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('scheduled_delete', (e) => {
|
||||
const peerId = e.peerId;
|
||||
|
||||
this.listenerSetter.add(rootScope)('scheduled_delete', ({peerId}) => {
|
||||
if(this.chat.peerId !== peerId) {
|
||||
return;
|
||||
}
|
||||
@ -370,7 +367,8 @@ export default class ChatInput {
|
||||
text: 'Chat.Input.Attach.PhotoOrVideo',
|
||||
onClick: () => {
|
||||
this.fileInput.value = '';
|
||||
this.fileInput.setAttribute('accept', 'image/*, video/*');
|
||||
const accept = [...MEDIA_MIME_TYPES_SUPPORTED].join(', ');
|
||||
this.fileInput.setAttribute('accept', accept);
|
||||
this.willAttachType = 'media';
|
||||
this.fileInput.click();
|
||||
},
|
||||
@ -391,7 +389,7 @@ export default class ChatInput {
|
||||
onClick: () => {
|
||||
new PopupCreatePoll(this.chat).show();
|
||||
},
|
||||
verify: (peerId, threadId) => this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_polls') && peerId < 0
|
||||
verify: (peerId, threadId) => peerId < 0 && this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_polls')
|
||||
}];
|
||||
|
||||
this.attachMenu = ButtonMenuToggle({noRipple: true, listenerSetter: this.listenerSetter}, 'top-left', this.attachMenuButtons);
|
||||
@ -491,8 +489,7 @@ export default class ChatInput {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('draft_updated', (e) => {
|
||||
const {peerId, threadId, draft, force} = e;
|
||||
this.listenerSetter.add(rootScope)('draft_updated', ({peerId, threadId, draft, force}) => {
|
||||
if(this.chat.threadId !== threadId || this.chat.peerId !== peerId) return;
|
||||
this.setDraft(draft, true, force);
|
||||
});
|
||||
@ -671,12 +668,12 @@ export default class ChatInput {
|
||||
};
|
||||
|
||||
private onEmoticonsOpen = () => {
|
||||
const toggleClass = isTouchSupported ? 'flip-icon' : 'active';
|
||||
const toggleClass = IS_TOUCH_SUPPORTED ? 'flip-icon' : 'active';
|
||||
this.btnToggleEmoticons.classList.toggle(toggleClass, true);
|
||||
};
|
||||
|
||||
private onEmoticonsClose = () => {
|
||||
const toggleClass = isTouchSupported ? 'flip-icon' : 'active';
|
||||
const toggleClass = IS_TOUCH_SUPPORTED ? 'flip-icon' : 'active';
|
||||
this.btnToggleEmoticons.classList.toggle(toggleClass, false);
|
||||
};
|
||||
|
||||
@ -929,7 +926,7 @@ export default class ChatInput {
|
||||
}
|
||||
});
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
attachClickEvent(this.messageInput, (e) => {
|
||||
this.appImManager.selectTab(1); // * set chat tab for album orientation
|
||||
//this.saveScroll();
|
||||
@ -1619,7 +1616,7 @@ export default class ChatInput {
|
||||
};
|
||||
|
||||
public clearInput(canSetDraft = true, fireEvent = true, clearValue = '') {
|
||||
if(document.activeElement === this.messageInput && isMobileSafari) { // fix first char uppercase
|
||||
if(document.activeElement === this.messageInput && IS_MOBILE_SAFARI) { // fix first char uppercase
|
||||
const i = document.createElement('input');
|
||||
document.body.append(i);
|
||||
fixSafariStickyInput(i);
|
||||
@ -1630,7 +1627,7 @@ export default class ChatInput {
|
||||
this.messageInputField.setValueSilently(clearValue);
|
||||
}
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
//this.messageInput.innerText = '';
|
||||
} else {
|
||||
//this.attachMessageInputField();
|
||||
@ -1978,7 +1975,7 @@ export default class ChatInput {
|
||||
scroll.scrollTo(scroll.scrollHeight, 'top', true, true, 200);
|
||||
} */
|
||||
|
||||
if(!isMobile) {
|
||||
if(!IS_MOBILE) {
|
||||
appNavigationController.pushItem({
|
||||
type: 'input-helper',
|
||||
onPop: () => {
|
||||
|
@ -8,8 +8,8 @@ import type { AppImManager } from "../../lib/appManagers/appImManager";
|
||||
import RichTextProcessor from "../../lib/richtextprocessor";
|
||||
import ButtonIcon from "../buttonIcon";
|
||||
import { clamp } from "../../helpers/number";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { isApple, isMobile } from "../../helpers/userAgent";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import { IS_APPLE, IS_MOBILE } from "../../environment/userAgent";
|
||||
import appNavigationController from "../appNavigationController";
|
||||
import { _i18n } from "../../lib/langPack";
|
||||
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
||||
@ -313,7 +313,7 @@ export default class MarkupTooltip {
|
||||
|
||||
this.container.classList.add('is-visible');
|
||||
|
||||
if(!isMobile) {
|
||||
if(!IS_MOBILE) {
|
||||
appNavigationController.pushItem({
|
||||
type: 'markup',
|
||||
onPop: () => {
|
||||
@ -337,7 +337,7 @@ export default class MarkupTooltip {
|
||||
//this.log('onMouseUpSingle');
|
||||
this.waitingForMouseUp = false;
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
cancelEvent(e);
|
||||
if(this.mouseUpCounter++ === 0) {
|
||||
this.resetSelection(this.savedRange);
|
||||
@ -362,7 +362,7 @@ export default class MarkupTooltip {
|
||||
}
|
||||
|
||||
public cancelClosening() {
|
||||
if(isTouchSupported && !isApple) {
|
||||
if(IS_TOUCH_SUPPORTED && !IS_APPLE) {
|
||||
document.removeEventListener('mouseup', this.onMouseUpSingle);
|
||||
document.addEventListener('mouseup', (e) => {
|
||||
cancelEvent(e);
|
||||
@ -394,8 +394,8 @@ export default class MarkupTooltip {
|
||||
return;
|
||||
}
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(isApple) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
if(IS_APPLE) {
|
||||
this.show();
|
||||
this.setTooltipPosition(); // * because can skip this in .show();
|
||||
} else {
|
||||
|
@ -13,7 +13,7 @@ import rootScope from "../../lib/rootScope";
|
||||
import { safeAssign } from "../../helpers/object";
|
||||
import ListenerSetter, { Listener } from "../../helpers/listenerSetter";
|
||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import findUpAsChild from "../../helpers/dom/findUpAsChild";
|
||||
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
||||
import { getHeavyAnimationPromise } from "../../hooks/useHeavyAnimationCheck";
|
||||
@ -64,7 +64,7 @@ export default class ReplyKeyboard extends DropdownHover {
|
||||
this.listenerSetter.add(this)('open', () => {
|
||||
this.render();
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
this.touchListener = this.listenerSetter.add(document.body)('touchstart', this.onBodyTouchStart, {passive: false, capture: true}) as any as Listener;
|
||||
this.listenerSetter.add(this)('close', () => {
|
||||
this.listenerSetter.remove(this.touchListener);
|
||||
|
@ -8,7 +8,7 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage
|
||||
import type ChatBubbles from "./bubbles";
|
||||
import type ChatInput from "./input";
|
||||
import type Chat from "./chat";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import Button from "../button";
|
||||
import ButtonIcon from "../buttonIcon";
|
||||
import CheckboxField from "../checkboxField";
|
||||
@ -19,7 +19,7 @@ import SetTransition from "../singleTransition";
|
||||
import ListenerSetter from "../../helpers/listenerSetter";
|
||||
import PopupSendNow from "../popups/sendNow";
|
||||
import appNavigationController, { NavigationItem } from "../appNavigationController";
|
||||
import { isMobileSafari } from "../../helpers/userAgent";
|
||||
import { IS_MOBILE_SAFARI } from "../../environment/userAgent";
|
||||
import I18n, { i18n, _i18n } from "../../lib/langPack";
|
||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||
import blurActiveElement from "../../helpers/dom/blurActiveElement";
|
||||
@ -85,7 +85,7 @@ class AppSelection {
|
||||
|
||||
this.navigationType = 'multiselect-' + randomLong() as any;
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
this.listenerSetter.add(this.listenElement)('touchend', () => {
|
||||
if(!this.isSelecting) return;
|
||||
this.selectedText = getSelectedText();
|
||||
@ -367,7 +367,7 @@ class AppSelection {
|
||||
}
|
||||
} */
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.listenElement.classList.toggle('no-select', this.isSelecting);
|
||||
|
||||
if(wasSelecting) {
|
||||
@ -390,7 +390,7 @@ class AppSelection {
|
||||
const forwards = !!size || forceSelection;
|
||||
this.onToggleSelection && this.onToggleSelection(forwards);
|
||||
|
||||
if(!isMobileSafari) {
|
||||
if(!IS_MOBILE_SAFARI) {
|
||||
if(forwards) {
|
||||
appNavigationController.pushItem({
|
||||
type: this.navigationType,
|
||||
|
@ -14,7 +14,7 @@ import type { AppUsersManager } from "../../lib/appManagers/appUsersManager";
|
||||
import type Chat from "./chat";
|
||||
import { RIGHT_COLUMN_ACTIVE_CLASSNAME } from "../sidebarRight";
|
||||
import mediaSizes, { ScreenSize } from "../../helpers/mediaSizes";
|
||||
import { isSafari } from "../../helpers/userAgent";
|
||||
import { IS_SAFARI } from "../../environment/userAgent";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import AvatarElement from "../avatar";
|
||||
import Button from "../button";
|
||||
@ -685,7 +685,7 @@ export default class ChatTopbar {
|
||||
//return;
|
||||
if(this.setUtilsRAF) window.cancelAnimationFrame(this.setUtilsRAF);
|
||||
|
||||
if(isSafari && resize) {
|
||||
if(IS_SAFARI && resize) {
|
||||
this.chatUtils.classList.add('hide');
|
||||
}
|
||||
|
||||
@ -695,7 +695,7 @@ export default class ChatTopbar {
|
||||
//mutationRAF = window.requestAnimationFrame(() => {
|
||||
|
||||
//setTimeout(() => {
|
||||
if(isSafari && resize) {
|
||||
if(IS_SAFARI && resize) {
|
||||
this.chatUtils.classList.remove('hide');
|
||||
}
|
||||
/* this.chatInfo.style.removeProperty('--utils-width');
|
||||
|
@ -4,7 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import appImManager from "../../lib/appManagers/appImManager";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import animationIntersector from "../animationIntersector";
|
||||
@ -61,7 +61,7 @@ export class EmoticonsDropdown extends DropdownHover {
|
||||
});
|
||||
|
||||
this.addEventListener('open', async() => {
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
//appImManager.chat.input.saveScroll();
|
||||
if(blurActiveElement()) {
|
||||
await pause(100);
|
||||
|
@ -9,7 +9,7 @@ import { cancelEvent } from "../../../helpers/dom/cancelEvent";
|
||||
import findUpClassName from "../../../helpers/dom/findUpClassName";
|
||||
import { fastRaf } from "../../../helpers/schedulers";
|
||||
import { pause } from "../../../helpers/schedulers/pause";
|
||||
import { isTouchSupported } from "../../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../../environment/touchSupport";
|
||||
import appEmojiManager from "../../../lib/appManagers/appEmojiManager";
|
||||
import appImManager from "../../../lib/appManagers/appImManager";
|
||||
import Config from "../../../lib/config";
|
||||
@ -20,6 +20,7 @@ import { emojiFromCodePoints } from "../../../vendor/emoji";
|
||||
import { putPreloader } from "../../misc";
|
||||
import Scrollable from "../../scrollable";
|
||||
import StickyIntersector from "../../stickyIntersector";
|
||||
import IS_EMOJI_SUPPORTED from "../../../environment/emojiSupport";
|
||||
|
||||
const loadedURLs: Set<string> = new Set();
|
||||
export function appendEmoji(emoji: string, container: HTMLElement, prepend = false, unify = false) {
|
||||
@ -31,7 +32,7 @@ export function appendEmoji(emoji: string, container: HTMLElement, prepend = fal
|
||||
spanEmoji.classList.add('super-emoji');
|
||||
|
||||
let kek: string;
|
||||
if(unify && !RichTextProcessor.emojiSupported) {
|
||||
if(unify && !IS_EMOJI_SUPPORTED) {
|
||||
kek = RichTextProcessor.wrapSingleEmoji(emoji);
|
||||
} else {
|
||||
emoji = RichTextProcessor.fixEmoji(emoji);
|
||||
@ -53,7 +54,7 @@ export function appendEmoji(emoji: string, container: HTMLElement, prepend = fal
|
||||
spanEmoji.append(first);
|
||||
}
|
||||
|
||||
if(spanEmoji.firstElementChild && !RichTextProcessor.emojiSupported) {
|
||||
if(spanEmoji.firstElementChild && !IS_EMOJI_SUPPORTED) {
|
||||
const image = spanEmoji.firstElementChild as HTMLImageElement;
|
||||
|
||||
const url = image.src;
|
||||
@ -295,7 +296,7 @@ export default class EmojiTab implements EmoticonsTab {
|
||||
const html = RichTextProcessor.wrapEmojiText(emoji, true);
|
||||
let inserted = false;
|
||||
if(window.getSelection) {
|
||||
const savedRange = isTouchSupported ? undefined : emoticonsDropdown.getSavedRange();
|
||||
const savedRange = IS_TOUCH_SUPPORTED ? undefined : emoticonsDropdown.getSavedRange();
|
||||
let sel = window.getSelection();
|
||||
if(savedRange) {
|
||||
sel.removeAllRanges();
|
||||
|
@ -9,8 +9,8 @@ import { cancelEvent } from "../helpers/dom/cancelEvent";
|
||||
import { CLICK_EVENT_NAME } from "../helpers/dom/clickEvent";
|
||||
import ListenerSetter from "../helpers/listenerSetter";
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { isApple, isMobileSafari } from "../helpers/userAgent";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import { IS_APPLE, IS_MOBILE_SAFARI } from "../environment/userAgent";
|
||||
import rootScope from "../lib/rootScope";
|
||||
import appNavigationController from "./appNavigationController";
|
||||
|
||||
@ -101,7 +101,7 @@ export const closeBtnMenu = () => {
|
||||
openedMenuOnClose = null;
|
||||
}
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
window.removeEventListener('mousemove', onMouseMove);
|
||||
//window.removeEventListener('keydown', onKeyDown, {capture: true});
|
||||
window.removeEventListener('contextmenu', onClick);
|
||||
@ -109,7 +109,7 @@ export const closeBtnMenu = () => {
|
||||
|
||||
document.removeEventListener(CLICK_EVENT_NAME, onClick);
|
||||
|
||||
if(!isMobileSafari) {
|
||||
if(!IS_MOBILE_SAFARI) {
|
||||
appNavigationController.removeByType('menu');
|
||||
}
|
||||
};
|
||||
@ -131,7 +131,7 @@ let openedMenu: HTMLElement = null, openedMenuOnClose: () => void = null, menuOv
|
||||
export function openBtnMenu(menuElement: HTMLElement, onClose?: () => void) {
|
||||
closeBtnMenu();
|
||||
|
||||
if(!isMobileSafari) {
|
||||
if(!IS_MOBILE_SAFARI) {
|
||||
appNavigationController.pushItem({
|
||||
type: 'menu',
|
||||
onPop: (canAnimate) => {
|
||||
@ -161,7 +161,7 @@ export function openBtnMenu(menuElement: HTMLElement, onClose?: () => void) {
|
||||
|
||||
openedMenuOnClose = onClose;
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
window.addEventListener('mousemove', onMouseMove);
|
||||
//window.addEventListener('keydown', onKeyDown, {capture: true});
|
||||
window.addEventListener('contextmenu', onClick, {once: true});
|
||||
@ -297,7 +297,7 @@ export function attachContextMenuListener(element: HTMLElement, callback: (e: To
|
||||
const add = listenerSetter ? listenerSetter.add(element) : element.addEventListener.bind(element);
|
||||
const remove = listenerSetter ? listenerSetter.removeManual.bind(listenerSetter, element) : element.removeEventListener.bind(element);
|
||||
|
||||
if(isApple && isTouchSupported) {
|
||||
if(IS_APPLE && IS_TOUCH_SUPPORTED) {
|
||||
let timeout: number;
|
||||
|
||||
const options: EventListenerOptions = {capture: true};
|
||||
@ -343,7 +343,7 @@ export function attachContextMenuListener(element: HTMLElement, callback: (e: To
|
||||
}, {passive: false, capture: true});
|
||||
} */
|
||||
} else {
|
||||
add('contextmenu', isTouchSupported ? (e: any) => {
|
||||
add('contextmenu', IS_TOUCH_SUPPORTED ? (e: any) => {
|
||||
callback(e);
|
||||
|
||||
if(openedMenu) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import appImManager from "../lib/appManagers/appImManager";
|
||||
import appPollsManager, { Poll, PollResults } from "../lib/appManagers/appPollsManager";
|
||||
import serverTimeManager from "../lib/mtproto/serverTimeManager";
|
||||
@ -161,7 +161,7 @@ const setQuizHint = (solution: string, solution_entities: any[], onHide: () => v
|
||||
prevQuizHintOnHide = onHide;
|
||||
prevQuizHintTimeout = window.setTimeout(() => {
|
||||
hideQuizHint(element, onHide, prevQuizHintTimeout);
|
||||
}, isTouchSupported ? 5000 : 7000);
|
||||
}, IS_TOUCH_SUPPORTED ? 5000 : 7000);
|
||||
};
|
||||
|
||||
export default class PollElement extends HTMLElement {
|
||||
|
@ -22,6 +22,7 @@ import rootScope from "../../lib/rootScope";
|
||||
import RichTextProcessor from "../../lib/richtextprocessor";
|
||||
import { MediaSize } from "../../helpers/mediaSizes";
|
||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||
import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport';
|
||||
|
||||
type SendFileParams = Partial<{
|
||||
file: File,
|
||||
@ -368,13 +369,11 @@ export default class PopupNewMedia extends PopupElement {
|
||||
willAttach.type = 'document';
|
||||
} */
|
||||
|
||||
files = files.filter(file => {
|
||||
if(willAttach.type === 'media') {
|
||||
return ['image/', 'video/'].find(s => file.type.indexOf(s) === 0);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if(willAttach.type === 'media') {
|
||||
files = files.filter(file => MEDIA_MIME_TYPES_SUPPORTED.has(file.type));
|
||||
} else {
|
||||
files = files.slice();
|
||||
}
|
||||
|
||||
Promise.all(files.map(this.attachFile)).then(results => {
|
||||
this.container.classList.remove('is-media', 'is-document', 'is-album');
|
||||
|
@ -4,7 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import AppSelectPeers from "../appSelectPeers";
|
||||
import PopupElement from ".";
|
||||
import { LangPackKey, _i18n } from "../../lib/langPack";
|
||||
@ -50,7 +50,7 @@ export default class PopupPickUser extends PopupElement {
|
||||
this.show();
|
||||
this.selector.checkForTriggers(); // ! due to zero height before mounting
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.selector.input.focus();
|
||||
}
|
||||
},
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import findUpClassName from "../helpers/dom/findUpClassName";
|
||||
import sequentialDom from "../helpers/sequentialDom";
|
||||
import {isTouchSupported} from "../helpers/touchSupport";
|
||||
import {IS_TOUCH_SUPPORTED} from "../environment/touchSupport";
|
||||
import rootScope from "../lib/rootScope";
|
||||
|
||||
let rippleClickId = 0;
|
||||
@ -63,7 +63,7 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
|
||||
setTimeout(cb, duration / 2);
|
||||
}
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
window.removeEventListener('contextmenu', handler);
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
|
||||
|
||||
// TODO: rename this variable
|
||||
let touchStartFired = false;
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
let touchEnd = () => {
|
||||
handler && handler();
|
||||
};
|
||||
|
@ -4,7 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import { logger, LogTypes } from "../lib/logger";
|
||||
import fastSmoothScroll, { FocusDirection } from "../helpers/fastSmoothScroll";
|
||||
import useHeavyAnimationCheck from "../hooks/useHeavyAnimationCheck";
|
||||
@ -248,7 +248,7 @@ export class ScrollableX extends ScrollableBase {
|
||||
|
||||
this.container.classList.add('scrollable-x');
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
const scrollHorizontally = (e: any) => {
|
||||
if(!e.deltaX && this.container.scrollWidth > this.container.clientWidth) {
|
||||
this.container.scrollLeft += e.deltaY / 4;
|
||||
|
@ -28,7 +28,7 @@ import AppAddMembersTab from "./tabs/addMembers";
|
||||
import { i18n_, LangPackKey } from "../../lib/langPack";
|
||||
import { ButtonMenuItemOptions } from "../buttonMenu";
|
||||
import CheckboxField from "../checkboxField";
|
||||
import { isMobileSafari } from "../../helpers/userAgent";
|
||||
import { IS_MOBILE_SAFARI } from "../../environment/userAgent";
|
||||
import appNavigationController from "../appNavigationController";
|
||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||
import findUpTag from "../../helpers/dom/findUpTag";
|
||||
@ -531,7 +531,7 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||
this.newBtnMenu.classList.add('is-hidden');
|
||||
this.toolsBtn.parentElement.firstElementChild.classList.toggle('state-back', true);
|
||||
|
||||
if(!isMobileSafari && !appNavigationController.findItemByType('global-search')) {
|
||||
if(!IS_MOBILE_SAFARI && !appNavigationController.findItemByType('global-search')) {
|
||||
appNavigationController.pushItem({
|
||||
onPop: () => {
|
||||
close();
|
||||
|
@ -8,7 +8,7 @@ import { SliderSuperTab } from "../../slider";
|
||||
import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
|
||||
import appUsersManager from "../../../lib/appManagers/appUsersManager";
|
||||
import InputSearch from "../../inputSearch";
|
||||
import { isMobile } from "../../../helpers/userAgent";
|
||||
import { IS_MOBILE } from "../../../environment/userAgent";
|
||||
import { canFocus } from "../../../helpers/dom/canFocus";
|
||||
import windowSize from "../../../helpers/windowSize";
|
||||
import ButtonCorner from "../../buttonCorner";
|
||||
@ -75,7 +75,7 @@ export default class AppContactsTab extends SliderSuperTab {
|
||||
}
|
||||
|
||||
protected onOpenAfterTimeout() {
|
||||
if(isMobile || !canFocus(true)) return;
|
||||
if(IS_MOBILE || !canFocus(true)) return;
|
||||
this.inputSearch.input.focus();
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import CheckboxField from "../../checkboxField";
|
||||
import RadioField from "../../radioField";
|
||||
import appStateManager from "../../../lib/appManagers/appStateManager";
|
||||
import rootScope from "../../../lib/rootScope";
|
||||
import { isApple } from "../../../helpers/userAgent";
|
||||
import { IS_APPLE } from "../../../environment/userAgent";
|
||||
import Row from "../../row";
|
||||
import AppBackgroundTab from "./background";
|
||||
import { LangPackKey, _i18n } from "../../../lib/langPack";
|
||||
@ -120,7 +120,7 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
|
||||
}),
|
||||
subtitleLangKey: 'General.SendShortcut.NewLine.Enter'
|
||||
});
|
||||
_i18n(ctrlEnterRow.radioField.main, 'General.SendShortcut.CtrlEnter', [isApple ? '⌘' : 'Ctrl']);
|
||||
_i18n(ctrlEnterRow.radioField.main, 'General.SendShortcut.CtrlEnter', [IS_APPLE ? '⌘' : 'Ctrl']);
|
||||
|
||||
form.append(enterRow.container, ctrlEnterRow.container);
|
||||
container.append(form);
|
||||
|
@ -39,8 +39,8 @@ import AppAddMembersTab from "../../sidebarLeft/tabs/addMembers";
|
||||
import PopupPickUser from "../../popups/pickUser";
|
||||
import PopupPeer, { PopupPeerButtonCallbackCheckboxes, PopupPeerCheckboxOptions } from "../../popups/peer";
|
||||
import Scrollable from "../../scrollable";
|
||||
import { isTouchSupported } from "../../../helpers/touchSupport";
|
||||
import { isFirefox } from "../../../helpers/userAgent";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../../environment/touchSupport";
|
||||
import { IS_FIREFOX } from "../../../environment/userAgent";
|
||||
import appDownloadManager from "../../../lib/appManagers/appDownloadManager";
|
||||
import ButtonCorner from "../../buttonCorner";
|
||||
import { cancelEvent } from "../../../helpers/dom/cancelEvent";
|
||||
@ -58,7 +58,7 @@ let setText = (text: string, row: Row) => {
|
||||
//});
|
||||
};
|
||||
|
||||
const PARALLAX_SUPPORTED = !isFirefox && false;
|
||||
const PARALLAX_SUPPORTED = !IS_FIREFOX && false;
|
||||
|
||||
export function filterChatPhotosMessages(value: {
|
||||
count: number;
|
||||
@ -199,7 +199,7 @@ class PeerProfileAvatars {
|
||||
|
||||
const cancelNextClick = () => {
|
||||
cancel = true;
|
||||
document.body.addEventListener(isTouchSupported ? 'touchend' : 'click', (e) => {
|
||||
document.body.addEventListener(IS_TOUCH_SUPPORTED ? 'touchend' : 'click', (e) => {
|
||||
cancel = false;
|
||||
}, {once: true});
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import { cancelEvent } from "../helpers/dom/cancelEvent";
|
||||
import { safeAssign } from "../helpers/object";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import rootScope from "../lib/rootScope";
|
||||
|
||||
const getEvent = (e: TouchEvent | MouseEvent) => {
|
||||
@ -48,7 +48,7 @@ export default class SwipeHandler {
|
||||
}
|
||||
|
||||
public setListeners() {
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.element.addEventListener('mousedown', this.handleStart, false);
|
||||
attachGlobalListenerTo.addEventListener('mouseup', this.reset);
|
||||
} else {
|
||||
@ -58,7 +58,7 @@ export default class SwipeHandler {
|
||||
}
|
||||
|
||||
public removeListeners() {
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.element.removeEventListener('mousedown', this.handleStart, false);
|
||||
attachGlobalListenerTo.removeEventListener('mouseup', this.reset);
|
||||
} else {
|
||||
@ -72,7 +72,7 @@ export default class SwipeHandler {
|
||||
cancelEvent(e);
|
||||
} */
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
attachGlobalListenerTo.removeEventListener('touchmove', this.handleMove, {capture: true});
|
||||
} else {
|
||||
attachGlobalListenerTo.removeEventListener('mousemove', this.handleMove);
|
||||
@ -96,7 +96,7 @@ export default class SwipeHandler {
|
||||
this.xDown = e.clientX;
|
||||
this.yDown = e.clientY;
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
attachGlobalListenerTo.addEventListener('touchmove', this.handleMove, {passive: false, capture: true});
|
||||
} else {
|
||||
attachGlobalListenerTo.addEventListener('mousemove', this.handleMove, false);
|
||||
@ -127,7 +127,7 @@ export default class SwipeHandler {
|
||||
|
||||
this.hadMove = true;
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.element.style.setProperty('cursor', this.cursor, 'important');
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import placeCaretAtEnd from "../helpers/dom/placeCaretAtEnd";
|
||||
import { formatPhoneNumber } from "../helpers/formatPhoneNumber";
|
||||
import { isApple, isAndroid, isAppleMobile } from "../helpers/userAgent";
|
||||
import { IS_APPLE, IS_ANDROID, IS_APPLE_MOBILE } from "../environment/userAgent";
|
||||
import { HelpCountry, HelpCountryCode } from "../layer";
|
||||
import InputField, { InputFieldOptions } from "./inputField";
|
||||
|
||||
@ -36,9 +36,9 @@ export default class TelInputField extends InputField {
|
||||
const pixelRatio = window.devicePixelRatio;
|
||||
if(pixelRatio > 1) {
|
||||
let letterSpacing: number;
|
||||
if(isApple) {
|
||||
if(IS_APPLE) {
|
||||
letterSpacing = pixelRatio * -.16;
|
||||
} else if(isAndroid) {
|
||||
} else if(IS_ANDROID) {
|
||||
letterSpacing = 0;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ export default class TelInputField extends InputField {
|
||||
|
||||
const value = this.value;
|
||||
const diff = Math.abs(value.length - this.lastValue.length);
|
||||
if(diff > 1 && !this.pasted && isAppleMobile) {
|
||||
if(diff > 1 && !this.pasted && IS_APPLE_MOBILE) {
|
||||
this.setValueSilently(this.lastValue + value);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import { deferredPromise } from '../helpers/cancellablePromise';
|
||||
import { formatDateAccordingToToday, months } from '../helpers/date';
|
||||
import mediaSizes, { ScreenSize } from '../helpers/mediaSizes';
|
||||
import { formatBytes } from '../helpers/number';
|
||||
import { isSafari } from '../helpers/userAgent';
|
||||
import { IS_SAFARI } from '../environment/userAgent';
|
||||
import { PhotoSize, StickerSet } from '../layer';
|
||||
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
|
||||
import appMessagesManager from '../lib/appManagers/appMessagesManager';
|
||||
@ -44,6 +44,8 @@ import isInDOM from '../helpers/dom/isInDOM';
|
||||
import lottieLoader from '../lib/lottieLoader';
|
||||
import { clearBadCharsAndTrim } from '../helpers/cleanSearchText';
|
||||
import blur from '../helpers/blur';
|
||||
import IS_WEBP_SUPPORTED from '../environment/webpSupport';
|
||||
import MEDIA_MIME_TYPES_SUPPORTED from '../environment/mediaMimeTypesSupport';
|
||||
|
||||
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
|
||||
|
||||
@ -382,7 +384,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
loadPromise = Promise.reject();
|
||||
} else if(!cacheContext.downloaded) { // * check for uploading video
|
||||
preloader.attach(container, false, null);
|
||||
video.addEventListener(isSafari ? 'timeupdate' : 'canplay', () => {
|
||||
video.addEventListener(IS_SAFARI ? 'timeupdate' : 'canplay', () => {
|
||||
preloader.detach();
|
||||
}, {once: true});
|
||||
}
|
||||
@ -640,10 +642,12 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
|
||||
} else if(doc.type === 'pdf') {
|
||||
download = appDocsManager.downloadDoc(doc, queueId);
|
||||
download.then(() => {
|
||||
const cacheContext = appDownloadManager.getCacheContext(doc);
|
||||
window.open(cacheContext.url);
|
||||
setTimeout(() => { // wait for preloader animation end
|
||||
const url = appDownloadManager.getCacheContext(doc).url;
|
||||
window.open(url);
|
||||
}, rootScope.settings.animationsEnabled ? 250 : 0);
|
||||
});
|
||||
} else if(doc.type === 'photo' || doc.type === 'video' || doc.mime_type.indexOf('video/') === 0) {
|
||||
} else if(MEDIA_MIME_TYPES_SUPPORTED.has(doc.mime_type)) {
|
||||
download = appDocsManager.downloadDoc(doc, queueId);
|
||||
} else {
|
||||
download = appDocsManager.saveDocFile(doc, queueId);
|
||||
@ -1149,7 +1153,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
|
||||
if(thumb && thumb._ !== 'photoPathSize' && toneIndex <= 0) {
|
||||
thumbImage = new Image();
|
||||
|
||||
if((webpWorkerController.isWebpSupported() || doc.pFlags.stickerThumbConverted || cacheContext.url)/* && false */) {
|
||||
if((IS_WEBP_SUPPORTED || doc.pFlags.stickerThumbConverted || cacheContext.url)/* && false */) {
|
||||
renderImageFromUrl(thumbImage, appPhotosManager.getPreviewURLFromThumb(doc, thumb as PhotoSize.photoStrippedSize, true), afterRender);
|
||||
haveThumbCached = true;
|
||||
} else {
|
||||
|
3
src/environment/ctx.ts
Normal file
3
src/environment/ctx.ts
Normal file
@ -0,0 +1,3 @@
|
||||
const ctx = typeof(window) !== 'undefined' ? window : self;
|
||||
|
||||
export default ctx;
|
21
src/environment/mediaMimeTypesSupport.ts
Normal file
21
src/environment/mediaMimeTypesSupport.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import IS_MOV_SUPPORTED from "./movSupport";
|
||||
import IS_WEBP_SUPPORTED from "./webpSupport";
|
||||
|
||||
const MEDIA_MIME_TYPES_SUPPORTED = new Set([
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/gif',
|
||||
'image/bmp',
|
||||
'video/mp4',
|
||||
'video/webm'
|
||||
]);
|
||||
|
||||
if(IS_MOV_SUPPORTED) {
|
||||
MEDIA_MIME_TYPES_SUPPORTED.add('video/quicktime');
|
||||
}
|
||||
|
||||
if(IS_WEBP_SUPPORTED) {
|
||||
MEDIA_MIME_TYPES_SUPPORTED.add('image/webp');
|
||||
}
|
||||
|
||||
export default MEDIA_MIME_TYPES_SUPPORTED;
|
6
src/environment/movSupport.ts
Normal file
6
src/environment/movSupport.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { IS_APPLE_MOBILE, IS_SAFARI } from "./userAgent";
|
||||
|
||||
// mov is not supported in Chrome on macOS
|
||||
const IS_MOV_SUPPORTED = !!document.createElement('video').canPlayType('video/quicktime') || IS_SAFARI || IS_APPLE_MOBILE;
|
||||
|
||||
export default IS_MOV_SUPPORTED;
|
@ -5,4 +5,4 @@
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
export const isTouchSupported = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)/* || true */;
|
||||
export const IS_TOUCH_SUPPORTED = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)/* || true */;
|
24
src/environment/userAgent.ts
Normal file
24
src/environment/userAgent.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import ctx from './ctx';
|
||||
|
||||
export const USER_AGENT = navigator ? navigator.userAgent : null;
|
||||
export const IS_APPLE = navigator.userAgent.search(/OS X|iPhone|iPad|iOS/i) !== -1;
|
||||
export const IS_ANDROID = navigator.userAgent.toLowerCase().indexOf('android') !== -1;
|
||||
export const IS_CHROMIUM = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
||||
|
||||
// https://stackoverflow.com/a/58065241
|
||||
export const IS_APPLE_MOBILE = (/iPad|iPhone|iPod/.test(navigator.platform) ||
|
||||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
|
||||
!(ctx as any).MSStream;
|
||||
|
||||
export const IS_SAFARI = !!('safari' in ctx) || !!(USER_AGENT && (/\b(iPad|iPhone|iPod)\b/.test(USER_AGENT) || (!!USER_AGENT.match('Safari') && !USER_AGENT.match('Chrome'))))/* || true */;
|
||||
export const IS_FIREFOX = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||
|
||||
export const IS_MOBILE_SAFARI = IS_SAFARI && IS_APPLE_MOBILE;
|
||||
|
||||
export const IS_MOBILE = /* screen.width && screen.width < 480 || */navigator.maxTouchPoints > 0 && navigator.userAgent.search(/iOS|iPhone OS|Android|BlackBerry|BB10|Series ?[64]0|J2ME|MIDP|opera mini|opera mobi|mobi.+Gecko|Windows Phone/i) != -1;
|
3
src/environment/webpSupport.ts
Normal file
3
src/environment/webpSupport.ts
Normal file
@ -0,0 +1,3 @@
|
||||
const IS_WEBP_SUPPORTED = document.createElement('canvas').toDataURL('image/webp').startsWith('data:image/webp');
|
||||
|
||||
export default IS_WEBP_SUPPORTED;
|
@ -4,8 +4,8 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { isMobileSafari } from "../userAgent";
|
||||
import { IS_MOBILE_SAFARI } from "../../environment/userAgent";
|
||||
|
||||
export function canFocus(isFirstInput: boolean) {
|
||||
return !isMobileSafari || !isFirstInput;
|
||||
return !IS_MOBILE_SAFARI || !isFirstInput;
|
||||
}
|
||||
|
@ -5,10 +5,10 @@
|
||||
*/
|
||||
|
||||
import type ListenerSetter from "../listenerSetter";
|
||||
import { isTouchSupported } from "../touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import simulateEvent from "./dispatchEvent";
|
||||
|
||||
export const CLICK_EVENT_NAME: 'mousedown' /* | 'touchend' */ | 'click' = (isTouchSupported ? 'mousedown' : 'click') as any;
|
||||
export const CLICK_EVENT_NAME: 'mousedown' /* | 'touchend' */ | 'click' = (IS_TOUCH_SUPPORTED ? 'mousedown' : 'click') as any;
|
||||
export type AttachClickOptions = AddEventListenerOptions & Partial<{listenerSetter: ListenerSetter, touchMouseDown: true}>;
|
||||
export function attachClickEvent(elem: HTMLElement | Window, callback: (e: /* TouchEvent | */MouseEvent) => void, options: AttachClickOptions = {}) {
|
||||
const add = options.listenerSetter ? options.listenerSetter.add(elem) : elem.addEventListener.bind(elem);
|
||||
|
@ -4,12 +4,12 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { isTouchSupported } from "../touchSupport";
|
||||
import { isMobile, isSafari } from "../userAgent";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import { IS_MOBILE, IS_SAFARI } from "../../environment/userAgent";
|
||||
import findUpClassName from "./findUpClassName";
|
||||
import fixSafariStickyInput from "./fixSafariStickyInput";
|
||||
|
||||
export const IS_STICKY_INPUT_BUGGED = isSafari && isMobile && isTouchSupported;
|
||||
export const IS_STICKY_INPUT_BUGGED = IS_SAFARI && IS_MOBILE && IS_TOUCH_SUPPORTED;
|
||||
|
||||
if(IS_STICKY_INPUT_BUGGED) {
|
||||
let key: 'clientY' | 'pageY' = 'clientY';
|
||||
|
@ -5,10 +5,10 @@
|
||||
*/
|
||||
|
||||
import type ListenerSetter from "../listenerSetter";
|
||||
import { isTouchSupported } from "../touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
|
||||
export default function handleScrollSideEvent(elem: HTMLElement, side: 'top' | 'bottom', callback: () => void, listenerSetter: ListenerSetter) {
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
let lastY: number;
|
||||
const options = {passive: true};
|
||||
listenerSetter.add(elem)('touchstart', (e) => {
|
||||
|
@ -5,10 +5,10 @@
|
||||
*/
|
||||
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import { isMobile, isApple } from "../userAgent";
|
||||
import { IS_MOBILE, IS_APPLE } from "../../environment/userAgent";
|
||||
|
||||
export default function isSendShortcutPressed(e: KeyboardEvent) {
|
||||
if(e.key === 'Enter' && !isMobile && !e.isComposing) {
|
||||
if(e.key === 'Enter' && !IS_MOBILE && !e.isComposing) {
|
||||
/* if(e.ctrlKey || e.metaKey) {
|
||||
this.messageInput.innerHTML += '<br>';
|
||||
placeCaretAtEnd(this.message)
|
||||
@ -22,8 +22,8 @@ export default function isSendShortcutPressed(e: KeyboardEvent) {
|
||||
|
||||
return true;
|
||||
} else {
|
||||
const secondaryKey = isApple ? e.metaKey : e.ctrlKey;
|
||||
if(e.shiftKey || (isApple ? e.ctrlKey : e.metaKey)) {
|
||||
const secondaryKey = IS_APPLE ? e.metaKey : e.ctrlKey;
|
||||
if(e.shiftKey || (IS_APPLE ? e.ctrlKey : e.metaKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@
|
||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { isTouchSupported } from "../touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
|
||||
export default function placeCaretAtEnd(el: HTMLElement, ignoreTouchCheck = false) {
|
||||
if(isTouchSupported && (!ignoreTouchCheck || document.activeElement !== el)) {
|
||||
if(IS_TOUCH_SUPPORTED && (!ignoreTouchCheck || document.activeElement !== el)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import findUpAsChild from "./dom/findUpAsChild";
|
||||
import EventListenerBase from "./eventListenerBase";
|
||||
import ListenerSetter from "./listenerSetter";
|
||||
import { safeAssign } from "./object";
|
||||
import { isTouchSupported } from "./touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
|
||||
const KEEP_OPEN = false;
|
||||
const TOGGLE_TIMEOUT = 200;
|
||||
@ -35,7 +35,7 @@ export default class DropdownHover extends EventListenerBase<{
|
||||
|
||||
public attachButtonListener(button: HTMLElement, listenerSetter: ListenerSetter) {
|
||||
let firstTime = true;
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
attachClickEvent(button, () => {
|
||||
if(firstTime) {
|
||||
firstTime = false;
|
||||
@ -76,7 +76,7 @@ export default class DropdownHover extends EventListenerBase<{
|
||||
};
|
||||
|
||||
protected init() {
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.element.onmouseout = this.onMouseOut;
|
||||
this.element.onmouseover = (e) => {
|
||||
if(this.forceClose) {
|
||||
@ -117,7 +117,7 @@ export default class DropdownHover extends EventListenerBase<{
|
||||
this.displayTimeout = window.setTimeout(() => {
|
||||
this.forceClose = false;
|
||||
this.dispatchEvent('opened');
|
||||
}, isTouchSupported ? 0 : ANIMATION_DURATION);
|
||||
}, IS_TOUCH_SUPPORTED ? 0 : ANIMATION_DURATION);
|
||||
|
||||
// ! can't use together with resizeObserver
|
||||
/* if(isTouchSupported) {
|
||||
@ -139,7 +139,7 @@ export default class DropdownHover extends EventListenerBase<{
|
||||
this.element.style.display = 'none';
|
||||
this.forceClose = false;
|
||||
this.dispatchEvent('closed');
|
||||
}, isTouchSupported ? 0 : ANIMATION_DURATION);
|
||||
}, IS_TOUCH_SUPPORTED ? 0 : ANIMATION_DURATION);
|
||||
|
||||
/* if(isTouchSupported) {
|
||||
const scrollHeight = this.container.scrollHeight;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
import { makeMediaSize, MediaSize } from "./mediaSizes";
|
||||
import { pause } from "./schedulers/pause";
|
||||
import { isAppleMobile } from "./userAgent";
|
||||
import { IS_APPLE_MOBILE } from "../environment/userAgent";
|
||||
|
||||
export function scaleMediaElement(options: {
|
||||
media: CanvasImageSource,
|
||||
@ -76,7 +76,7 @@ export function onVideoLoad(video: HTMLVideoElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
video.addEventListener(isAppleMobile ? 'loadeddata' : 'canplay', () => resolve(), {once: true});
|
||||
video.addEventListener(IS_APPLE_MOBILE ? 'loadeddata' : 'canplay', () => resolve(), {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
export const userAgent = navigator ? navigator.userAgent : null;
|
||||
export const isApple = navigator.userAgent.search(/OS X|iPhone|iPad|iOS/i) !== -1;
|
||||
export const isAndroid = navigator.userAgent.toLowerCase().indexOf('android') !== -1;
|
||||
export const isChromium = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
||||
|
||||
export const ctx = typeof(window) !== 'undefined' ? window : self;
|
||||
|
||||
// https://stackoverflow.com/a/58065241
|
||||
export const isAppleMobile = (/iPad|iPhone|iPod/.test(navigator.platform) ||
|
||||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
|
||||
!(ctx as any).MSStream;
|
||||
|
||||
export const isSafari = !!('safari' in ctx) || !!(userAgent && (/\b(iPad|iPhone|iPod)\b/.test(userAgent) || (!!userAgent.match('Safari') && !userAgent.match('Chrome'))))/* || true */;
|
||||
export const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||
|
||||
export const isMobileSafari = isSafari && isAppleMobile;
|
||||
|
||||
export const isMobile = /* screen.width && screen.width < 480 || */navigator.maxTouchPoints > 0 && navigator.userAgent.search(/iOS|iPhone OS|Android|BlackBerry|BB10|Series ?[64]0|J2ME|MIDP|opera mini|opera mobi|mobi.+Gecko|Windows Phone/i) != -1;
|
26
src/index.ts
26
src/index.ts
@ -9,8 +9,8 @@ import blurActiveElement from './helpers/dom/blurActiveElement';
|
||||
import { cancelEvent } from './helpers/dom/cancelEvent';
|
||||
import { IS_STICKY_INPUT_BUGGED } from './helpers/dom/fixSafariStickyInputFocusing';
|
||||
import loadFonts from './helpers/dom/loadFonts';
|
||||
import IS_EMOJI_SUPPORTED from './helpers/emojiSupport';
|
||||
import { isMobileSafari } from './helpers/userAgent';
|
||||
import IS_EMOJI_SUPPORTED from './environment/emojiSupport';
|
||||
import { IS_MOBILE_SAFARI } from './environment/userAgent';
|
||||
import './materialize.scss';
|
||||
import './scss/style.scss';
|
||||
import './scss/tgico.scss';
|
||||
@ -67,7 +67,7 @@ console.timeEnd('get storage1'); */
|
||||
const vh = (setViewportVH && !rootScope.default.isOverlayActive ? w.height || w.innerHeight : window.innerHeight) * 0.01;
|
||||
if(lastVH === vh) {
|
||||
return;
|
||||
} else if(touchSupport.isTouchSupported && lastVH < vh && (vh - lastVH) > 1) {
|
||||
} else if(touchSupport.IS_TOUCH_SUPPORTED && lastVH < vh && (vh - lastVH) > 1) {
|
||||
blurActiveElement(); // (Android) fix blurring inputs when keyboard is being closed (e.g. closing keyboard by back arrow and touching a bubble)
|
||||
}
|
||||
|
||||
@ -101,8 +101,8 @@ console.timeEnd('get storage1'); */
|
||||
|
||||
const [_, touchSupport, userAgent, rootScope, appStateManager, I18n] = await Promise.all([
|
||||
import('./lib/polyfill'),
|
||||
import('./helpers/touchSupport'),
|
||||
import('./helpers/userAgent'),
|
||||
import('./environment/touchSupport'),
|
||||
import('./environment/userAgent'),
|
||||
import('./lib/rootScope'),
|
||||
import('./lib/appManagers/appStateManager'),
|
||||
import('./lib/langPack'),
|
||||
@ -146,7 +146,7 @@ console.timeEnd('get storage1'); */
|
||||
});
|
||||
}
|
||||
|
||||
if(userAgent.isFirefox && !IS_EMOJI_SUPPORTED) {
|
||||
if(userAgent.IS_FIREFOX && !IS_EMOJI_SUPPORTED) {
|
||||
document.addEventListener('dragstart', (e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if(target.tagName === 'IMG' && target.classList.contains('emoji')) {
|
||||
@ -164,23 +164,23 @@ console.timeEnd('get storage1'); */
|
||||
}
|
||||
});
|
||||
|
||||
if(userAgent.isFirefox) {
|
||||
if(userAgent.IS_FIREFOX) {
|
||||
document.documentElement.classList.add('is-firefox');
|
||||
}
|
||||
|
||||
if(userAgent.isApple) {
|
||||
if(userAgent.isSafari) {
|
||||
if(userAgent.IS_APPLE) {
|
||||
if(userAgent.IS_SAFARI) {
|
||||
document.documentElement.classList.add('is-safari');
|
||||
}
|
||||
|
||||
document.documentElement.classList.add('emoji-supported');
|
||||
|
||||
if(userAgent.isAppleMobile) {
|
||||
if(userAgent.IS_APPLE_MOBILE) {
|
||||
document.documentElement.classList.add('is-ios');
|
||||
} else {
|
||||
document.documentElement.classList.add('is-mac');
|
||||
}
|
||||
} else if(userAgent.isAndroid) {
|
||||
} else if(userAgent.IS_ANDROID) {
|
||||
document.documentElement.classList.add('is-android');
|
||||
|
||||
/* document.addEventListener('focusin', (e) => {
|
||||
@ -193,7 +193,7 @@ console.timeEnd('get storage1'); */
|
||||
}, {passive: true}); */
|
||||
}
|
||||
|
||||
if(!touchSupport.isTouchSupported) {
|
||||
if(!touchSupport.IS_TOUCH_SUPPORTED) {
|
||||
document.documentElement.classList.add('no-touch');
|
||||
} else {
|
||||
document.documentElement.classList.add('is-touch');
|
||||
@ -257,7 +257,7 @@ console.timeEnd('get storage1'); */
|
||||
let scrollable: HTMLElement;
|
||||
if(el) {
|
||||
scrollable = el.querySelector('.scrollable') as HTMLElement;
|
||||
if((!touchSupport.isTouchSupported || isMobileSafari)) {
|
||||
if((!touchSupport.IS_TOUCH_SUPPORTED || IS_MOBILE_SAFARI)) {
|
||||
scrollable.classList.add('no-scrollbar');
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ import { ripple } from "../../components/ripple";
|
||||
//import Scrollable from "../../components/scrollable";
|
||||
import Scrollable, { ScrollableX, SliceSides } from "../../components/scrollable";
|
||||
import { formatDateAccordingToTodayNew } from "../../helpers/date";
|
||||
import { isSafari } from "../../helpers/userAgent";
|
||||
import { IS_SAFARI } from "../../environment/userAgent";
|
||||
import { logger, LogTypes } from "../logger";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import rootScope from "../rootScope";
|
||||
@ -45,7 +45,7 @@ import appChatsManager from "./appChatsManager";
|
||||
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
|
||||
import { fastRaf, fastRafConventional, fastRafPromise } from "../../helpers/schedulers";
|
||||
import SortedUserList from "../../components/sortedUserList";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import handleTabSwipe from "../../helpers/dom/handleTabSwipe";
|
||||
import windowSize from "../../helpers/windowSize";
|
||||
import isInDOM from "../../helpers/dom/isInDOM";
|
||||
@ -202,7 +202,7 @@ export class AppDialogsManager {
|
||||
});
|
||||
} */
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
handleTabSwipe(this.folders.container, (next) => {
|
||||
const prevId = selectTab.prevId();
|
||||
selectTab(next ? prevId + 1 : prevId - 1);
|
||||
@ -1100,7 +1100,7 @@ export class AppDialogsManager {
|
||||
|
||||
const saveLength = 10;
|
||||
|
||||
const sliceFromStart = isSafari ? [] : children.slice(0, Math.max(0, firstIndex - saveLength));
|
||||
const sliceFromStart = IS_SAFARI ? [] : children.slice(0, Math.max(0, firstIndex - saveLength));
|
||||
const sliceFromEnd = children.slice(lastIndex + saveLength);
|
||||
|
||||
/* if(sliceFromStart.length !== sliceFromEnd.length) {
|
||||
|
@ -15,7 +15,6 @@ import { Document, InputFileLocation, InputMedia, PhotoSize } from '../../layer'
|
||||
import referenceDatabase, { ReferenceContext } from '../mtproto/referenceDatabase';
|
||||
import opusDecodeController from '../opusDecodeController';
|
||||
import { RichTextProcessor } from '../richtextprocessor';
|
||||
import webpWorkerController from '../webp/webpWorkerController';
|
||||
import appDownloadManager, { DownloadBlob } from './appDownloadManager';
|
||||
import appPhotosManager from './appPhotosManager';
|
||||
import blur from '../../helpers/blur';
|
||||
@ -23,11 +22,16 @@ import apiManager from '../mtproto/mtprotoworker';
|
||||
import { MOUNT_CLASS_TO } from '../../config/debug';
|
||||
import { getFullDate } from '../../helpers/date';
|
||||
import rootScope from '../rootScope';
|
||||
import IS_WEBP_SUPPORTED from '../../environment/webpSupport';
|
||||
|
||||
export type MyDocument = Document.document;
|
||||
|
||||
// TODO: если залить картинку файлом, а потом перезайти в диалог - превьюшка заново скачается
|
||||
|
||||
const EXTENSION_MIME_TYPE_MAP: {[key: string]: string} = {
|
||||
mov: 'video/quicktime'
|
||||
};
|
||||
|
||||
export class AppDocsManager {
|
||||
private docs: {[docId: string]: MyDocument} = {};
|
||||
private savingLottiePreview: {[docId: string]: true} = {};
|
||||
@ -135,7 +139,7 @@ export class AppDocsManager {
|
||||
}
|
||||
|
||||
// * there can be no thumbs, then it is a document
|
||||
if(/* apiDoc.thumbs && */doc.mime_type === 'image/webp' && (doc.thumbs || webpWorkerController.isWebpSupported())) {
|
||||
if(/* apiDoc.thumbs && */doc.mime_type === 'image/webp' && (doc.thumbs || IS_WEBP_SUPPORTED)) {
|
||||
doc.type = 'sticker';
|
||||
doc.sticker = 1;
|
||||
}
|
||||
@ -158,28 +162,32 @@ export class AppDocsManager {
|
||||
});
|
||||
|
||||
if(!doc.mime_type) {
|
||||
switch(doc.type) {
|
||||
case 'gif':
|
||||
case 'video':
|
||||
case 'round':
|
||||
doc.mime_type = 'video/mp4';
|
||||
break;
|
||||
case 'sticker':
|
||||
doc.mime_type = 'image/webp';
|
||||
break;
|
||||
case 'audio':
|
||||
doc.mime_type = 'audio/mpeg';
|
||||
break;
|
||||
case 'voice':
|
||||
doc.mime_type = 'audio/ogg';
|
||||
break;
|
||||
default:
|
||||
doc.mime_type = 'application/octet-stream';
|
||||
break;
|
||||
const ext = (doc.file_name || '').split('.').pop();
|
||||
const mappedMimeType = ext && EXTENSION_MIME_TYPE_MAP[ext.toLowerCase()];
|
||||
if(mappedMimeType) {
|
||||
doc.mime_type = mappedMimeType;
|
||||
} else {
|
||||
switch(doc.type) {
|
||||
case 'gif':
|
||||
case 'video':
|
||||
case 'round':
|
||||
doc.mime_type = 'video/mp4';
|
||||
break;
|
||||
case 'sticker':
|
||||
doc.mime_type = 'image/webp';
|
||||
break;
|
||||
case 'audio':
|
||||
doc.mime_type = 'audio/mpeg';
|
||||
break;
|
||||
case 'voice':
|
||||
doc.mime_type = 'audio/ogg';
|
||||
break;
|
||||
default:
|
||||
doc.mime_type = 'application/octet-stream';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(doc.mime_type === 'application/pdf') {
|
||||
} else if(doc.mime_type === 'application/pdf') {
|
||||
doc.type = 'pdf';
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ import appStickersManager from './appStickersManager';
|
||||
import appWebPagesManager from './appWebPagesManager';
|
||||
import PopupNewMedia from '../../components/popups/newMedia';
|
||||
import MarkupTooltip from '../../components/chat/markupTooltip';
|
||||
import { isTouchSupported } from '../../helpers/touchSupport';
|
||||
import { IS_TOUCH_SUPPORTED } from '../../environment/touchSupport';
|
||||
import appPollsManager from './appPollsManager';
|
||||
import SetTransition from '../../components/singleTransition';
|
||||
import ChatDragAndDrop from '../../components/chat/dragAndDrop';
|
||||
@ -67,13 +67,14 @@ import { pause } from '../../helpers/schedulers/pause';
|
||||
import appMessagesIdsManager from './appMessagesIdsManager';
|
||||
import { InternalLink, InternalLinkTypeMap, INTERNAL_LINK_TYPE } from './internalLink';
|
||||
import RichTextProcessor from '../richtextprocessor';
|
||||
import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport';
|
||||
|
||||
//console.log('appImManager included33!');
|
||||
|
||||
appSidebarLeft; // just to include
|
||||
|
||||
export const CHAT_ANIMATION_GROUP = 'chat';
|
||||
const FOCUS_EVENT_NAME = isTouchSupported ? 'touchstart' : 'mousemove';
|
||||
const FOCUS_EVENT_NAME = IS_TOUCH_SUPPORTED ? 'touchstart' : 'mousemove';
|
||||
|
||||
export type ChatSavedPosition = {
|
||||
mids: number[],
|
||||
@ -495,7 +496,7 @@ export class AppImManager {
|
||||
e.target !== chat.input.messageInput &&
|
||||
target.tagName !== 'INPUT' &&
|
||||
!target.hasAttribute('contenteditable') &&
|
||||
!isTouchSupported &&
|
||||
!IS_TOUCH_SUPPORTED &&
|
||||
(!mediaSizes.isMobile || this.tabId === 1) &&
|
||||
!this.chat.selection.isSelecting &&
|
||||
!this.chat.input.recording) {
|
||||
@ -891,7 +892,7 @@ export class AppImManager {
|
||||
appSidebarRight.sharedMediaTab.renderNewMessages(message.peerId, [mid]);
|
||||
});
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.attachDragAndDropListeners();
|
||||
}
|
||||
|
||||
@ -917,10 +918,10 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
if(mount && !drops.length) {
|
||||
const types: string[] = await getFilesFromEvent(e, true)
|
||||
const types: string[] = await getFilesFromEvent(e, true);
|
||||
const force = isFiles && !types.length; // * can't get file items not from 'drop' on Safari
|
||||
|
||||
const foundMedia = types.filter(t => ['image', 'video'].includes(t.split('/')[0])).length;
|
||||
const foundMedia = types.filter(t => MEDIA_MIME_TYPES_SUPPORTED.has(t)).length;
|
||||
const foundDocuments = types.length - foundMedia;
|
||||
|
||||
this.log('drag files', types);
|
||||
@ -1029,12 +1030,12 @@ export class AppImManager {
|
||||
|
||||
getFilesFromEvent(e).then((files: File[]) => {
|
||||
if(files.length) {
|
||||
if(attachType === 'media' && files.find(file => !['image', 'video'].includes(file.type.split('/')[0]))) {
|
||||
if(/* attachType === 'media' && */files.find(file => !MEDIA_MIME_TYPES_SUPPORTED.has(file.type))) {
|
||||
attachType = 'document';
|
||||
}
|
||||
|
||||
const chatInput = this.chat.input;
|
||||
chatInput.willAttachType = attachType || (files[0].type.indexOf('image/') === 0 ? 'media' : "document");
|
||||
chatInput.willAttachType = attachType || (MEDIA_MIME_TYPES_SUPPORTED.has(files[0].type) ? 'media' : "document");
|
||||
new PopupNewMedia(this.chat, files, chatInput.willAttachType);
|
||||
}
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ import { CancellablePromise, deferredPromise } from "../../helpers/cancellablePr
|
||||
import { tsNow } from "../../helpers/date";
|
||||
import { deepEqual } from "../../helpers/object";
|
||||
import { convertInputKeyToKey } from "../../helpers/string";
|
||||
import { isMobile } from "../../helpers/userAgent";
|
||||
import { IS_MOBILE } from "../../environment/userAgent";
|
||||
import { InputNotifyPeer, InputPeerNotifySettings, NotifyPeer, PeerNotifySettings, Update } from "../../layer";
|
||||
import I18n from "../langPack";
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
@ -209,7 +209,7 @@ export class AppNotificationsManager {
|
||||
}
|
||||
|
||||
private toggleToggler(enable = rootScope.idle.isIDLE) {
|
||||
if(isMobile) return;
|
||||
if(IS_MOBILE) return;
|
||||
|
||||
const resetTitle = () => {
|
||||
this.titleChanged = false;
|
||||
@ -616,7 +616,7 @@ export class AppNotificationsManager {
|
||||
}
|
||||
this.notificationsShown[key] = notification;
|
||||
|
||||
if(!isMobile) {
|
||||
if(!IS_MOBILE) {
|
||||
setTimeout(() => {
|
||||
this.hide(key);
|
||||
}, 8000);
|
||||
|
@ -14,7 +14,7 @@ import { bytesFromHex } from "../../helpers/bytes";
|
||||
import { CancellablePromise } from "../../helpers/cancellablePromise";
|
||||
import { getFileNameByLocation } from "../../helpers/fileName";
|
||||
import { safeReplaceArrayInObject, isObject } from "../../helpers/object";
|
||||
import { isSafari } from "../../helpers/userAgent";
|
||||
import { IS_SAFARI } from "../../environment/userAgent";
|
||||
import { InputFileLocation, InputMedia, InputPhoto, Photo, PhotoSize, PhotosPhotos } from "../../layer";
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
import referenceDatabase, { ReferenceContext } from "../mtproto/referenceDatabase";
|
||||
@ -165,7 +165,7 @@ export class AppPhotosManager {
|
||||
|
||||
let mimeType: string;
|
||||
if(isSticker) {
|
||||
mimeType = isSafari ? 'image/png' : 'image/webp';
|
||||
mimeType = IS_SAFARI ? 'image/png' : 'image/webp';
|
||||
} else {
|
||||
mimeType = 'image/jpeg';
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import App from '../../config/app';
|
||||
import DEBUG, { MOUNT_CLASS_TO } from '../../config/debug';
|
||||
import AppStorage from '../storage';
|
||||
import { Chat } from '../../layer';
|
||||
import { isMobile } from '../../helpers/userAgent';
|
||||
import { IS_MOBILE } from '../../environment/userAgent';
|
||||
import DATABASE_STATE from '../../config/databases/state';
|
||||
import sessionStorage from '../sessionStorage';
|
||||
import { nextRandomUint } from '../../helpers/random';
|
||||
@ -112,7 +112,7 @@ export const STATE_INIT: State = {
|
||||
recentSearch: [],
|
||||
version: STATE_VERSION,
|
||||
authState: {
|
||||
_: isMobile ? 'authStateSignIn' : 'authStateSignQr'
|
||||
_: IS_MOBILE ? 'authStateSignIn' : 'authStateSignQr'
|
||||
},
|
||||
hiddenPinnedMessages: {},
|
||||
settings: {
|
||||
|
@ -11,7 +11,7 @@ import EventListenerBase from "../helpers/eventListenerBase";
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { clamp } from '../helpers/number';
|
||||
import { pause } from '../helpers/schedulers/pause';
|
||||
import { isAndroid, isApple, isAppleMobile, isSafari } from "../helpers/userAgent";
|
||||
import { IS_ANDROID, IS_APPLE, IS_APPLE_MOBILE, IS_SAFARI } from "../environment/userAgent";
|
||||
import { logger, LogTypes } from "./logger";
|
||||
import apiManager from "./mtproto/mtprotoworker";
|
||||
|
||||
@ -107,7 +107,7 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
// * Skip ratio (30fps)
|
||||
let skipRatio: number;
|
||||
if(options.skipRatio !== undefined) skipRatio = options.skipRatio;
|
||||
else if((isAndroid || isAppleMobile || (isApple && !isSafari)) && this.width < 100 && this.height < 100) {
|
||||
else if((IS_ANDROID || IS_APPLE_MOBILE || (IS_APPLE && !IS_SAFARI)) && this.width < 100 && this.height < 100) {
|
||||
skipRatio = 0.5;
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
this.height = Math.round(this.height * pixelRatio);
|
||||
} else if(pixelRatio > 1) {
|
||||
if(this.width > 100 && this.height > 100) {
|
||||
if(isApple || !mediaSizes.isMobile) {
|
||||
if(IS_APPLE || !mediaSizes.isMobile) {
|
||||
/* this.width = Math.round(this.width * (pixelRatio - 1));
|
||||
this.height = Math.round(this.height * (pixelRatio - 1)); */
|
||||
this.width = Math.round(this.width * pixelRatio);
|
||||
@ -146,7 +146,7 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
// * Cache frames params
|
||||
if(!options.noCache/* && false */) {
|
||||
// проверка на размер уже после скейлинга, сделано для попапа и сайдбара, где стикеры 80х80 и 68х68, туда нужно 75%
|
||||
if(isApple && this.width > 100 && this.height > 100) {
|
||||
if(IS_APPLE && this.width > 100 && this.height > 100) {
|
||||
this.cachingDelta = 2; //2 // 50%
|
||||
} else if(this.width < 100 && this.height < 100) {
|
||||
this.cachingDelta = Infinity; // 100%
|
||||
@ -303,7 +303,7 @@ export class RLottiePlayer extends EventListenerBase<{
|
||||
public requestFrame(frameNo: number) {
|
||||
if(this.frames[frameNo]) {
|
||||
this.renderFrame(this.frames[frameNo], frameNo);
|
||||
} else if(isSafari) {
|
||||
} else if(IS_SAFARI) {
|
||||
this.sendQuery('renderFrame', frameNo);
|
||||
} else {
|
||||
if(!this.clamped.length) { // fix detached
|
||||
@ -480,7 +480,7 @@ class QueryableWorker extends EventListenerBase<any> {
|
||||
}
|
||||
|
||||
public sendQuery(queryMethod: string, ...args: any[]) {
|
||||
if(isSafari) {
|
||||
if(IS_SAFARI) {
|
||||
this.worker.postMessage({
|
||||
'queryMethod': queryMethod,
|
||||
'queryMethodArguments': args
|
||||
|
@ -5,8 +5,8 @@
|
||||
*/
|
||||
|
||||
import appMediaPlaybackController from "../components/appMediaPlaybackController";
|
||||
import { isAppleMobile } from "../helpers/userAgent";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { IS_APPLE_MOBILE } from "../environment/userAgent";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import RangeSelector from "../components/rangeSelector";
|
||||
import { onVideoLoad } from "../helpers/files";
|
||||
import { cancelEvent } from "../helpers/dom/cancelEvent";
|
||||
@ -314,12 +314,12 @@ export default class VideoPlayer extends EventListenerBase<{
|
||||
});
|
||||
|
||||
this.listenerSetter.add(video)('click', () => {
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.togglePlay();
|
||||
}
|
||||
});
|
||||
|
||||
if(isTouchSupported) {
|
||||
if(IS_TOUCH_SUPPORTED) {
|
||||
this.listenerSetter.add(player)('click', () => {
|
||||
this.toggleControls();
|
||||
});
|
||||
@ -390,7 +390,7 @@ export default class VideoPlayer extends EventListenerBase<{
|
||||
}); */
|
||||
|
||||
this.listenerSetter.add(video)('dblclick', () => {
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
this.toggleFullScreen(fullScreenButton);
|
||||
}
|
||||
});
|
||||
@ -537,7 +537,7 @@ export default class VideoPlayer extends EventListenerBase<{
|
||||
const player = this.wrapper;
|
||||
|
||||
// * https://caniuse.com/#feat=fullscreen
|
||||
if(isAppleMobile) {
|
||||
if(IS_APPLE_MOBILE) {
|
||||
const video = this.video as any;
|
||||
video.webkitEnterFullscreen();
|
||||
video.enterFullscreen();
|
||||
|
@ -27,7 +27,7 @@ import apiManager from "./apiManager";
|
||||
import { isWebpSupported } from "./mtproto.worker";
|
||||
import { bytesToHex } from "../../helpers/bytes";
|
||||
import assumeType from "../../helpers/assumeType";
|
||||
import { ctx } from "../../helpers/userAgent";
|
||||
import ctx from "../../environment/ctx";
|
||||
|
||||
type Delayed = {
|
||||
offset: number,
|
||||
|
@ -23,11 +23,12 @@ import type { MethodDeclMap } from '../../layer';
|
||||
import { CancellablePromise, deferredPromise } from '../../helpers/cancellablePromise';
|
||||
import { bytesFromHex, bytesToHex } from '../../helpers/bytes';
|
||||
//import { clamp } from '../../helpers/number';
|
||||
import { ctx, isSafari } from '../../helpers/userAgent';
|
||||
import { IS_SAFARI } from '../../environment/userAgent';
|
||||
import App from '../../config/app';
|
||||
import { MOUNT_CLASS_TO } from '../../config/debug';
|
||||
import IDBStorage from '../idb';
|
||||
import CryptoWorker from "../crypto/cryptoworker";
|
||||
import ctx from '../../environment/ctx';
|
||||
|
||||
/// #if !MTPROTO_WORKER
|
||||
import rootScope from '../rootScope';
|
||||
@ -203,7 +204,7 @@ export class ApiManager {
|
||||
|
||||
/// #if MTPROTO_HTTP_UPLOAD
|
||||
// @ts-ignore
|
||||
const transportType: TransportType = connectionType === 'upload' && isSafari ? 'https' : 'websocket';
|
||||
const transportType: TransportType = connectionType === 'upload' && IS_SAFARI ? 'https' : 'websocket';
|
||||
//const transportType: TransportType = connectionType !== 'client' ? 'https' : 'websocket';
|
||||
/// #else
|
||||
// @ts-ignore
|
||||
|
@ -19,7 +19,7 @@ import HTTP from './transports/http';
|
||||
/// #if !MTPROTO_HTTP
|
||||
import Socket from './transports/websocket';
|
||||
import TcpObfuscated from './transports/tcpObfuscated';
|
||||
import { isSafari } from '../../helpers/userAgent';
|
||||
import { IS_SAFARI } from '../../environment/userAgent';
|
||||
import { isWebWorker } from '../../helpers/context';
|
||||
import SocketProxied from './transports/socketProxied';
|
||||
import App from '../../config/app';
|
||||
@ -64,7 +64,7 @@ export class DcConfigurator {
|
||||
|
||||
const retryTimeout = connectionType === 'client' ? 10000 : 10000;
|
||||
|
||||
const oooohLetMeLive: MTConnectionConstructable = (isSafari && isWebWorker && typeof(SocketProxied) !== 'undefined') /* || true */ ? SocketProxied : Socket;
|
||||
const oooohLetMeLive: MTConnectionConstructable = (IS_SAFARI && isWebWorker && typeof(SocketProxied) !== 'undefined') /* || true */ ? SocketProxied : Socket;
|
||||
|
||||
return new TcpObfuscated(oooohLetMeLive, dcId, chosenServer, logSuffix, retryTimeout);
|
||||
};
|
||||
|
@ -15,12 +15,12 @@ import apiManager from "./apiManager";
|
||||
import cryptoWorker from "../crypto/cryptoworker";
|
||||
import networkerFactory from "./networkerFactory";
|
||||
import apiFileManager from './apiFileManager';
|
||||
import { ctx } from '../../helpers/userAgent';
|
||||
import { notifyAll } from '../../helpers/context';
|
||||
import CacheStorageController from '../cacheStorage';
|
||||
import sessionStorage from '../sessionStorage';
|
||||
import { socketsProxied } from './transports/socketProxied';
|
||||
import { bytesToHex } from '../../helpers/bytes';
|
||||
import ctx from '../../environment/ctx';
|
||||
|
||||
let webpSupported = false;
|
||||
export const isWebpSupported = () => {
|
||||
|
@ -30,6 +30,7 @@ import { SocketProxyTask } from './transports/socketProxied';
|
||||
import telegramMeWebManager from './telegramMeWebManager';
|
||||
import { CacheStorageDbName } from '../cacheStorage';
|
||||
import { pause } from '../../helpers/schedulers/pause';
|
||||
import IS_WEBP_SUPPORTED from '../../environment/webpSupport';
|
||||
|
||||
type Task = {
|
||||
taskId: number,
|
||||
@ -318,7 +319,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
||||
this.postMessagesWaiting.forEach(args => this.postMessage(...args));
|
||||
this.postMessagesWaiting.length = 0;
|
||||
|
||||
const isWebpSupported = webpWorkerController.isWebpSupported();
|
||||
const isWebpSupported = IS_WEBP_SUPPORTED;
|
||||
this.log('WebP supported:', isWebpSupported);
|
||||
this.postMessage({type: 'webpSupport', payload: isWebpSupported});
|
||||
this.postMessage({type: 'userAgent', payload: navigator.userAgent});
|
||||
|
@ -17,7 +17,7 @@ import rootScope from "../rootScope";
|
||||
import { ServiceWorkerNotificationsClearTask, ServiceWorkerPingTask, ServiceWorkerPushClickTask } from "../serviceWorker/index.service";
|
||||
import apiManager from "./mtprotoworker";
|
||||
import I18n, { LangPackKey } from "../langPack";
|
||||
import { isMobile } from "../../helpers/userAgent";
|
||||
import { IS_MOBILE } from "../../environment/userAgent";
|
||||
import appRuntimeManager from "../appManagers/appRuntimeManager";
|
||||
|
||||
export type PushSubscriptionNotifyType = 'init' | 'subscribe' | 'unsubscribe';
|
||||
@ -163,8 +163,8 @@ export class WebPushApiManager {
|
||||
|
||||
const lang: ServiceWorkerPingTask['payload']['lang'] = {} as any;
|
||||
const ACTIONS_LANG_MAP: Record<keyof ServiceWorkerPingTask['payload']['lang'], LangPackKey> = {
|
||||
push_action_mute1d: isMobile ? 'PushNotification.Action.Mute1d.Mobile' : 'PushNotification.Action.Mute1d',
|
||||
push_action_settings: isMobile ? 'PushNotification.Action.Settings.Mobile' : 'PushNotification.Action.Settings',
|
||||
push_action_mute1d: IS_MOBILE ? 'PushNotification.Action.Mute1d.Mobile' : 'PushNotification.Action.Mute1d',
|
||||
push_action_settings: IS_MOBILE ? 'PushNotification.Action.Settings.Mobile' : 'PushNotification.Action.Settings',
|
||||
push_message_nopreview: 'PushNotification.Message.NoPreview'
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||
import { isSafari } from "../helpers/userAgent";
|
||||
import { IS_SAFARI } from "../environment/userAgent";
|
||||
import { logger, LogTypes } from "./logger";
|
||||
|
||||
type Result = {
|
||||
@ -72,7 +72,7 @@ export class OpusDecodeController {
|
||||
this.wavWorker.postMessage({
|
||||
command: 'encode',
|
||||
buffers: e.data
|
||||
}, isSafari ? undefined : data.map((typedArray: Uint8Array) => typedArray.buffer));
|
||||
}, IS_SAFARI ? undefined : data.map((typedArray: Uint8Array) => typedArray.buffer));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -136,7 +136,7 @@ export class OpusDecodeController {
|
||||
command: 'decode',
|
||||
pages: task.pages,
|
||||
waveform: task.withWaveform
|
||||
}, isSafari ? undefined : [task.pages.buffer]);
|
||||
}, IS_SAFARI ? undefined : [task.pages.buffer]);
|
||||
//}, 1e3);
|
||||
|
||||
task.timeout = window.setTimeout(() => {
|
||||
|
@ -15,9 +15,9 @@ import emojiRegExp from '../vendor/emoji/regex';
|
||||
import { encodeEmoji, toCodePoints } from '../vendor/emoji';
|
||||
import { MessageEntity } from '../layer';
|
||||
import { encodeEntities } from '../helpers/string';
|
||||
import { isSafari } from '../helpers/userAgent';
|
||||
import { IS_SAFARI } from '../environment/userAgent';
|
||||
import { MOUNT_CLASS_TO } from '../config/debug';
|
||||
import IS_EMOJI_SUPPORTED from '../helpers/emojiSupport';
|
||||
import IS_EMOJI_SUPPORTED from '../environment/emojiSupport';
|
||||
|
||||
const EmojiHelper = {
|
||||
emojiMap: (code: string) => { return code; },
|
||||
@ -115,8 +115,6 @@ for(let i in markdownEntities) {
|
||||
}
|
||||
|
||||
namespace RichTextProcessor {
|
||||
export const emojiSupported = IS_EMOJI_SUPPORTED;
|
||||
|
||||
export function getEmojiSpritesheetCoords(emojiCode: string) {
|
||||
let unified = encodeEmoji(emojiCode).replace(/-?fe0f/g, '');
|
||||
|
||||
@ -406,7 +404,7 @@ namespace RichTextProcessor {
|
||||
currentEntities.push(...filtered);
|
||||
currentEntities.sort((a, b) => a.offset - b.offset);
|
||||
|
||||
if(!emojiSupported) { // fix splitted emoji. messageEntityTextUrl can split the emoji if starts before its end (e.g. on fe0f)
|
||||
if(!IS_EMOJI_SUPPORTED) { // fix splitted emoji. messageEntityTextUrl can split the emoji if starts before its end (e.g. on fe0f)
|
||||
for(let i = 0; i < currentEntities.length; ++i) {
|
||||
const entity = currentEntities[i];
|
||||
if(entity._ === 'messageEntityEmoji') {
|
||||
@ -507,7 +505,7 @@ namespace RichTextProcessor {
|
||||
|
||||
case 'messageEntityStrike': {
|
||||
if(options.wrappingDraft) {
|
||||
const styleName = isSafari ? 'text-decoration' : 'text-decoration-line';
|
||||
const styleName = IS_SAFARI ? 'text-decoration' : 'text-decoration-line';
|
||||
insertPart(entity, `<span style="${styleName}: line-through;">`, '</span>');
|
||||
} else {
|
||||
insertPart(entity, '<del>', '</del>');
|
||||
@ -518,7 +516,7 @@ namespace RichTextProcessor {
|
||||
|
||||
case 'messageEntityUnderline': {
|
||||
if(options.wrappingDraft) {
|
||||
const styleName = isSafari ? 'text-decoration' : 'text-decoration-line';
|
||||
const styleName = IS_SAFARI ? 'text-decoration' : 'text-decoration-line';
|
||||
insertPart(entity, `<span style="${styleName}: underline;">`, '</span>');
|
||||
} else {
|
||||
insertPart(entity, '<u>', '</u>');
|
||||
@ -571,9 +569,9 @@ namespace RichTextProcessor {
|
||||
}
|
||||
|
||||
case 'messageEntityEmoji': {
|
||||
//if(!(options.wrappingDraft && emojiSupported)) { // * fix safari emoji
|
||||
if(!emojiSupported) { // no wrapping needed
|
||||
// if(emojiSupported) { // ! contenteditable="false" нужен для поля ввода, иначе там будет меняться шрифт в Safari, или же рендерить смайлик напрямую, без контейнера
|
||||
//if(!(options.wrappingDraft && IS_EMOJI_SUPPORTED)) { // * fix safari emoji
|
||||
if(!IS_EMOJI_SUPPORTED) { // no wrapping needed
|
||||
// if(IS_EMOJI_SUPPORTED) { // ! contenteditable="false" нужен для поля ввода, иначе там будет меняться шрифт в Safari, или же рендерить смайлик напрямую, без контейнера
|
||||
// insertPart(entity, '<span class="emoji">', '</span>');
|
||||
// } else {
|
||||
insertPart(entity, `<img src="assets/img/emoji/${entity.unicode}.png" alt="`, `" class="emoji">`);
|
||||
@ -581,10 +579,10 @@ namespace RichTextProcessor {
|
||||
//} else if(options.mustWrapEmoji) {
|
||||
} else if(!options.wrappingDraft) {
|
||||
insertPart(entity, '<span class="emoji">', '</span>');
|
||||
} else if(!isSafari) {
|
||||
} else if(!IS_SAFARI) {
|
||||
insertPart(entity, '<span class="emoji" contenteditable="false">', '</span>');
|
||||
}
|
||||
/* if(!emojiSupported) {
|
||||
/* if(!IS_EMOJI_SUPPORTED) {
|
||||
insertPart(entity, `<img src="assets/img/emoji/${entity.unicode}.png" alt="`, `" class="emoji">`);
|
||||
} */
|
||||
|
||||
@ -723,7 +721,7 @@ namespace RichTextProcessor {
|
||||
}
|
||||
|
||||
export function fixEmoji(text: string, entities?: MessageEntity[]) {
|
||||
/* if(!emojiSupported) {
|
||||
/* if(!IS_EMOJI_SUPPORTED) {
|
||||
return text;
|
||||
} */
|
||||
// '$`\ufe0f'
|
||||
@ -795,7 +793,7 @@ namespace RichTextProcessor {
|
||||
}
|
||||
|
||||
export function wrapPlainText(text: string) {
|
||||
if(emojiSupported) {
|
||||
if(IS_EMOJI_SUPPORTED) {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
import { Database } from "../../config/databases";
|
||||
import DATABASE_STATE from "../../config/databases/state";
|
||||
import { isFirefox } from "../../helpers/userAgent";
|
||||
import { IS_FIREFOX } from "../../environment/userAgent";
|
||||
import IDBStorage from "../idb";
|
||||
import { log, ServiceWorkerPingTask, ServiceWorkerPushClickTask } from "./index.service";
|
||||
|
||||
@ -256,7 +256,7 @@ export function closeAllNotifications() {
|
||||
}
|
||||
|
||||
function userInvisibleIsSupported() {
|
||||
return isFirefox;
|
||||
return IS_FIREFOX;
|
||||
}
|
||||
|
||||
function fireNotification(obj: PushNotificationObject, settings: PushStorage['push_settings'], lang: PushStorage['push_lang']) {
|
||||
|
@ -20,9 +20,8 @@ export type WebpConvertTask = {
|
||||
export class WebpWorkerController {
|
||||
private worker: Worker;
|
||||
private convertPromises: {[fileName: string]: CancellablePromise<Uint8Array>} = {};
|
||||
private isWebpSupportedCache: boolean;
|
||||
|
||||
init() {
|
||||
private init() {
|
||||
this.worker = new WebpWorker();
|
||||
this.worker.addEventListener('message', (e) => {
|
||||
const payload = (e.data as WebpConvertTask).payload;
|
||||
@ -39,7 +38,7 @@ export class WebpWorkerController {
|
||||
});
|
||||
}
|
||||
|
||||
postMessage(data: WebpConvertTask) {
|
||||
public postMessage(data: WebpConvertTask) {
|
||||
if(this.init) {
|
||||
this.init();
|
||||
this.init = null;
|
||||
@ -48,15 +47,7 @@ export class WebpWorkerController {
|
||||
this.worker.postMessage(data);
|
||||
}
|
||||
|
||||
isWebpSupported() {
|
||||
if(this.isWebpSupportedCache === undefined) {
|
||||
this.isWebpSupportedCache = document.createElement('canvas').toDataURL('image/webp').startsWith('data:image/webp');
|
||||
}
|
||||
|
||||
return this.isWebpSupportedCache;
|
||||
}
|
||||
|
||||
convert(fileName: string, bytes: Uint8Array) {
|
||||
public convert(fileName: string, bytes: Uint8Array) {
|
||||
fileName = 'main-' + fileName;
|
||||
|
||||
if(this.convertPromises.hasOwnProperty(fileName)) {
|
||||
|
@ -13,9 +13,9 @@ import Page from "./page";
|
||||
import InputField from "../components/inputField";
|
||||
import CheckboxField from "../components/checkboxField";
|
||||
import Button from "../components/button";
|
||||
import { isAndroid, isApple, isAppleMobile } from "../helpers/userAgent";
|
||||
import { IS_ANDROID, IS_APPLE, IS_APPLE_MOBILE } from "../environment/userAgent";
|
||||
import fastSmoothScroll from "../helpers/fastSmoothScroll";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { IS_TOUCH_SUPPORTED } from "../environment/touchSupport";
|
||||
import App from "../config/app";
|
||||
import I18n, { _i18n, i18n } from "../lib/langPack";
|
||||
import lottieLoader from "../lib/lottieLoader";
|
||||
@ -41,6 +41,7 @@ import simulateEvent from "../helpers/dom/dispatchEvent";
|
||||
import stateStorage from "../lib/stateStorage";
|
||||
import rootScope from "../lib/rootScope";
|
||||
import TelInputField from "../components/telInputField";
|
||||
import IS_EMOJI_SUPPORTED from "../environment/emojiSupport";
|
||||
|
||||
//import _countries from '../countries_pretty.json';
|
||||
let btnNext: HTMLButtonElement = null, btnQr: HTMLButtonElement;
|
||||
@ -117,7 +118,7 @@ let onFirstMount = () => {
|
||||
const li = document.createElement('li');
|
||||
|
||||
let wrapped = RichTextProcessor.wrapEmojiText(emoji);
|
||||
if(RichTextProcessor.emojiSupported) {
|
||||
if(IS_EMOJI_SUPPORTED) {
|
||||
const spanEmoji = document.createElement('span');
|
||||
spanEmoji.innerHTML = wrapped;
|
||||
li.append(spanEmoji);
|
||||
@ -477,7 +478,7 @@ let onFirstMount = () => {
|
||||
})//.catch(tryAgain);
|
||||
};
|
||||
|
||||
if(!isTouchSupported) {
|
||||
if(!IS_TOUCH_SUPPORTED) {
|
||||
setTimeout(() => {
|
||||
telEl.focus();
|
||||
}, 0);
|
||||
|
@ -2294,7 +2294,10 @@ $bubble-margin: .25rem;
|
||||
|
||||
.c-ripple__circle {
|
||||
background-color: var(--message-out-primary-color);
|
||||
opacity: .08;
|
||||
|
||||
&:not(.hiding) {
|
||||
opacity: .08;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user