Browse Source

Show .mov videos as document if it's not supported

master
morethanwords 3 years ago
parent
commit
ce715fa09f
  1. 4
      src/components/animationIntersector.ts
  2. 10
      src/components/appMediaPlaybackController.ts
  3. 17
      src/components/appMediaViewer.ts
  4. 4
      src/components/appNavigationController.ts
  5. 6
      src/components/appSearchSuper..ts
  6. 4
      src/components/audio.ts
  7. 4
      src/components/chat/autocompleteHelper.ts
  8. 22
      src/components/chat/bubbles.ts
  9. 8
      src/components/chat/contextMenu.ts
  10. 33
      src/components/chat/input.ts
  11. 14
      src/components/chat/markupTooltip.ts
  12. 4
      src/components/chat/replyKeyboard.ts
  13. 10
      src/components/chat/selection.ts
  14. 6
      src/components/chat/topbar.ts
  15. 4
      src/components/emoticonsDropdown/index.ts
  16. 9
      src/components/emoticonsDropdown/tabs/emoji.ts
  17. 16
      src/components/misc.ts
  18. 4
      src/components/poll.ts
  19. 13
      src/components/popups/newMedia.ts
  20. 4
      src/components/popups/pickUser.ts
  21. 6
      src/components/ripple.ts
  22. 4
      src/components/scrollable.ts
  23. 4
      src/components/sidebarLeft/index.ts
  24. 4
      src/components/sidebarLeft/tabs/contacts.ts
  25. 4
      src/components/sidebarLeft/tabs/generalSettings.ts
  26. 8
      src/components/sidebarRight/tabs/sharedMedia.ts
  27. 12
      src/components/swipeHandler.ts
  28. 8
      src/components/telInputField.ts
  29. 16
      src/components/wrappers.ts
  30. 3
      src/environment/ctx.ts
  31. 0
      src/environment/emojiSupport.ts
  32. 21
      src/environment/mediaMimeTypesSupport.ts
  33. 6
      src/environment/movSupport.ts
  34. 2
      src/environment/touchSupport.ts
  35. 24
      src/environment/userAgent.ts
  36. 3
      src/environment/webpSupport.ts
  37. 4
      src/helpers/dom/canFocus.ts
  38. 4
      src/helpers/dom/clickEvent.ts
  39. 6
      src/helpers/dom/fixSafariStickyInputFocusing.ts
  40. 4
      src/helpers/dom/handleScrollSideEvent.ts
  41. 8
      src/helpers/dom/isSendShortcutPressed.ts
  42. 4
      src/helpers/dom/placeCaretAtEnd.ts
  43. 10
      src/helpers/dropdownHover.ts
  44. 4
      src/helpers/files.ts
  45. 24
      src/helpers/userAgent.ts
  46. 26
      src/index.ts
  47. 8
      src/lib/appManagers/appDialogsManager.ts
  48. 54
      src/lib/appManagers/appDocsManager.ts
  49. 17
      src/lib/appManagers/appImManager.ts
  50. 6
      src/lib/appManagers/appNotificationsManager.ts
  51. 4
      src/lib/appManagers/appPhotosManager.ts
  52. 4
      src/lib/appManagers/appStateManager.ts
  53. 12
      src/lib/lottieLoader.ts
  54. 12
      src/lib/mediaPlayer.ts
  55. 2
      src/lib/mtproto/apiFileManager.ts
  56. 5
      src/lib/mtproto/apiManager.ts
  57. 4
      src/lib/mtproto/dcConfigurator.ts
  58. 2
      src/lib/mtproto/mtproto.worker.ts
  59. 3
      src/lib/mtproto/mtprotoworker.ts
  60. 6
      src/lib/mtproto/webPushApiManager.ts
  61. 6
      src/lib/opusDecodeController.ts
  62. 26
      src/lib/richtextprocessor.ts
  63. 4
      src/lib/serviceWorker/push.ts
  64. 15
      src/lib/webp/webpWorkerController.ts
  65. 9
      src/pages/pageSignIn.ts
  66. 5
      src/scss/partials/_chatBubble.scss

4
src/components/animationIntersector.ts

@ -6,7 +6,7 @@ @@ -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 { @@ -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();

10
src/components/appMediaPlaybackController.ts

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

17
src/components/appMediaViewer.ts

@ -6,8 +6,8 @@ @@ -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"; @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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);
}
}

4
src/components/appNavigationController.ts

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

6
src/components/appSearchSuper..ts

@ -38,7 +38,7 @@ import mediaSizes from "../helpers/mediaSizes"; @@ -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 { @@ -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 { @@ -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);

4
src/components/audio.ts

@ -12,7 +12,7 @@ import { MediaProgressLine } from "../lib/mediaPlayer"; @@ -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 { @@ -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;
}

4
src/components/chat/autocompleteHelper.ts

@ -7,7 +7,7 @@ @@ -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<{ @@ -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: () => {

22
src/components/chat/bubbles.ts

@ -18,7 +18,7 @@ import type { AppMessagesIdsManager } from "../../lib/appManagers/appMessagesIds @@ -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"; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -3376,7 +3376,7 @@ export default class ChatBubbles {
// ! в хроме, каким-то образом из-за zoom-fade класса начинает прыгать скролл при подгрузке сообщений вверх,
// ! т.е. скролл не ставится, так же, как в сафари при translateZ на блок выше scrollable
if(!isSafari) {
if(!IS_SAFARI) {
this.needReflowScroll = true;
}
});

8
src/components/chat/contextMenu.ts

@ -10,7 +10,7 @@ import type { AppPollsManager, Poll } from "../../lib/appManagers/appPollsManage @@ -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 { @@ -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 { @@ -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 { @@ -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;

33
src/components/chat/input.ts

@ -19,7 +19,7 @@ import type { AppInlineBotsManager } from '../../lib/appManagers/appInlineBotsMa @@ -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'; @@ -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'; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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: () => {

14
src/components/chat/markupTooltip.ts

@ -8,8 +8,8 @@ import type { AppImManager } from "../../lib/appManagers/appImManager"; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 {

4
src/components/chat/replyKeyboard.ts

@ -13,7 +13,7 @@ import rootScope from "../../lib/rootScope"; @@ -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 { @@ -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);

10
src/components/chat/selection.ts

@ -8,7 +8,7 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage @@ -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"; @@ -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 { @@ -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 { @@ -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 { @@ -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,

6
src/components/chat/topbar.ts

@ -14,7 +14,7 @@ import type { AppUsersManager } from "../../lib/appManagers/appUsersManager"; @@ -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 { @@ -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 { @@ -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
src/components/emoticonsDropdown/index.ts

@ -4,7 +4,7 @@ @@ -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 { @@ -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
src/components/emoticonsDropdown/tabs/emoji.ts

@ -9,7 +9,7 @@ import { cancelEvent } from "../../../helpers/dom/cancelEvent"; @@ -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"; @@ -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 @@ -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 @@ -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 { @@ -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();

16
src/components/misc.ts

@ -9,8 +9,8 @@ import { cancelEvent } from "../helpers/dom/cancelEvent"; @@ -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 = () => { @@ -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 = () => { @@ -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 @@ -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) { @@ -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 @@ -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 @@ -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) {

4
src/components/poll.ts

@ -5,7 +5,7 @@ @@ -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 @@ -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 {

13
src/components/popups/newMedia.ts

@ -22,6 +22,7 @@ import rootScope from "../../lib/rootScope"; @@ -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 { @@ -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
src/components/popups/pickUser.ts

@ -4,7 +4,7 @@ @@ -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 { @@ -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
src/components/ripple.ts

@ -6,7 +6,7 @@ @@ -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 @@ -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 @@ -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
src/components/scrollable.ts

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

4
src/components/sidebarLeft/index.ts

@ -28,7 +28,7 @@ import AppAddMembersTab from "./tabs/addMembers"; @@ -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 { @@ -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();

4
src/components/sidebarLeft/tabs/contacts.ts

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

4
src/components/sidebarLeft/tabs/generalSettings.ts

@ -12,7 +12,7 @@ import CheckboxField from "../../checkboxField"; @@ -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 { @@ -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);

8
src/components/sidebarRight/tabs/sharedMedia.ts

@ -39,8 +39,8 @@ import AppAddMembersTab from "../../sidebarLeft/tabs/addMembers"; @@ -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) => { @@ -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 { @@ -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});
};

12
src/components/swipeHandler.ts

@ -6,7 +6,7 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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');
}

8
src/components/telInputField.ts

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

16
src/components/wrappers.ts

@ -11,7 +11,7 @@ import { deferredPromise } from '../helpers/cancellablePromise'; @@ -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'; @@ -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 @@ -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 @@ -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 @@ -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

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
const ctx = typeof(window) !== 'undefined' ? window : self;
export default ctx;

0
src/helpers/emojiSupport.ts → src/environment/emojiSupport.ts

21
src/environment/mediaMimeTypesSupport.ts

@ -0,0 +1,21 @@ @@ -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

@ -0,0 +1,6 @@ @@ -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;

2
src/helpers/touchSupport.ts → src/environment/touchSupport.ts

@ -5,4 +5,4 @@ @@ -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

@ -0,0 +1,24 @@ @@ -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

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
const IS_WEBP_SUPPORTED = document.createElement('canvas').toDataURL('image/webp').startsWith('data:image/webp');
export default IS_WEBP_SUPPORTED;

4
src/helpers/dom/canFocus.ts

@ -4,8 +4,8 @@ @@ -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;
}

4
src/helpers/dom/clickEvent.ts

@ -5,10 +5,10 @@ @@ -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);

6
src/helpers/dom/fixSafariStickyInputFocusing.ts

@ -4,12 +4,12 @@ @@ -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';

4
src/helpers/dom/handleScrollSideEvent.ts

@ -5,10 +5,10 @@ @@ -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) => {

8
src/helpers/dom/isSendShortcutPressed.ts

@ -5,10 +5,10 @@ @@ -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) { @@ -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;
}

4
src/helpers/dom/placeCaretAtEnd.ts

@ -9,10 +9,10 @@ @@ -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;
}

10
src/helpers/dropdownHover.ts

@ -9,7 +9,7 @@ import findUpAsChild from "./dom/findUpAsChild"; @@ -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<{ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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;

4
src/helpers/files.ts

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

24
src/helpers/userAgent.ts

@ -1,24 +0,0 @@ @@ -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

@ -9,8 +9,8 @@ import blurActiveElement from './helpers/dom/blurActiveElement'; @@ -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'); */ @@ -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'); */ @@ -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'); */ @@ -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'); */ @@ -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'); */ @@ -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'); */ @@ -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');
}

8
src/lib/appManagers/appDialogsManager.ts

@ -15,7 +15,7 @@ import { ripple } from "../../components/ripple"; @@ -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"; @@ -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 { @@ -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 { @@ -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) {

54
src/lib/appManagers/appDocsManager.ts

@ -15,7 +15,6 @@ import { Document, InputFileLocation, InputMedia, PhotoSize } from '../../layer' @@ -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'; @@ -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 { @@ -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 { @@ -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';
}

17
src/lib/appManagers/appImManager.ts

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

6
src/lib/appManagers/appNotificationsManager.ts

@ -15,7 +15,7 @@ import { CancellablePromise, deferredPromise } from "../../helpers/cancellablePr @@ -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 { @@ -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 { @@ -616,7 +616,7 @@ export class AppNotificationsManager {
}
this.notificationsShown[key] = notification;
if(!isMobile) {
if(!IS_MOBILE) {
setTimeout(() => {
this.hide(key);
}, 8000);

4
src/lib/appManagers/appPhotosManager.ts

@ -14,7 +14,7 @@ import { bytesFromHex } from "../../helpers/bytes"; @@ -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 { @@ -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';
}

4
src/lib/appManagers/appStateManager.ts

@ -19,7 +19,7 @@ import App from '../../config/app'; @@ -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 = { @@ -112,7 +112,7 @@ export const STATE_INIT: State = {
recentSearch: [],
version: STATE_VERSION,
authState: {
_: isMobile ? 'authStateSignIn' : 'authStateSignQr'
_: IS_MOBILE ? 'authStateSignIn' : 'authStateSignQr'
},
hiddenPinnedMessages: {},
settings: {

12
src/lib/lottieLoader.ts

@ -11,7 +11,7 @@ import EventListenerBase from "../helpers/eventListenerBase"; @@ -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<{ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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> { @@ -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

12
src/lib/mediaPlayer.ts

@ -5,8 +5,8 @@ @@ -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<{ @@ -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<{ @@ -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<{ @@ -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();

2
src/lib/mtproto/apiFileManager.ts

@ -27,7 +27,7 @@ import apiManager from "./apiManager"; @@ -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,

5
src/lib/mtproto/apiManager.ts

@ -23,11 +23,12 @@ import type { MethodDeclMap } from '../../layer'; @@ -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 { @@ -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

4
src/lib/mtproto/dcConfigurator.ts

@ -19,7 +19,7 @@ import HTTP from './transports/http'; @@ -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 { @@ -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);
};

2
src/lib/mtproto/mtproto.worker.ts

@ -15,12 +15,12 @@ import apiManager from "./apiManager"; @@ -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 = () => {

3
src/lib/mtproto/mtprotoworker.ts

@ -30,6 +30,7 @@ import { SocketProxyTask } from './transports/socketProxied'; @@ -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 { @@ -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});

6
src/lib/mtproto/webPushApiManager.ts

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

6
src/lib/opusDecodeController.ts

@ -5,7 +5,7 @@ @@ -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 { @@ -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 { @@ -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(() => {

26
src/lib/richtextprocessor.ts

@ -15,9 +15,9 @@ import emojiRegExp from '../vendor/emoji/regex'; @@ -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) { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -795,7 +793,7 @@ namespace RichTextProcessor {
}
export function wrapPlainText(text: string) {
if(emojiSupported) {
if(IS_EMOJI_SUPPORTED) {
return text;
}

4
src/lib/serviceWorker/push.ts

@ -11,7 +11,7 @@ @@ -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() { @@ -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']) {

15
src/lib/webp/webpWorkerController.ts

@ -20,9 +20,8 @@ export type WebpConvertTask = { @@ -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 { @@ -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 { @@ -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)) {

9
src/pages/pageSignIn.ts

@ -13,9 +13,9 @@ import Page from "./page"; @@ -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"; @@ -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 = () => { @@ -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 = () => { @@ -477,7 +478,7 @@ let onFirstMount = () => {
})//.catch(tryAgain);
};
if(!isTouchSupported) {
if(!IS_TOUCH_SUPPORTED) {
setTimeout(() => {
telEl.focus();
}, 0);

5
src/scss/partials/_chatBubble.scss

@ -2294,7 +2294,10 @@ $bubble-margin: .25rem; @@ -2294,7 +2294,10 @@ $bubble-margin: .25rem;
.c-ripple__circle {
background-color: var(--message-out-primary-color);
opacity: .08;
&:not(.hiding) {
opacity: .08;
}
}
}

Loading…
Cancel
Save