MTProto networker refactor
State manager improvements Fix local storage parse New layer (119)
This commit is contained in:
parent
03ce499565
commit
a25b5e9823
6
package-lock.json
generated
6
package-lock.json
generated
@ -9102,12 +9102,6 @@
|
||||
"invert-kv": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"leemon": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/leemon/-/leemon-6.2.0.tgz",
|
||||
"integrity": "sha512-a5ieuGSGEb5ezCL6UNds5//cVFaKpeexVK0VDCE8/eOF0r0/9Og94LQ33U2Px5dUcHVCDPWQY8gXLgDlDJnyyg==",
|
||||
"dev": true
|
||||
},
|
||||
"left-pad": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
|
||||
|
@ -47,7 +47,6 @@
|
||||
"ifdef-loader": "^2.1.5",
|
||||
"install": "^0.13.0",
|
||||
"jest": "^24.9.0",
|
||||
"leemon": "^6.2.0",
|
||||
"media-query-plugin": "^1.3.1",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"node-sass": "^4.14.1",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { isInDOM, $rootScope } from "../lib/utils";
|
||||
import { isInDOM } from "../lib/utils";
|
||||
import { RLottiePlayer } from "../lib/lottieLoader";
|
||||
import { MOUNT_CLASS_TO } from "../lib/mtproto/mtproto_config";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
|
||||
export interface AnimationItem {
|
||||
el: HTMLElement,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { $rootScope } from "../lib/utils";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
import appDocsManager, {MyDocument} from "../lib/appManagers/appDocsManager";
|
||||
import { CancellablePromise, deferredPromise } from "../helpers/cancellablePromise";
|
||||
|
@ -4,11 +4,12 @@ import appMessagesIDsManager from "../lib/appManagers/appMessagesIDsManager";
|
||||
import appUsersManager from "../lib/appManagers/appUsersManager";
|
||||
import appPeersManager from '../lib/appManagers/appPeersManager';
|
||||
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
import { $rootScope, escapeRegExp } from "../lib/utils";
|
||||
import { escapeRegExp } from "../lib/utils";
|
||||
import { formatPhoneNumber } from "./misc";
|
||||
import appChatsManager from "../lib/appManagers/appChatsManager";
|
||||
import SearchInput from "./searchInput";
|
||||
import { Peer } from "../layer";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
|
||||
export class SearchGroup {
|
||||
container: HTMLDivElement;
|
||||
@ -269,7 +270,7 @@ export default class AppSearch {
|
||||
originalDialog = {
|
||||
peerID: message.peerID,
|
||||
pFlags: {},
|
||||
peer: message.to_id
|
||||
peer: message.peer_id
|
||||
} as any;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
import Scrollable from "./scrollable_new";
|
||||
import appMessagesManager, { Dialog } from "../lib/appManagers/appMessagesManager";
|
||||
import { $rootScope, cancelEvent, findUpClassName, findUpAttribute } from "../lib/utils";
|
||||
import { cancelEvent, findUpClassName, findUpAttribute } from "../lib/utils";
|
||||
import appDialogsManager from "../lib/appManagers/appDialogsManager";
|
||||
import appChatsManager from "../lib/appManagers/appChatsManager";
|
||||
import appUsersManager from "../lib/appManagers/appUsersManager";
|
||||
import appPeersManager from "../lib/appManagers/appPeersManager";
|
||||
import appPhotosManager from "../lib/appManagers/appPhotosManager";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
|
||||
type PeerType = 'contacts' | 'dialogs';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import appProfileManager from "../lib/appManagers/appProfileManager";
|
||||
import { $rootScope } from "../lib/utils";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
|
||||
$rootScope.$on('avatar_update', (e) => {
|
||||
let peerID = e.detail;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { generatePathData, $rootScope } from "../lib/utils";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
import { generatePathData } from "../lib/utils";
|
||||
|
||||
export default class BubbleGroups {
|
||||
bubblesByGroups: Array<{timestamp: number, fromID: number, mid: number, group: HTMLDivElement[]}> = []; // map to group
|
||||
|
@ -2,7 +2,8 @@ import appImManager from "../../lib/appManagers/appImManager";
|
||||
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
||||
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
||||
import { cancelEvent, $rootScope } from "../../lib/utils";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
import { cancelEvent } from "../../lib/utils";
|
||||
import appMediaPlaybackController from "../appMediaPlaybackController";
|
||||
import { formatDate } from "../wrappers";
|
||||
|
||||
|
@ -3,7 +3,8 @@ import appImManager from "../../lib/appManagers/appImManager";
|
||||
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
||||
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||
import appSidebarRight from "../../lib/appManagers/appSidebarRight";
|
||||
import { findUpClassName, $rootScope } from "../../lib/utils";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
import { findUpClassName } from "../../lib/utils";
|
||||
import { parseMenuButtonsTo, attachContextMenuListener, positionMenu, openBtnMenu } from "../misc";
|
||||
import { PopupButton, PopupPeer } from "../popup";
|
||||
|
||||
|
@ -10,11 +10,11 @@ import { Layouter, RectPart } from "../groupedLayout";
|
||||
import Recorder from '../../../public/recorder.min';
|
||||
//import Recorder from '../opus-recorder/dist/recorder.min';
|
||||
import opusDecodeController from "../../lib/opusDecodeController";
|
||||
import { touchSupport } from "../../lib/config";
|
||||
import appDocsManager from "../../lib/appManagers/appDocsManager";
|
||||
import emoticonsDropdown from "../emoticonsDropdown";
|
||||
import PopupCreatePoll from "../popupCreatePoll";
|
||||
import { toast } from "../toast";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
|
||||
const RECORD_MIN_TIME = 500;
|
||||
|
||||
@ -104,7 +104,7 @@ export class ChatInput {
|
||||
this.updateSendBtn();
|
||||
|
||||
this.messageInput.addEventListener('keydown', (e: KeyboardEvent) => {
|
||||
if(e.key == 'Enter' && !touchSupport) {
|
||||
if(e.key == 'Enter' && !isTouchSupported) {
|
||||
/* if(e.ctrlKey || e.metaKey) {
|
||||
this.messageInput.innerHTML += '<br>';
|
||||
placeCaretAtEnd(this.message)
|
||||
@ -119,7 +119,7 @@ export class ChatInput {
|
||||
}
|
||||
});
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
this.messageInput.addEventListener('touchend', (e) => {
|
||||
this.saveScroll();
|
||||
emoticonsDropdown.toggle(false);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import appImManager from "../../lib/appManagers/appImManager";
|
||||
import { $rootScope, cancelEvent, whichChild, findUpTag } from "../../lib/utils";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
import { cancelEvent, whichChild, findUpTag } from "../../lib/utils";
|
||||
import AppSearch, { SearchGroup } from "../appSearch";
|
||||
import PopupDatePicker from "../popupDatepicker";
|
||||
import { ripple } from "../ripple";
|
||||
|
@ -1,6 +1,5 @@
|
||||
import LazyLoadQueue from "../lazyLoadQueue";
|
||||
import GifsTab from "./tabs/gifs";
|
||||
import { touchSupport } from "../../lib/config";
|
||||
import { findUpClassName, findUpTag, whichChild } from "../../lib/utils";
|
||||
import { horizontalMenu } from "../horizontalMenu";
|
||||
import animationIntersector from "../animationIntersector";
|
||||
@ -11,6 +10,7 @@ import EmojiTab from "./tabs/emoji";
|
||||
import StickersTab from "./tabs/stickers";
|
||||
import StickyIntersector from "../stickyIntersector";
|
||||
import { MOUNT_CLASS_TO } from "../../lib/mtproto/mtproto_config";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
|
||||
export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';
|
||||
|
||||
@ -58,7 +58,7 @@ export class EmoticonsDropdown {
|
||||
|
||||
let firstTime = true;
|
||||
this.toggleEl = document.getElementById('toggle-emoticons');
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
this.toggleEl.addEventListener('click', () => {
|
||||
if(firstTime) {
|
||||
firstTime = false;
|
||||
@ -172,7 +172,7 @@ export class EmoticonsDropdown {
|
||||
}
|
||||
}
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
this.toggleEl.classList.toggle('flip-icon', willBeActive);
|
||||
if(willBeActive) {
|
||||
appImManager.chatInputC.saveScroll();
|
||||
@ -204,7 +204,7 @@ export class EmoticonsDropdown {
|
||||
EmoticonsDropdown.lazyLoadQueue.refresh();
|
||||
|
||||
this.events.onOpenAfter.forEach(cb => cb());
|
||||
}, touchSupport ? 0 : 200);
|
||||
}, isTouchSupported ? 0 : 200);
|
||||
|
||||
/* if(touchSupport) {
|
||||
this.restoreScroll();
|
||||
@ -231,7 +231,7 @@ export class EmoticonsDropdown {
|
||||
EmoticonsDropdown.lazyLoadQueue.refresh();
|
||||
|
||||
this.events.onCloseAfter.forEach(cb => cb());
|
||||
}, touchSupport ? 0 : 200);
|
||||
}, isTouchSupported ? 0 : 200);
|
||||
|
||||
/* if(touchSupport) {
|
||||
this.restoreScroll();
|
||||
|
@ -8,7 +8,7 @@ import { readBlobAsText } from "../../../helpers/blob";
|
||||
import lottieLoader from "../../../lib/lottieLoader";
|
||||
import { renderImageFromUrl, putPreloader } from "../../misc";
|
||||
import { RichTextProcessor } from "../../../lib/richtextprocessor";
|
||||
import { $rootScope } from "../../../lib/utils";
|
||||
import $rootScope from "../../../lib/rootScope";
|
||||
import apiManager from "../../../lib/mtproto/mtprotoworker";
|
||||
import StickyIntersector from "../../stickyIntersector";
|
||||
import appDocsManager, {MyDocument} from "../../../lib/appManagers/appDocsManager";
|
||||
|
@ -28,6 +28,7 @@ function slideTabs(tabContent: HTMLElement, prevTabContent: HTMLElement, width:
|
||||
|
||||
export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?: (id: number, tabContent: HTMLDivElement) => void, onTransitionEnd?: () => void, transitionTime = 250) {
|
||||
const hideTimeouts: {[id: number]: number} = {};
|
||||
let transitionEndTimeout: number;
|
||||
let prevTabContent: HTMLElement = null;
|
||||
let prevId = -1;
|
||||
|
||||
@ -88,10 +89,16 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
|
||||
}
|
||||
|
||||
delete hideTimeouts[_prevId];
|
||||
|
||||
if(onTransitionEnd) onTransitionEnd();
|
||||
}, /* 420 */transitionTime);
|
||||
}
|
||||
|
||||
if(onTransitionEnd) {
|
||||
if(transitionEndTimeout) clearTimeout(transitionEndTimeout);
|
||||
transitionEndTimeout = window.setTimeout(() => {
|
||||
onTransitionEnd();
|
||||
transitionEndTimeout = 0;
|
||||
}, transitionTime);
|
||||
}
|
||||
}
|
||||
|
||||
prevId = id;
|
||||
prevTabContent = tabContent;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { isApple } from "../helpers/userAgent";
|
||||
import Config, { touchSupport } from "../lib/config";
|
||||
import Config from "../lib/config";
|
||||
|
||||
export const loadedURLs: {[url: string]: boolean} = {};
|
||||
const set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLVideoElement, url: string) => {
|
||||
@ -144,7 +145,7 @@ let closeBtnMenu = () => {
|
||||
|
||||
//document.body.classList.remove('disable-hover');
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
window.removeEventListener('touchmove', onClick);
|
||||
//window.removeEventListener('touchstart', onClick);
|
||||
} else {
|
||||
@ -182,7 +183,7 @@ export function openBtnMenu(menuElement: HTMLDivElement, onClose?: () => void) {
|
||||
|
||||
openedMenuOnClose = onClose;
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
window.addEventListener('touchmove', onClick, {once: true});
|
||||
//window.addEventListener('touchstart', onClick);
|
||||
} else {
|
||||
@ -233,7 +234,7 @@ export function positionMenu({clientX, clientY}: {clientX: number, clientY: numb
|
||||
}
|
||||
|
||||
export function attachContextMenuListener(element: HTMLElement, callback: (e: Touch | MouseEvent) => void) {
|
||||
if(isApple && touchSupport) {
|
||||
if(isApple && isTouchSupported) {
|
||||
let timeout: number;
|
||||
|
||||
const onCancel = () => {
|
||||
|
@ -1,12 +1,13 @@
|
||||
import appPollsManager, { PollResults, Poll } from "../lib/appManagers/appPollsManager";
|
||||
import { RichTextProcessor } from "../lib/richtextprocessor";
|
||||
import { findUpClassName, $rootScope, cancelEvent } from "../lib/utils";
|
||||
import { touchSupport } from "../lib/config";
|
||||
import { findUpClassName, cancelEvent } from "../lib/utils";
|
||||
import appSidebarRight from "../lib/appManagers/appSidebarRight";
|
||||
import appImManager from "../lib/appManagers/appImManager";
|
||||
import serverTimeManager from "../lib/mtproto/serverTimeManager";
|
||||
import { ripple } from "./ripple";
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
|
||||
let lineTotalLength = 0;
|
||||
const tailLength = 9;
|
||||
@ -126,7 +127,7 @@ const setQuizHint = (solution: string, solution_entities: any[], onHide: () => v
|
||||
prevQuizHintOnHide = onHide;
|
||||
prevQuizHintTimeout = window.setTimeout(() => {
|
||||
hideQuizHint(element, onHide, prevQuizHintTimeout);
|
||||
}, touchSupport ? 5000 : 7000);
|
||||
}, isTouchSupported ? 5000 : 7000);
|
||||
};
|
||||
|
||||
export default class PollElement extends HTMLElement {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { PopupElement } from "./popup";
|
||||
import Scrollable from "./scrollable_new";
|
||||
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
import { $rootScope } from "../lib/utils";
|
||||
import $rootScope from "../lib/rootScope";
|
||||
import { Poll } from "../lib/appManagers/appPollsManager";
|
||||
import { toast } from "./toast";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { touchSupport } from "../lib/config";
|
||||
import {isTouchSupported} from "../helpers/touchSupport";
|
||||
import { findUpClassName } from "../lib/utils";
|
||||
|
||||
let rippleClickID = 0;
|
||||
@ -129,7 +129,7 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
|
||||
|
||||
// TODO: rename this variable
|
||||
let touchStartFired = false;
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
let touchEnd = () => {
|
||||
handler && handler();
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { logger, LogLevels } from "../lib/logger";
|
||||
import smoothscroll, { SCROLL_TIME, SmoothScrollToOptions } from '../vendor/smoothscroll';
|
||||
import { touchSupport } from "../lib/config";
|
||||
//import { CancellablePromise, deferredPromise } from "../lib/polyfill";
|
||||
//import { isInDOM } from "../lib/utils";
|
||||
(window as any).__forceSmoothScrollPolyfill__ = true;
|
||||
@ -509,7 +509,7 @@ export class ScrollableX extends ScrollableBase {
|
||||
|
||||
this.container.classList.add('scrollable-x');
|
||||
|
||||
if(!touchSupport) {
|
||||
if(!isTouchSupported) {
|
||||
const scrollHorizontally = (e: any) => {
|
||||
e = window.event || e;
|
||||
if(e.which == 1) {
|
||||
|
@ -4,11 +4,12 @@ import apiManager from "../../lib/mtproto/mtprotoworker";
|
||||
import appMessagesManager, { MyDialogFilter } from "../../lib/appManagers/appMessagesManager";
|
||||
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
||||
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||
import { $rootScope, cancelEvent } from "../../lib/utils";
|
||||
import { cancelEvent } from "../../lib/utils";
|
||||
import appSidebarLeft from "../../lib/appManagers/appSidebarLeft";
|
||||
import { ripple } from "../ripple";
|
||||
import { toast } from "../toast";
|
||||
import { DialogFilterSuggested, DialogFilter } from "../../layer";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
|
||||
export default class AppChatFoldersTab implements SliderTab {
|
||||
public container: HTMLElement;
|
||||
|
@ -4,7 +4,7 @@ import appDialogsManager from "../../lib/appManagers/appDialogsManager";
|
||||
import appUsersManager from "../../lib/appManagers/appUsersManager";
|
||||
import appPhotosManager from "../../lib/appManagers/appPhotosManager";
|
||||
import appSidebarLeft, { AppSidebarLeft } from "../../lib/appManagers/appSidebarLeft";
|
||||
import { $rootScope } from "../../lib/utils";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
import SearchInput from "../searchInput";
|
||||
|
||||
// TODO: поиск по людям глобальный, если не нашло в контактах никого
|
||||
|
@ -5,7 +5,7 @@ import appProfileManager from "../../lib/appManagers/appProfileManager";
|
||||
import appSidebarLeft from "../../lib/appManagers/appSidebarLeft";
|
||||
import Scrollable from "../scrollable_new";
|
||||
import appUsersManager from "../../lib/appManagers/appUsersManager";
|
||||
import { $rootScope } from "../../lib/utils";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
import { InputFile } from "../../layer";
|
||||
|
||||
// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист)
|
||||
|
@ -4,8 +4,9 @@ import appSidebarLeft, { AppSidebarLeft } from "../../lib/appManagers/appSidebar
|
||||
import appDialogsManager from "../../lib/appManagers/appDialogsManager";
|
||||
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||
import appUsersManager from "../../lib/appManagers/appUsersManager";
|
||||
import { $rootScope, copy } from "../../lib/utils";
|
||||
import { copy } from "../../lib/utils";
|
||||
import { MyDialogFilter as DialogFilter } from "../../lib/appManagers/appMessagesManager";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
|
||||
export default class AppIncludedChatsTab implements SliderTab {
|
||||
public container: HTMLElement;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { SliderTab } from "../slider";
|
||||
import AvatarElement from "../avatar";
|
||||
import { parseMenuButtonsTo } from "../misc";
|
||||
import { $rootScope } from "../../lib/utils";
|
||||
//import $rootScope from "../../lib/rootScope";
|
||||
import apiManager from "../../lib/mtproto/mtprotoworker";
|
||||
import appSidebarLeft, { AppSidebarLeft } from "../../lib/appManagers/appSidebarLeft";
|
||||
import appUsersManager from "../../lib/appManagers/appUsersManager";
|
||||
@ -26,9 +26,9 @@ export default class AppSettingsTab implements SliderTab {
|
||||
constructor() {
|
||||
parseMenuButtonsTo(this.buttons, this.container.querySelector('.profile-buttons').children);
|
||||
|
||||
$rootScope.$on('user_auth', (e) => {
|
||||
/* $rootScope.$on('user_auth', (e) => {
|
||||
this.fillElements();
|
||||
});
|
||||
}); */
|
||||
|
||||
this.logOutBtn.addEventListener('click', (e) => {
|
||||
apiManager.logOut();
|
||||
|
@ -7,7 +7,7 @@ import appProfileManager from "../../lib/appManagers/appProfileManager";
|
||||
import appUsersManager from "../../lib/appManagers/appUsersManager";
|
||||
import { logger, LogLevels } from "../../lib/logger";
|
||||
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
||||
import { $rootScope } from "../../lib/utils";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
import AvatarElement from "../avatar";
|
||||
import { horizontalMenu } from "../horizontalMenu";
|
||||
import LazyLoadQueue from "../lazyLoadQueue";
|
||||
@ -32,11 +32,11 @@ let setText = (text: string, el: HTMLDivElement) => {
|
||||
});
|
||||
};
|
||||
|
||||
type ContentType = 'contentMembers' | 'contentMedia' | 'contentDocuments' | 'contentLinks' | 'contentAudio';
|
||||
type SharedMediaType = 'inputMessagesFilterContacts' | 'inputMessagesFilterPhotoVideo' | 'inputMessagesFilterDocument' | 'inputMessagesFilterUrl' | 'inputMessagesFilterMusic';
|
||||
type ContentType = /* 'contentMembers' | */'contentMedia' | 'contentDocuments' | 'contentLinks' | 'contentAudio';
|
||||
type SharedMediaType = /* 'inputMessagesFilterContacts' | */'inputMessagesFilterEmpty' | 'inputMessagesFilterPhotoVideo' | 'inputMessagesFilterDocument' | 'inputMessagesFilterUrl' | 'inputMessagesFilterMusic';
|
||||
|
||||
const contentToSharedMap: {[contentType in ContentType]: SharedMediaType} = {
|
||||
contentMembers: 'inputMessagesFilterContacts',
|
||||
//contentMembers: 'inputMessagesFilterContacts',
|
||||
contentMedia: 'inputMessagesFilterPhotoVideo',
|
||||
contentDocuments: 'inputMessagesFilterDocument',
|
||||
contentLinks: 'inputMessagesFilterUrl',
|
||||
@ -74,7 +74,8 @@ export default class AppSharedMediaTab implements SliderTab {
|
||||
|
||||
public sharedMediaTypes: SharedMediaType[] = [
|
||||
//'members',
|
||||
'inputMessagesFilterContacts',
|
||||
'inputMessagesFilterEmpty',
|
||||
//'inputMessagesFilterContacts',
|
||||
'inputMessagesFilterPhotoVideo',
|
||||
'inputMessagesFilterDocument',
|
||||
'inputMessagesFilterUrl',
|
||||
@ -128,7 +129,7 @@ export default class AppSharedMediaTab implements SliderTab {
|
||||
};
|
||||
|
||||
this.sharedMedia = {
|
||||
contentMembers: this.profileContentEl.querySelector('#content-members'),
|
||||
//contentMembers: this.profileContentEl.querySelector('#content-members'),
|
||||
contentMedia: this.profileContentEl.querySelector('#content-media'),
|
||||
contentDocuments: this.profileContentEl.querySelector('#content-docs'),
|
||||
contentLinks: this.profileContentEl.querySelector('#content-links'),
|
||||
|
@ -1,4 +1,5 @@
|
||||
export function parse(text: string) {
|
||||
// TOO SLOW
|
||||
/* export function parse(text: string) {
|
||||
let arr: number[] = [], performedValue: any = null;
|
||||
return JSON.parse(text, (key, value) => {
|
||||
//console.log(key, value);
|
||||
@ -19,7 +20,7 @@ export function parse(text: string) {
|
||||
|
||||
return value;
|
||||
});
|
||||
}
|
||||
} */
|
||||
// parse('{"file_reference": {"type": "bytes", "value": [1,2,3]}, "file_reference2": {"type": "bytes", "value": [3,2,1]}}');
|
||||
// -> {file_reference: Uint8Array}
|
||||
|
||||
|
2
src/helpers/touchSupport.ts
Normal file
2
src/helpers/touchSupport.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// @ts-ignore
|
||||
export const isTouchSupported = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch);
|
638
src/layer.d.ts
vendored
638
src/layer.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,13 @@
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
//import networkerFactory from '../mtproto/networkerFactory';
|
||||
import { $rootScope, tsNow } from "../utils";
|
||||
import { tsNow } from "../utils";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import { logger, LogLevels } from '../logger';
|
||||
import $rootScope from '../rootScope';
|
||||
import appStateManager from './appStateManager';
|
||||
|
||||
export class ApiUpdatesManager {
|
||||
public updatesState: {
|
||||
@ -27,7 +29,18 @@ export class ApiUpdatesManager {
|
||||
public channelStates: any = {};
|
||||
private attached = false;
|
||||
|
||||
private log = logger('UPDATES', LogLevels.error);
|
||||
private log = logger('UPDATES'/* , LogLevels.error */);
|
||||
|
||||
constructor() {
|
||||
appStateManager.addListener('save', () => {
|
||||
const us = this.updatesState;
|
||||
appStateManager.pushToState('updates', {
|
||||
seq: us.seq,
|
||||
pts: us.pts,
|
||||
date: us.date
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public popPendingSeqUpdate() {
|
||||
var nextSeq = this.updatesState.seq + 1;
|
||||
@ -135,12 +148,13 @@ export class ApiUpdatesManager {
|
||||
break;
|
||||
|
||||
case 'updateShortMessage':
|
||||
case 'updateShortChatMessage':
|
||||
var isOut = updateMessage.flags & 2;
|
||||
var fromID = updateMessage.from_id || (isOut ? $rootScope.myID : updateMessage.user_id);
|
||||
var toID = updateMessage.chat_id
|
||||
case 'updateShortChatMessage': {
|
||||
this.log('updateShortMessage | updateShortChatMessage', {...updateMessage});
|
||||
const isOut = updateMessage.pFlags.out;
|
||||
const fromID = updateMessage.from_id || (isOut ? $rootScope.myID : updateMessage.user_id);
|
||||
const toID = updateMessage.chat_id
|
||||
? -updateMessage.chat_id
|
||||
: (isOut ? updateMessage.user_id : $rootScope.myID);
|
||||
: (updateMessage.user_id || $rootScope.myID);
|
||||
|
||||
this.processUpdate({
|
||||
_: 'updateNewMessage',
|
||||
@ -149,8 +163,8 @@ export class ApiUpdatesManager {
|
||||
flags: updateMessage.flags,
|
||||
pFlags: updateMessage.pFlags,
|
||||
id: updateMessage.id,
|
||||
from_id: fromID,
|
||||
to_id: appPeersManager.getOutputPeer(toID),
|
||||
from_id: appPeersManager.getOutputPeer(fromID),
|
||||
peer_id: appPeersManager.getOutputPeer(toID),
|
||||
date: updateMessage.date,
|
||||
message: updateMessage.message,
|
||||
fwd_from: updateMessage.fwd_from,
|
||||
@ -161,6 +175,7 @@ export class ApiUpdatesManager {
|
||||
pts_count: updateMessage.pts_count
|
||||
}, processOpts);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'updatesCombined':
|
||||
case 'updates':
|
||||
@ -364,7 +379,7 @@ export class ApiUpdatesManager {
|
||||
switch(update._) {
|
||||
case 'updateNewChannelMessage':
|
||||
case 'updateEditChannelMessage':
|
||||
channelID = -appPeersManager.getPeerID(update.message.to_id);
|
||||
channelID = -appPeersManager.getPeerID(update.message.peer_id);
|
||||
break;
|
||||
case 'updateDeleteChannelMessages':
|
||||
channelID = update.channel_id;
|
||||
@ -399,11 +414,11 @@ export class ApiUpdatesManager {
|
||||
update._ == 'updateNewChannelMessage' ||
|
||||
update._ == 'updateEditChannelMessage') {
|
||||
var message = update.message;
|
||||
var toPeerID = appPeersManager.getPeerID(message.to_id);
|
||||
var toPeerID = appPeersManager.getPeerID(message.peer_id);
|
||||
var fwdHeader = message.fwd_from || {};
|
||||
var reason: any = false;
|
||||
if(message.from_id && !appUsersManager.hasUser(message.from_id, message.pFlags.post/* || channelID*/) && (reason = 'author') ||
|
||||
fwdHeader.from_id && !appUsersManager.hasUser(fwdHeader.from_id, !!fwdHeader.channel_id) && (reason = 'fwdAuthor') ||
|
||||
if(message.from_id && !appUsersManager.hasUser(appPeersManager.getPeerID(message.from_id), message.pFlags.post/* || channelID*/) && (reason = 'author') ||
|
||||
fwdHeader.from_id && !appUsersManager.hasUser(appPeersManager.getPeerID(fwdHeader.from_id), !!fwdHeader.channel_id) && (reason = 'fwdAuthor') ||
|
||||
fwdHeader.channel_id && !appChatsManager.hasChat(fwdHeader.channel_id, true) && (reason = 'fwdChannel') ||
|
||||
toPeerID > 0 && !appUsersManager.hasUser(toPeerID) && (reason = 'toPeer User') ||
|
||||
toPeerID < 0 && !appChatsManager.hasChat(-toPeerID) && (reason = 'toPeer Chat')) {
|
||||
@ -509,32 +524,37 @@ export class ApiUpdatesManager {
|
||||
$rootScope.$broadcast('apiUpdate', update);
|
||||
}
|
||||
|
||||
public attach(state: Pick<ApiUpdatesManager['updatesState'], 'seq' | 'pts' | 'date'>) {
|
||||
public attach() {
|
||||
if(this.attached) return;
|
||||
|
||||
//return;
|
||||
|
||||
this.attached = true;
|
||||
apiManager.setUpdatesProcessor(this.processUpdateMessage.bind(this));
|
||||
|
||||
if(!state || !state.pts || !state.date || !state.seq) {
|
||||
apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult) => {
|
||||
this.updatesState.seq = stateResult.seq;
|
||||
this.updatesState.pts = stateResult.pts;
|
||||
this.updatesState.date = stateResult.date;
|
||||
setTimeout(() => {
|
||||
this.updatesState.syncLoading = false;
|
||||
}, 1000);
|
||||
|
||||
// updatesState.seq = 1
|
||||
// updatesState.pts = stateResult.pts - 5000
|
||||
// updatesState.date = 1
|
||||
// getDifference()
|
||||
});
|
||||
} else {
|
||||
Object.assign(this.updatesState, state);
|
||||
this.getDifference();
|
||||
}
|
||||
appStateManager.getState().then(_state => {
|
||||
const state = _state.updates;
|
||||
|
||||
apiManager.setUpdatesProcessor(this.processUpdateMessage.bind(this));
|
||||
|
||||
if(!state || !state.pts || !state.date || !state.seq) {
|
||||
apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult) => {
|
||||
this.updatesState.seq = stateResult.seq;
|
||||
this.updatesState.pts = stateResult.pts;
|
||||
this.updatesState.date = stateResult.date;
|
||||
setTimeout(() => {
|
||||
this.updatesState.syncLoading = false;
|
||||
}, 1000);
|
||||
|
||||
// updatesState.seq = 1
|
||||
// updatesState.pts = stateResult.pts - 5000
|
||||
// updatesState.date = 1
|
||||
// getDifference()
|
||||
});
|
||||
} else {
|
||||
Object.assign(this.updatesState, state);
|
||||
this.getDifference();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { $rootScope, isObject, safeReplaceObject, copy, numberWithCommas, getAbbreviation } from "../utils";
|
||||
import { isObject, safeReplaceObject, copy, numberWithCommas, getAbbreviation } from "../utils";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
@ -6,6 +6,7 @@ import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appProfileManager from "./appProfileManager";
|
||||
import searchIndexManager from "../searchIndexManager";
|
||||
import { InputPeer, InputChannel, Updates, InputChatPhoto } from "../../layer";
|
||||
import $rootScope from "../rootScope";
|
||||
|
||||
export type Channel = {
|
||||
_: 'channel',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { findUpClassName, $rootScope, escapeRegExp, findUpTag, cancelEvent, positionElementByIndex } from "../utils";
|
||||
import { findUpClassName, escapeRegExp, findUpTag, cancelEvent, positionElementByIndex } from "../utils";
|
||||
import appImManager, { AppImManager } from "./appImManager";
|
||||
import appPeersManager from './appPeersManager';
|
||||
import appMessagesManager, { Dialog, MyDialogFilter as DialogFilter } from "./appMessagesManager";
|
||||
@ -13,11 +13,12 @@ import AvatarElement from "../../components/avatar";
|
||||
import { PopupButton, PopupPeer } from "../../components/popup";
|
||||
import { SliderTab } from "../../components/slider";
|
||||
import appStateManager from "./appStateManager";
|
||||
import { touchSupport } from "../config";
|
||||
import { horizontalMenu } from "../../components/horizontalMenu";
|
||||
import { ripple } from "../../components/ripple";
|
||||
import { isSafari } from "../../helpers/userAgent";
|
||||
import { formatDateAccordingToToday, getWeekNumber } from "../../helpers/date";
|
||||
import { formatDateAccordingToToday } from "../../helpers/date";
|
||||
import $rootScope from "../rootScope";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
|
||||
type DialogDom = {
|
||||
avatarEl: AvatarElement,
|
||||
@ -386,7 +387,7 @@ export class AppDialogsManager {
|
||||
this.scroll.setVirtualContainer(this.chatList);
|
||||
//this.scroll.attachSentinels();
|
||||
|
||||
if(touchSupport && isSafari) {
|
||||
if(isTouchSupported && isSafari) {
|
||||
let allowUp: boolean, allowDown: boolean, slideBeginY: number;
|
||||
const container = this.scroll.container;
|
||||
container.addEventListener('touchstart', (event) => {
|
||||
@ -981,8 +982,8 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
/* if(lastMessage.from_id == auth.id) { // You: */
|
||||
if(peer._ != 'peerUser' && peerID != -lastMessage.from_id) {
|
||||
let sender = appUsersManager.getUser(lastMessage.from_id);
|
||||
if(peer._ != 'peerUser' && peerID != lastMessage.fromID) {
|
||||
let sender = appUsersManager.getUser(lastMessage.fromID);
|
||||
if(sender && sender.id) {
|
||||
let senderBold = document.createElement('b');
|
||||
|
||||
@ -1030,7 +1031,7 @@ export class AppDialogsManager {
|
||||
|
||||
const lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
||||
if(lastMessage._ != 'messageEmpty' && !lastMessage.deleted &&
|
||||
lastMessage.from_id == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
|
||||
lastMessage.fromID == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
|
||||
dialog.read_outbox_max_id) { // maybe comment, 06.20.2020
|
||||
const outgoing = (lastMessage.pFlags && lastMessage.pFlags.unread)
|
||||
/* && dialog.read_outbox_max_id != 0 */; // maybe uncomment, 31.01.2020
|
||||
|
@ -4,7 +4,6 @@ import opusDecodeController from '../opusDecodeController';
|
||||
import { getFileNameByLocation } from '../bin_utils';
|
||||
import appDownloadManager, { DownloadBlob } from './appDownloadManager';
|
||||
import appPhotosManager from './appPhotosManager';
|
||||
import { isServiceWorkerSupported } from '../config';
|
||||
import { InputFileLocation, Document, PhotoSize } from '../../layer';
|
||||
import referenceDatabase, { ReferenceContext } from '../mtproto/referenceDatabase';
|
||||
import { MOUNT_CLASS_TO } from '../mtproto/mtproto_config';
|
||||
@ -137,7 +136,7 @@ class AppDocsManager {
|
||||
}
|
||||
}
|
||||
|
||||
if(isServiceWorkerSupported) {
|
||||
if('serviceWorker' in navigator) {
|
||||
if((doc.type == 'gif' && doc.size > 8e6) || doc.type == 'audio' || doc.type == 'video') {
|
||||
doc.supportsStreaming = true;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { $rootScope } from "../utils";
|
||||
import $rootScope from "../rootScope";
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
import { deferredPromise, CancellablePromise } from "../../helpers/cancellablePromise";
|
||||
import type { DownloadOptions } from "../mtproto/apiFileManager";
|
||||
|
@ -1,6 +1,6 @@
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { $rootScope, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, findUpTag, langPack, whichChild, cancelEvent, getObjectKeysAndSort } from "../utils";
|
||||
import { numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, findUpTag, langPack, whichChild, cancelEvent, getObjectKeysAndSort } from "../utils";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import appMessagesManager, { Dialog } from "./appMessagesManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
@ -27,7 +27,6 @@ import appStickersManager from './appStickersManager';
|
||||
import AvatarElement from '../../components/avatar';
|
||||
import appInlineBotsManager from './AppInlineBotsManager';
|
||||
import StickyIntersector from '../../components/stickyIntersector';
|
||||
import { touchSupport } from '../config';
|
||||
import animationIntersector from '../../components/animationIntersector';
|
||||
import PopupStickers from '../../components/popupStickers';
|
||||
import PopupDatePicker from '../../components/popupDatepicker';
|
||||
@ -42,6 +41,9 @@ import { ChatSearch } from '../../components/chat/search';
|
||||
import mediaSizes from '../../helpers/mediaSizes';
|
||||
import { isAndroid, isApple, isSafari } from '../../helpers/userAgent';
|
||||
import { MOUNT_CLASS_TO } from '../mtproto/mtproto_config';
|
||||
import $rootScope from '../rootScope';
|
||||
import { isTouchSupported } from '../../helpers/touchSupport';
|
||||
import apiUpdatesManager from './apiUpdatesManager';
|
||||
|
||||
//console.log('appImManager included33!');
|
||||
|
||||
@ -76,7 +78,6 @@ export class AppImManager {
|
||||
delete: HTMLButtonElement
|
||||
} = {} as any;
|
||||
|
||||
public myID = 0;
|
||||
public peerID = 0;
|
||||
|
||||
public bubbles: {[mid: string]: HTMLDivElement} = {};
|
||||
@ -146,7 +147,13 @@ export class AppImManager {
|
||||
private closeBtn = this.topbar.querySelector('.sidebar-close-button') as HTMLButtonElement;
|
||||
public hideRightSidebar = false;
|
||||
|
||||
get myID() {
|
||||
return $rootScope.myID;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
apiUpdatesManager.attach();
|
||||
|
||||
this.log = logger('IM', LogLevels.log | LogLevels.warn | LogLevels.debug | LogLevels.error);
|
||||
this.chatInputC = new ChatInput();
|
||||
this.preloader = new ProgressivePreloader(null, false);
|
||||
@ -160,15 +167,6 @@ export class AppImManager {
|
||||
this.chatAudio = new ChatAudio();
|
||||
this.chatInfo.nextElementSibling.prepend(this.chatAudio.container);
|
||||
|
||||
apiManager.getUserID().then((id) => {
|
||||
this.myID = $rootScope.myID = id;
|
||||
});
|
||||
|
||||
$rootScope.$on('user_auth', (e) => {
|
||||
let userAuth = e.detail;
|
||||
this.myID = $rootScope.myID = userAuth ? userAuth.id : 0;
|
||||
});
|
||||
|
||||
// will call when message is sent (only 1)
|
||||
$rootScope.$on('history_append', (e) => {
|
||||
let details = e.detail;
|
||||
@ -619,7 +617,7 @@ export class AppImManager {
|
||||
this.chatInputC.attachMediaPopUp.captionInput.focus();
|
||||
}
|
||||
|
||||
if(e.key == 'Enter' && !touchSupport) {
|
||||
if(e.key == 'Enter' && !isTouchSupported) {
|
||||
this.chatInputC.attachMediaPopUp.sendBtn.click();
|
||||
} else if(e.key == 'Escape') {
|
||||
this.chatInputC.attachMediaPopUp.container.classList.remove('active');
|
||||
@ -836,7 +834,7 @@ export class AppImManager {
|
||||
this.onScrollRAF = window.requestAnimationFrame(() => {
|
||||
//lottieLoader.checkAnimations(false, 'chat');
|
||||
|
||||
if(!touchSupport) {
|
||||
if(!isTouchSupported) {
|
||||
if(this.isScrollingTimeout) {
|
||||
clearTimeout(this.isScrollingTimeout);
|
||||
} else if(!this.chatInner.classList.contains('is-scrolling')) {
|
||||
@ -885,7 +883,7 @@ export class AppImManager {
|
||||
this.scroll.addEventListener('scroll', this.onScroll.bind(this));
|
||||
this.scroll.parentElement.classList.add('scrolled-down');
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
this.scroll.addEventListener('touchmove', () => {
|
||||
if(this.isScrollingTimeout) {
|
||||
clearTimeout(this.isScrollingTimeout);
|
||||
@ -2395,10 +2393,10 @@ export class AppImManager {
|
||||
//this.log('performHistoryResult: will set scrollTop', this.scrollable.scrollHeight, newScrollTop, this.scrollable.container.clientHeight);
|
||||
|
||||
// touchSupport for safari iOS
|
||||
touchSupport && isApple && (this.scrollable.container.style.overflow = 'hidden');
|
||||
isTouchSupported && isApple && (this.scrollable.container.style.overflow = 'hidden');
|
||||
this.scrollable.scrollTop = newScrollTop;
|
||||
//this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||
touchSupport && isApple && (this.scrollable.container.style.overflow = '');
|
||||
isTouchSupported && isApple && (this.scrollable.container.style.overflow = '');
|
||||
|
||||
//this.log('performHistoryResult: have set up scrollTop:', newScrollTop, this.scrollable.scrollTop);
|
||||
}
|
||||
|
@ -4,18 +4,19 @@ import appMessagesManager from "./appMessagesManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { logger } from "../logger";
|
||||
import ProgressivePreloader from "../../components/preloader";
|
||||
import { findUpClassName, $rootScope, generatePathData, fillPropertyValue, cancelEvent } from "../utils";
|
||||
import { findUpClassName, generatePathData, fillPropertyValue, cancelEvent } from "../utils";
|
||||
import appDocsManager, {MyDocument} from "./appDocsManager";
|
||||
import VideoPlayer from "../mediaPlayer";
|
||||
import { renderImageFromUrl, parseMenuButtonsTo } from "../../components/misc";
|
||||
import AvatarElement from "../../components/avatar";
|
||||
import { LazyLoadQueueBase } from "../../components/lazyLoadQueue";
|
||||
import { touchSupport } from "../config";
|
||||
import appMediaPlaybackController from "../../components/appMediaPlaybackController";
|
||||
import { deferredPromise } from "../../helpers/cancellablePromise";
|
||||
import mediaSizes from "../../helpers/mediaSizes";
|
||||
import { isSafari } from "../../helpers/userAgent";
|
||||
import appSidebarRight, { AppSidebarRight } from "./appSidebarRight";
|
||||
import $rootScope from "../rootScope";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
|
||||
// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию
|
||||
// TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода)
|
||||
@ -211,7 +212,7 @@ export class AppMediaViewer {
|
||||
//this.content.mover.append(this.buttons.prev, this.buttons.next);
|
||||
this.setNewMover();
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
const swipeHandler = new SwipeHandler(this.wholeDiv, (xDiff, yDiff) => {
|
||||
if(VideoPlayer.isFullScreen()) {
|
||||
return;
|
||||
@ -266,7 +267,7 @@ export class AppMediaViewer {
|
||||
if(target.tagName == 'A') return;
|
||||
cancelEvent(e);
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
if(this.highlightSwitchersTimeout) {
|
||||
clearTimeout(this.highlightSwitchersTimeout);
|
||||
} else {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { $rootScope, copy, tsNow, safeReplaceObject, listMergeSorted, deepEqual, langPack } from "../utils";
|
||||
import { copy, tsNow, safeReplaceObject, listMergeSorted, deepEqual, langPack } from "../utils";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { nextRandomInt, bigint } from "../bin_utils";
|
||||
import { telegramMeWebService } from "../mtproto/mtproto";
|
||||
//import { telegramMeWebService } from "../mtproto/mtproto";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appPhotosManager, { MyPhoto } from "./appPhotosManager";
|
||||
|
||||
@ -26,6 +26,8 @@ import type {ApiFileManager} from '../mtproto/apiFileManager';
|
||||
import appDownloadManager from "./appDownloadManager";
|
||||
import { DialogFilter, Message, InputMessage, MethodDeclMap, MessagesFilter, PhotoSize, DocumentAttribute, Dialog as MTDialog, MessagesDialogs, MessagesPeerDialogs, MessagesMessages, MessageMedia } from "../../layer";
|
||||
import referenceDatabase, { ReferenceContext } from "../mtproto/referenceDatabase";
|
||||
import $rootScope from "../rootScope";
|
||||
import appStateManager from "./appStateManager";
|
||||
|
||||
//console.trace('include');
|
||||
// TODO: если удалить сообщение в непрогруженном диалоге, то при обновлении, из-за стейта, последнего сообщения в чатлисте не будет
|
||||
@ -461,6 +463,17 @@ export class FiltersStorage {
|
||||
}
|
||||
|
||||
type MyMessage = Message.message | Message.messageService;
|
||||
type MyInputMessagesFilter = 'inputMessagesFilterEmpty'
|
||||
| 'inputMessagesFilterPhotos'
|
||||
| 'inputMessagesFilterPhotoVideo'
|
||||
| 'inputMessagesFilterVideo'
|
||||
| 'inputMessagesFilterDocument'
|
||||
| 'inputMessagesFilterVoice'
|
||||
| 'inputMessagesFilterRoundVoice'
|
||||
| 'inputMessagesFilterRoundVideo'
|
||||
| 'inputMessagesFilterMusic'
|
||||
| 'inputMessagesFilterUrl'
|
||||
| 'inputMessagesFilterMyMentions';
|
||||
|
||||
export class AppMessagesManager {
|
||||
public messagesStorage: {[mid: string]: any} = {};
|
||||
@ -567,6 +580,91 @@ export class AppMessagesManager {
|
||||
});
|
||||
}
|
||||
}); */
|
||||
|
||||
appStateManager.addListener('save', () => {
|
||||
const messages: any[] = [];
|
||||
const dialogs: Dialog[] = [];
|
||||
|
||||
for(const folderID in this.dialogsStorage.byFolders) {
|
||||
const folder = this.dialogsStorage.getFolder(+folderID);
|
||||
|
||||
for(let dialog of folder) {
|
||||
const historyStorage = this.historiesStorage[dialog.peerID];
|
||||
const history = [].concat(historyStorage?.pending ?? [], historyStorage?.history ?? []);
|
||||
|
||||
dialog = copy(dialog);
|
||||
let removeUnread = 0;
|
||||
for(const mid of history) {
|
||||
const message = this.getMessage(mid);
|
||||
if(/* message._ != 'messageEmpty' && */message.id > 0) {
|
||||
messages.push(message);
|
||||
|
||||
if(message.fromID != dialog.peerID) {
|
||||
appStateManager.setPeer(message.fromID, appPeersManager.getPeer(message.fromID));
|
||||
}
|
||||
|
||||
dialog.top_message = message.mid;
|
||||
|
||||
break;
|
||||
} else if(message.pFlags && message.pFlags.unread) {
|
||||
++removeUnread;
|
||||
}
|
||||
}
|
||||
|
||||
if(removeUnread && dialog.unread_count) dialog.unread_count -= removeUnread;
|
||||
|
||||
dialogs.push(dialog);
|
||||
|
||||
appStateManager.setPeer(dialog.peerID, appPeersManager.getPeer(dialog.peerID));
|
||||
}
|
||||
}
|
||||
|
||||
appStateManager.pushToState('dialogs', dialogs);
|
||||
appStateManager.pushToState('messages', messages);
|
||||
appStateManager.pushToState('filters', this.filtersStorage.filters);
|
||||
appStateManager.pushToState('allDialogsLoaded', this.dialogsStorage.allDialogsLoaded);
|
||||
appStateManager.pushToState('maxSeenMsgID', this.maxSeenID);
|
||||
});
|
||||
|
||||
appStateManager.getState().then(state => {
|
||||
if(state.maxSeenMsgID && !appMessagesIDsManager.getMessageIDInfo(state.maxSeenMsgID)[1]) {
|
||||
this.maxSeenID = state.maxSeenMsgID;
|
||||
}
|
||||
|
||||
const messages = state.messages;
|
||||
if(messages) {
|
||||
/* let tempID = this.tempID;
|
||||
|
||||
for(let message of messages) {
|
||||
if(message.id < tempID) {
|
||||
tempID = message.id;
|
||||
}
|
||||
}
|
||||
|
||||
if(tempID != this.tempID) {
|
||||
this.log('Set tempID to:', tempID);
|
||||
this.tempID = tempID;
|
||||
} */
|
||||
|
||||
this.saveMessages(messages);
|
||||
}
|
||||
|
||||
if(state.allDialogsLoaded) {
|
||||
this.dialogsStorage.allDialogsLoaded = state.allDialogsLoaded;
|
||||
}
|
||||
|
||||
if(state.filters) {
|
||||
for(const filterID in state.filters) {
|
||||
this.filtersStorage.saveDialogFilter(state.filters[filterID], false);
|
||||
}
|
||||
}
|
||||
|
||||
if(state.dialogs) {
|
||||
state.dialogs.forEachReverse(dialog => {
|
||||
this.saveConversation(dialog);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -715,8 +813,8 @@ export class AppMessagesManager {
|
||||
message = {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
from_id: appPeersManager.getOutputPeer(fromID),
|
||||
peer_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: tsNow(true) + serverTimeManager.serverTimeOffset,
|
||||
@ -1071,8 +1169,8 @@ export class AppMessagesManager {
|
||||
const message: any = {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
from_id: appPeersManager.getOutputPeer(fromID),
|
||||
peer_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: date,
|
||||
@ -1349,9 +1447,9 @@ export class AppMessagesManager {
|
||||
let message = {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
from_id: appPeersManager.getOutputPeer(fromID),
|
||||
grouped_id: groupID,
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
peer_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: date,
|
||||
@ -1644,8 +1742,8 @@ export class AppMessagesManager {
|
||||
const message: any = {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
from_id: appPeersManager.getOutputPeer(fromID),
|
||||
peer_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: tsNow(true) + ServerTimeManager.serverTimeOffset,
|
||||
@ -1908,9 +2006,9 @@ export class AppMessagesManager {
|
||||
|
||||
//this.log.error('messages.getDialogs result:', dialogsResult.dialogs, {...dialogsResult.dialogs[0]});
|
||||
|
||||
if(!offsetDate) {
|
||||
/* if(!offsetDate) {
|
||||
telegramMeWebService.setAuthorized(true);
|
||||
}
|
||||
} */
|
||||
|
||||
appUsersManager.saveApiUsers(dialogsResult.users);
|
||||
appChatsManager.saveApiChats(dialogsResult.chats);
|
||||
@ -2038,14 +2136,15 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public getMessagePeer(message: any): number {
|
||||
var toID = message.to_id && appPeersManager.getPeerID(message.to_id) || 0;
|
||||
var toID = message.peer_id && appPeersManager.getPeerID(message.peer_id) || 0;
|
||||
|
||||
if(toID < 0) {
|
||||
return toID;
|
||||
/* if(toID < 0) {
|
||||
return toID;
|
||||
} else if(message.pFlags && message.pFlags.out || message.flags & 2) {
|
||||
return toID;
|
||||
}
|
||||
return message.from_id;
|
||||
return message.from_id; */
|
||||
}
|
||||
|
||||
public getDialogByPeerID(peerID: number): [Dialog, number] | [] {
|
||||
@ -2195,7 +2294,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
const peerID = this.getMessagePeer(apiMessage);
|
||||
const isChannel = apiMessage.to_id._ == 'peerChannel';
|
||||
const isChannel = apiMessage.peer_id._ == 'peerChannel';
|
||||
const channelID = isChannel ? -peerID : 0;
|
||||
const isBroadcast = isChannel && appChatsManager.isBroadcast(channelID);
|
||||
|
||||
@ -2223,12 +2322,18 @@ export class AppMessagesManager {
|
||||
|
||||
apiMessage.date -= serverTimeManager.serverTimeOffset;
|
||||
|
||||
const myID = appUsersManager.getSelf().id;
|
||||
|
||||
apiMessage.peerID = peerID;
|
||||
apiMessage.fromID = apiMessage.pFlags.post ? peerID : apiMessage.from_id;
|
||||
if(apiMessage.peerID == myID && !apiMessage.from_id && !apiMessage.fwd_from) {
|
||||
apiMessage.fromID = myID;
|
||||
} else {
|
||||
apiMessage.fromID = apiMessage.pFlags.post || peerID == myID ? peerID : appPeersManager.getPeerID(apiMessage.from_id);
|
||||
}
|
||||
|
||||
const fwdHeader = apiMessage.fwd_from;
|
||||
if(fwdHeader) {
|
||||
if(peerID == appUsersManager.getSelf().id) {
|
||||
if(peerID == myID) {
|
||||
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
|
||||
const savedFromPeerID = appPeersManager.getPeerID(fwdHeader.saved_from_peer);
|
||||
const savedFromMid = appMessagesIDsManager.getFullMessageID(fwdHeader.saved_from_msg_id,
|
||||
@ -2236,12 +2341,12 @@ export class AppMessagesManager {
|
||||
apiMessage.savedFrom = savedFromPeerID + '_' + savedFromMid;
|
||||
}
|
||||
|
||||
apiMessage.fromID = fwdHeader.channel_id ? -fwdHeader.channel_id : fwdHeader.from_id;
|
||||
apiMessage.fromID = fwdHeader.channel_id ? -fwdHeader.channel_id : appPeersManager.getPeerID(fwdHeader.from_id);
|
||||
} else {
|
||||
apiMessage.fwdPostID = fwdHeader.channel_post;
|
||||
}
|
||||
|
||||
apiMessage.fwdFromID = fwdHeader.channel_id ? -fwdHeader.channel_id : fwdHeader.from_id;
|
||||
apiMessage.fwdFromID = fwdHeader.channel_id ? -fwdHeader.channel_id : appPeersManager.getPeerID(fwdHeader.from_id);
|
||||
|
||||
fwdHeader.date -= serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
@ -2718,8 +2823,8 @@ export class AppMessagesManager {
|
||||
_: 'message',
|
||||
id: mid,
|
||||
mid: mid,
|
||||
from_id: appUsersManager.getSelf().id,
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
from_id: appPeersManager.getOutputPeer(appUsersManager.getSelf().id),
|
||||
peer_id: appPeersManager.getOutputPeer(peerID),
|
||||
deleted: true,
|
||||
flags: 0,
|
||||
pFlags: {unread: false, out: true},
|
||||
@ -2817,7 +2922,7 @@ export class AppMessagesManager {
|
||||
mid: message.mid
|
||||
}, messageReplyMarkup);
|
||||
if(messageReplyMarkup._ != 'replyKeyboardHide') {
|
||||
messageReplyMarkup.fromID = message.from_id;
|
||||
messageReplyMarkup.fromID = appPeersManager.getPeerID(message.from_id);
|
||||
}
|
||||
historyStorage.reply_markup = messageReplyMarkup;
|
||||
// this.log('set', historyStorage.reply_markup)
|
||||
@ -2861,8 +2966,8 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public getSearch(peerID = 0, query: string = '', inputFilter: {
|
||||
_?: string
|
||||
} = {_: 'inputMessagesFilterEmpty'}, maxID: number, limit: number, offsetRate = 0, backLimit = 0): Promise<{
|
||||
_?: MyInputMessagesFilter
|
||||
} = {_: 'inputMessagesFilterEmpty'}, maxID: number, limit = 20, offsetRate = 0, backLimit = 0): Promise<{
|
||||
count: number,
|
||||
next_rate: number,
|
||||
history: number[]
|
||||
@ -2886,10 +2991,9 @@ export class AppMessagesManager {
|
||||
|
||||
if(historyStorage !== undefined && historyStorage.history.length) {
|
||||
var neededContents: {
|
||||
[type: string]: boolean
|
||||
[messageMediaType: string]: boolean
|
||||
} = {},
|
||||
neededDocTypes: string[] = [];
|
||||
var neededLimit = limit || 20;
|
||||
var message;
|
||||
|
||||
switch(inputFilter._) {
|
||||
@ -2958,7 +3062,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
foundMsgs.push(message.mid);
|
||||
if(foundMsgs.length >= neededLimit) {
|
||||
if(foundMsgs.length >= limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2966,12 +3070,12 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
// this.log.warn(dT(), 'before append', foundMsgs)
|
||||
if(foundMsgs.length < neededLimit && this.lastSearchResults.length && sameSearchCache) {
|
||||
if(foundMsgs.length < limit && this.lastSearchResults.length && sameSearchCache) {
|
||||
var minID = foundMsgs.length ? foundMsgs[foundMsgs.length - 1] : false;
|
||||
for(let i = 0; i < this.lastSearchResults.length; i++) {
|
||||
if(minID === false || this.lastSearchResults[i] < minID) {
|
||||
foundMsgs.push(this.lastSearchResults[i]);
|
||||
if(foundMsgs.length >= neededLimit) {
|
||||
if(foundMsgs.length >= limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2980,7 +3084,7 @@ export class AppMessagesManager {
|
||||
// this.log.warn(dT(), 'after append', foundMsgs)
|
||||
}
|
||||
|
||||
if(foundMsgs.length || limit == 1000) {
|
||||
if(foundMsgs.length) {
|
||||
if(useSearchCache) {
|
||||
this.lastSearchResults = listMergeSorted(this.lastSearchResults, foundMsgs)
|
||||
}
|
||||
@ -3001,7 +3105,7 @@ export class AppMessagesManager {
|
||||
filter: (inputFilter || {_: 'inputMessagesFilterEmpty'}) as any as MessagesFilter,
|
||||
min_date: 0,
|
||||
max_date: 0,
|
||||
limit: limit,
|
||||
limit,
|
||||
offset_id: appMessagesIDsManager.getMessageLocalID(maxID) || 0,
|
||||
add_offset: backLimit ? -backLimit : 0,
|
||||
max_id: 0,
|
||||
@ -3026,10 +3130,13 @@ export class AppMessagesManager {
|
||||
apiPromise = apiManager.invokeApi('messages.searchGlobal', {
|
||||
flags: 0,
|
||||
q: query,
|
||||
filter: (inputFilter || {_: 'inputMessagesFilterEmpty'}) as any as MessagesFilter,
|
||||
min_date: 0,
|
||||
max_date: 0,
|
||||
offset_rate: offsetRate,
|
||||
offset_peer: appPeersManager.getInputPeerByID(offsetPeerID),
|
||||
offset_id: appMessagesIDsManager.getMessageLocalID(offsetID),
|
||||
limit: limit || 20
|
||||
limit
|
||||
}, {
|
||||
//timeout: APITIMEOUT,
|
||||
noErrorBox: true
|
||||
@ -3068,12 +3175,6 @@ export class AppMessagesManager {
|
||||
next_rate: searchResult.next_rate,
|
||||
history: foundMsgs
|
||||
};
|
||||
}, (error) => {
|
||||
if(error.code == 400) {
|
||||
error.handled = true;
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
@ -3416,7 +3517,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
if(!message.pFlags.out && message.from_id) {
|
||||
appUsersManager.forceUserOnline(message.from_id);
|
||||
appUsersManager.forceUserOnline(appPeersManager.getPeerID(message.from_id));
|
||||
}
|
||||
|
||||
var randomID = this.pendingByMessageID[message.mid],
|
||||
@ -3617,7 +3718,7 @@ export class AppMessagesManager {
|
||||
case 'updateEditChannelMessage': {
|
||||
var message = update.message;
|
||||
var peerID = this.getMessagePeer(message);
|
||||
var channelID = message.to_id._ == 'peerChannel' ? -peerID : 0;
|
||||
var channelID = message.peer_id._ == 'peerChannel' ? -peerID : 0;
|
||||
var mid = appMessagesIDsManager.getFullMessageID(message.id, channelID);
|
||||
if(this.messagesStorage[mid] === undefined) {
|
||||
break;
|
||||
@ -3796,7 +3897,7 @@ export class AppMessagesManager {
|
||||
deleted: true,
|
||||
id: messageID,
|
||||
from_id: message.from_id,
|
||||
to_id: message.to_id,
|
||||
peer_id: message.peer_id,
|
||||
flags: message.flags,
|
||||
pFlags: message.pFlags,
|
||||
date: message.date
|
||||
@ -3928,8 +4029,8 @@ export class AppMessagesManager {
|
||||
var message: any = {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
from_id: appPeersManager.getOutputPeer(fromID),
|
||||
peer_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: 0,
|
||||
pFlags: {unread: true},
|
||||
date: (update.inbox_date || tsNow(true)) + serverTimeManager.serverTimeOffset,
|
||||
@ -4290,7 +4391,7 @@ export class AppMessagesManager {
|
||||
_: 'messageService',
|
||||
id: messageID,
|
||||
from_id: peerID,
|
||||
to_id: appPeersManager.getOutputPeer(peerID),
|
||||
peer_id: appPeersManager.getOutputPeer(peerID),
|
||||
flags: 0,
|
||||
pFlags: {},
|
||||
date: tsNow(true) + serverTimeManager.serverTimeOffset,
|
||||
|
@ -3,6 +3,7 @@ import appChatsManager from "./appChatsManager";
|
||||
import { isObject } from "../utils";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { InputPeer, InputDialogPeer, Peer } from "../../layer";
|
||||
import appStateManager from "./appStateManager";
|
||||
|
||||
// https://github.com/eelcohn/Telegram-API/wiki/Calculating-color-for-a-Telegram-user-on-IRC
|
||||
/*
|
||||
@ -21,6 +22,20 @@ const DialogColors = ['#e17076', '#7bc862', '#e5ca77', '#65AADD', '#a695e7', '#e
|
||||
const DialogColorsMap = [0, 7, 4, 1, 6, 3, 5];
|
||||
|
||||
export class AppPeersManager {
|
||||
constructor() {
|
||||
appStateManager.getState().then((state) => {
|
||||
for(let peerID in state.peers) {
|
||||
let peer = state.peers[peerID];
|
||||
this.savePeerInstance(+peerID, peer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public savePeerInstance(peerID: number, instance: any) {
|
||||
if(+peerID < 0) appChatsManager.saveApiChat(instance);
|
||||
else appUsersManager.saveApiUser(instance);
|
||||
}
|
||||
|
||||
public getPeerPhoto(peerID: number) {
|
||||
return peerID > 0
|
||||
? appUsersManager.getUserPhoto(peerID)
|
||||
|
@ -3,7 +3,7 @@ import appMessagesManager from './appMessagesManager';
|
||||
import appPeersManager from './appPeersManager';
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import { $rootScope } from "../utils";
|
||||
import $rootScope from "../rootScope";
|
||||
import { logger, LogLevels } from "../logger";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
|
@ -1,12 +1,11 @@
|
||||
//import { logger } from "../polyfill";
|
||||
import appDialogsManager, { AppArchivedTab, archivedTab } from "./appDialogsManager";
|
||||
import { $rootScope, findUpTag, findUpClassName, formatNumber } from "../utils";
|
||||
import { findUpTag, findUpClassName, formatNumber } from "../utils";
|
||||
import appImManager from "./appImManager";
|
||||
import AppSearch, { SearchGroup } from "../../components/appSearch";
|
||||
import { parseMenuButtonsTo } from "../../components/misc";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import Scrollable, { ScrollableX } from "../../components/scrollable_new";
|
||||
import appPeersManager from "../appManagers/appPeersManager";
|
||||
import { ScrollableX } from "../../components/scrollable_new";
|
||||
import AvatarElement from "../../components/avatar";
|
||||
import AppNewChannelTab from "../../components/sidebarLeft/newChannel";
|
||||
import AppAddMembersTab from "../../components/sidebarLeft/addMembers";
|
||||
@ -22,6 +21,8 @@ import SearchInput from "../../components/searchInput";
|
||||
import appStateManager from "./appStateManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
import $rootScope from "../rootScope";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
|
||||
AvatarElement;
|
||||
|
||||
@ -167,7 +168,7 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||
this.renderRecentSearch();
|
||||
appStateManager.pushToState('recentSearch', this.recentSearch);
|
||||
for(const peerID of this.recentSearch) {
|
||||
appStateManager.pushPeer(peerID);
|
||||
appStateManager.setPeer(peerID, appPeersManager.getPeer(peerID));
|
||||
}
|
||||
|
||||
clearRecentSearchBtn.style.display = '';
|
||||
|
@ -1,14 +1,11 @@
|
||||
import AppStorage from '../storage';
|
||||
import appMessagesManager, { Dialog, DialogsStorage, FiltersStorage } from './appMessagesManager';
|
||||
import appMessagesIDsManager from './appMessagesIDsManager';
|
||||
import appPeersManager from './appPeersManager';
|
||||
import appChatsManager from './appChatsManager';
|
||||
import appUsersManager from './appUsersManager';
|
||||
import apiUpdatesManager from './apiUpdatesManager';
|
||||
import { $rootScope, copy } from '../utils';
|
||||
import { logger } from '../logger';
|
||||
import type { Dialog, DialogsStorage, FiltersStorage } from './appMessagesManager';
|
||||
import type { AppStickersManager } from './appStickersManager';
|
||||
import type { AppPeersManager } from './appPeersManager';
|
||||
import { App, MOUNT_CLASS_TO } from '../mtproto/mtproto_config';
|
||||
import EventListenerBase from '../../helpers/eventListenerBase';
|
||||
import $rootScope from '../rootScope';
|
||||
import AppStorage from '../storage';
|
||||
import { logger } from '../logger';
|
||||
|
||||
const REFRESH_EVERY = 24 * 60 * 60 * 1000; // 1 day
|
||||
const STATE_VERSION = App.version;
|
||||
@ -16,7 +13,7 @@ const STATE_VERSION = App.version;
|
||||
type State = Partial<{
|
||||
dialogs: Dialog[],
|
||||
allDialogsLoaded: DialogsStorage['allDialogsLoaded'],
|
||||
peers: {[peerID: string]: any},
|
||||
peers: {[peerID: string]: ReturnType<AppPeersManager['getPeer']>},
|
||||
messages: any[],
|
||||
contactsList: number[],
|
||||
updates: any,
|
||||
@ -33,22 +30,22 @@ type State = Partial<{
|
||||
const REFRESH_KEYS = ['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', 'stateCreatedTime',
|
||||
'updates', 'maxSeenMsgID', 'filters', 'topPeers'] as any as Array<keyof State>;
|
||||
|
||||
export class AppStateManager {
|
||||
export class AppStateManager extends EventListenerBase<{
|
||||
save: (state: State) => void
|
||||
}> {
|
||||
public loaded: Promise<State>;
|
||||
private log = logger('STATE'/* , LogLevels.error */);
|
||||
|
||||
private state: State;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.loadSavedState();
|
||||
|
||||
$rootScope.$on('user_auth', (e) => {
|
||||
apiUpdatesManager.attach(null);
|
||||
});
|
||||
}
|
||||
|
||||
public loadSavedState() {
|
||||
if(this.loaded) return this.loaded;
|
||||
console.time('load state');
|
||||
return this.loaded = new Promise((resolve) => {
|
||||
AppStorage.get<[State, {id: number}]>('state', 'user_auth').then(([state, auth]) => {
|
||||
const time = Date.now();
|
||||
@ -65,77 +62,26 @@ export class AppStateManager {
|
||||
}
|
||||
|
||||
// will not throw error because state can be `FALSE`
|
||||
const {dialogs, allDialogsLoaded, peers, messages, contactsList, maxSeenMsgID, updates, filters} = state;
|
||||
const {peers, updates} = state;
|
||||
|
||||
this.state = state || {};
|
||||
this.state.peers = peers || {};
|
||||
this.state.version = STATE_VERSION;
|
||||
|
||||
|
||||
// ??= doesn't compiles
|
||||
if(!this.state.hasOwnProperty('stateCreatedTime')) {
|
||||
this.state.stateCreatedTime = Date.now();
|
||||
}
|
||||
|
||||
this.log('state res', dialogs, messages);
|
||||
|
||||
if(maxSeenMsgID && !appMessagesIDsManager.getMessageIDInfo(maxSeenMsgID)[1]) {
|
||||
appMessagesManager.maxSeenID = maxSeenMsgID;
|
||||
}
|
||||
|
||||
this.log('state res', state);
|
||||
|
||||
//return resolve();
|
||||
|
||||
if(peers) {
|
||||
for(let peerID in peers) {
|
||||
let peer = peers[peerID];
|
||||
if(+peerID < 0) appChatsManager.saveApiChat(peer);
|
||||
else appUsersManager.saveApiUser(peer);
|
||||
}
|
||||
}
|
||||
|
||||
if(contactsList && Array.isArray(contactsList) && contactsList.length) {
|
||||
contactsList.forEach(userID => {
|
||||
appUsersManager.pushContact(userID);
|
||||
});
|
||||
appUsersManager.contactsFillPromise = Promise.resolve(appUsersManager.contactsList);
|
||||
}
|
||||
|
||||
if(messages) {
|
||||
/* let tempID = this.tempID;
|
||||
|
||||
for(let message of messages) {
|
||||
if(message.id < tempID) {
|
||||
tempID = message.id;
|
||||
}
|
||||
}
|
||||
|
||||
if(tempID != this.tempID) {
|
||||
this.log('Set tempID to:', tempID);
|
||||
this.tempID = tempID;
|
||||
} */
|
||||
|
||||
appMessagesManager.saveMessages(messages);
|
||||
if(auth?.id) {
|
||||
$rootScope.$broadcast('user_auth', {id: auth.id});
|
||||
}
|
||||
|
||||
if(allDialogsLoaded) {
|
||||
appMessagesManager.dialogsStorage.allDialogsLoaded = allDialogsLoaded;
|
||||
}
|
||||
|
||||
if(filters) {
|
||||
for(const filterID in filters) {
|
||||
appMessagesManager.filtersStorage.saveDialogFilter(filters[filterID], false);
|
||||
}
|
||||
}
|
||||
|
||||
if(dialogs) {
|
||||
dialogs.forEachReverse(dialog => {
|
||||
appMessagesManager.saveConversation(dialog);
|
||||
});
|
||||
}
|
||||
|
||||
if(auth?.id) {
|
||||
apiUpdatesManager.attach(updates ?? null);
|
||||
}
|
||||
|
||||
console.timeEnd('load state');
|
||||
resolve(state);
|
||||
}).catch(resolve).finally(() => {
|
||||
setInterval(() => this.saveState(), 10000);
|
||||
@ -150,74 +96,12 @@ export class AppStateManager {
|
||||
public saveState() {
|
||||
if(this.state === undefined) return;
|
||||
|
||||
const messages: any[] = [];
|
||||
const dialogs: Dialog[] = [];
|
||||
const peers = this.state.peers;
|
||||
|
||||
for(const folderID in appMessagesManager.dialogsStorage.byFolders) {
|
||||
const folder = appMessagesManager.dialogsStorage.getFolder(+folderID);
|
||||
this.setListenerResult('save', this.state);
|
||||
|
||||
for(let dialog of folder) {
|
||||
const historyStorage = appMessagesManager.historiesStorage[dialog.peerID];
|
||||
const history = [].concat(historyStorage?.pending ?? [], historyStorage?.history ?? []);
|
||||
|
||||
dialog = copy(dialog);
|
||||
let removeUnread = 0;
|
||||
for(const mid of history) {
|
||||
const message = appMessagesManager.getMessage(mid);
|
||||
if(/* message._ != 'messageEmpty' && */message.id > 0) {
|
||||
messages.push(message);
|
||||
|
||||
if(message.fromID != dialog.peerID) {
|
||||
peers[message.fromID] = appPeersManager.getPeer(message.fromID);
|
||||
}
|
||||
|
||||
dialog.top_message = message.mid;
|
||||
|
||||
break;
|
||||
} else if(message.pFlags && message.pFlags.unread) {
|
||||
++removeUnread;
|
||||
}
|
||||
}
|
||||
|
||||
if(removeUnread && dialog.unread_count) dialog.unread_count -= removeUnread;
|
||||
|
||||
dialogs.push(dialog);
|
||||
|
||||
peers[dialog.peerID] = appPeersManager.getPeer(dialog.peerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const us = apiUpdatesManager.updatesState;
|
||||
const updates = {
|
||||
seq: us.seq,
|
||||
pts: us.pts,
|
||||
date: us.date
|
||||
};
|
||||
|
||||
const contactsList = [...appUsersManager.contactsList];
|
||||
for(const userID of contactsList) {
|
||||
if(!peers[userID]) {
|
||||
peers[userID] = appUsersManager.getUser(userID);
|
||||
}
|
||||
}
|
||||
|
||||
const filters = appMessagesManager.filtersStorage.filters;
|
||||
//const pinnedOrders = appMessagesManager.dialogsStorage.pinnedOrders;
|
||||
|
||||
AppStorage.set({
|
||||
state: Object.assign({}, this.state, {
|
||||
dialogs,
|
||||
messages,
|
||||
allDialogsLoaded: appMessagesManager.dialogsStorage.allDialogsLoaded,
|
||||
peers,
|
||||
contactsList,
|
||||
filters,
|
||||
//pinnedOrders,
|
||||
updates,
|
||||
maxSeenMsgID: appMessagesManager.maxSeenID
|
||||
})
|
||||
state: this.state
|
||||
});
|
||||
}
|
||||
|
||||
@ -225,8 +109,9 @@ export class AppStateManager {
|
||||
this.state[key] = value;
|
||||
}
|
||||
|
||||
public pushPeer(peerID: number) {
|
||||
this.state.peers[peerID] = appPeersManager.getPeer(peerID);
|
||||
public setPeer(peerID: number, peer: any) {
|
||||
if(this.state.peers.hasOwnProperty(peerID)) return;
|
||||
this.state.peers[peerID] = peer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import appDocsManager from './appDocsManager';
|
||||
import { $rootScope } from '../utils';
|
||||
import $rootScope from '../rootScope';
|
||||
import { StickerSet, InputStickerSet, StickerSetCovered, MessagesRecentStickers, Document, InputFileLocation, MessagesStickerSet, PhotoSize } from '../../layer';
|
||||
import { Modify } from '../../types';
|
||||
import appStateManager from './appStateManager';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { safeReplaceObject, isObject, tsNow, copy, $rootScope, getAbbreviation } from "../utils";
|
||||
import { safeReplaceObject, isObject, tsNow, getAbbreviation } from "../utils";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
@ -9,6 +9,7 @@ import searchIndexManager from "../searchIndexManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appStateManager from "./appStateManager";
|
||||
import { InputUser, User as MTUser } from "../../layer";
|
||||
import $rootScope from "../rootScope";
|
||||
|
||||
/* export type User = {
|
||||
_: 'user',
|
||||
@ -55,20 +56,10 @@ export class AppUsersManager {
|
||||
public contactsIndex = searchIndexManager.createIndex();
|
||||
public contactsFillPromise: Promise<Set<number>>;
|
||||
public contactsList: Set<number> = new Set();
|
||||
public myID: number;
|
||||
|
||||
public getPeersPromise: Promise<number[]>;
|
||||
|
||||
constructor() {
|
||||
apiManager.getUserID().then((id) => {
|
||||
this.myID = id;
|
||||
});
|
||||
|
||||
$rootScope.$on('user_auth', (e) => {
|
||||
let userAuth = e.detail;
|
||||
this.myID = userAuth ? userAuth.id : 0;
|
||||
});
|
||||
|
||||
setInterval(this.updateUsersStatuses.bind(this), 60000);
|
||||
|
||||
$rootScope.$on('stateSynchronized', this.updateUsersStatuses.bind(this));
|
||||
@ -123,6 +114,23 @@ export class AppUsersManager {
|
||||
break; */
|
||||
}
|
||||
});
|
||||
|
||||
appStateManager.addListener('save', () => {
|
||||
const contactsList = [...this.contactsList];
|
||||
for(const userID of contactsList) {
|
||||
appStateManager.setPeer(userID, this.getUser(userID));
|
||||
}
|
||||
});
|
||||
|
||||
appStateManager.getState().then((state) => {
|
||||
const contactsList = state.contactsList;
|
||||
if(contactsList && Array.isArray(contactsList) && contactsList.length) {
|
||||
contactsList.forEach(userID => {
|
||||
this.pushContact(userID);
|
||||
});
|
||||
this.contactsFillPromise = Promise.resolve(this.contactsList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public fillContacts() {
|
||||
@ -320,7 +328,7 @@ export class AppUsersManager {
|
||||
}
|
||||
|
||||
public getSelf() {
|
||||
return this.getUser(this.myID);
|
||||
return this.getUser($rootScope.myID);
|
||||
}
|
||||
|
||||
public getUserStatusString(userID: number) {
|
||||
@ -565,13 +573,9 @@ export class AppUsersManager {
|
||||
this.saveApiUsers(result.users);
|
||||
appChatsManager.saveApiChats(result.chats);
|
||||
|
||||
peerIDs = result.categories[0].peers.map((topPeer: {
|
||||
_: 'topPeer',
|
||||
peer: any,
|
||||
rating: number
|
||||
}) => {
|
||||
peerIDs = result.categories[0].peers.map((topPeer) => {
|
||||
const peerID = appPeersManager.getPeerID(topPeer.peer);
|
||||
appStateManager.pushPeer(peerID);
|
||||
appStateManager.setPeer(peerID, this.getUser(peerID));
|
||||
return peerID;
|
||||
});
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { $rootScope, safeReplaceObject } from "../utils";
|
||||
import { safeReplaceObject } from "../utils";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
import appDocsManager from "./appDocsManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { ReferenceContext } from "../mtproto/referenceDatabase";
|
||||
import $rootScope from "../rootScope";
|
||||
|
||||
class AppWebPagesManager {
|
||||
webpages: any = {};
|
||||
|
@ -1,11 +1,4 @@
|
||||
/*!
|
||||
* Webogram v0.7.0 - messaging web application for MTProto
|
||||
* https://github.com/zhukov/webogram
|
||||
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
|
||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import {str2bigInt, divInt_, int2bigInt, bigInt2str, bigInt2bytes} from '../vendor/leemon';
|
||||
//import {str2bigInt, divInt_, int2bigInt, bigInt2str, bigInt2bytes} from '../vendor/leemon';
|
||||
|
||||
// @ts-ignore
|
||||
import {BigInteger, SecureRandom} from 'jsbn';
|
||||
|
@ -47,6 +47,8 @@ class CacheStorageController {
|
||||
public getFile(fileName: string) {
|
||||
//return Promise.reject();
|
||||
|
||||
// const str = `get fileName: ${fileName}`;
|
||||
// console.time(str);
|
||||
return this.timeoutOperation(async(cache) => {
|
||||
const response = await cache.match('/' + fileName);
|
||||
|
||||
@ -55,7 +57,11 @@ class CacheStorageController {
|
||||
throw 'No response???';
|
||||
}
|
||||
|
||||
return response.blob();
|
||||
const promise = response.blob();
|
||||
// promise.then(() => {
|
||||
// console.timeEnd(str);
|
||||
// });
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
import { cancelEvent } from "./utils";
|
||||
import { touchSupport } from "./config";
|
||||
import appMediaPlaybackController from "../components/appMediaPlaybackController";
|
||||
import { isAppleMobile } from "../helpers/userAgent";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
|
||||
type SUPEREVENT = MouseEvent | TouchEvent;
|
||||
|
||||
@ -69,7 +69,7 @@ export class ProgressLine {
|
||||
this.container.addEventListener('mousedown', this.onMouseDown);
|
||||
this.container.addEventListener('mouseup', this.onMouseUp);
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
this.container.addEventListener('touchmove', this.onMouseMove);
|
||||
this.container.addEventListener('touchstart', this.onMouseDown);
|
||||
this.container.addEventListener('touchend', this.onMouseUp);
|
||||
@ -109,7 +109,7 @@ export class ProgressLine {
|
||||
this.container.removeEventListener('mousedown', this.onMouseDown);
|
||||
this.container.removeEventListener('mouseup', this.onMouseUp);
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
this.container.removeEventListener('touchmove', this.onMouseMove);
|
||||
this.container.removeEventListener('touchstart', this.onMouseDown);
|
||||
this.container.removeEventListener('touchend', this.onMouseUp);
|
||||
@ -402,13 +402,13 @@ export default class VideoPlayer {
|
||||
});
|
||||
|
||||
video.addEventListener('click', () => {
|
||||
if(!touchSupport) {
|
||||
if(!isTouchSupported) {
|
||||
this.togglePlay();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
let showControlsTimeout = 0;
|
||||
|
||||
const t = () => {
|
||||
@ -456,7 +456,7 @@ export default class VideoPlayer {
|
||||
});
|
||||
|
||||
video.addEventListener('dblclick', () => {
|
||||
if(touchSupport) {
|
||||
if(isTouchSupported) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,18 @@ import AppStorage from '../storage';
|
||||
import { MTPNetworker } from './networker';
|
||||
import { bytesFromHex, bytesToHex, isObject } from '../bin_utils';
|
||||
import networkerFactory from './networkerFactory';
|
||||
import { telegramMeWebService } from './mtproto';
|
||||
//import { telegramMeWebService } from './mtproto';
|
||||
import authorizer from './authorizer';
|
||||
import {App, Modes} from './mtproto_config';
|
||||
import dcConfigurator from './dcConfigurator';
|
||||
import HTTP from './transports/http';
|
||||
import { logger } from '../logger';
|
||||
|
||||
/// #if MTPROTO_HTTP
|
||||
import HTTP from './transports/http';
|
||||
/// #endif
|
||||
|
||||
/// #if !MTPROTO_WORKER
|
||||
import { $rootScope } from '../utils';
|
||||
import $rootScope from '../rootScope';
|
||||
import { InvokeApiOptions } from '../../types';
|
||||
/// #endif
|
||||
|
||||
@ -53,7 +56,7 @@ export class ApiManager {
|
||||
public telegramMeNotify(newValue: boolean) {
|
||||
if(this.telegramMeNotified !== newValue) {
|
||||
this.telegramMeNotified = newValue;
|
||||
telegramMeWebService.setAuthorized(this.telegramMeNotified);
|
||||
//telegramMeWebService.setAuthorized(this.telegramMeNotified);
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,8 +114,17 @@ export class ApiManager {
|
||||
|
||||
// mtpGetNetworker
|
||||
public async getNetworker(dcID: number, options: InvokeApiOptions): Promise<MTPNetworker> {
|
||||
const transport = dcConfigurator.chooseServer(dcID, true);
|
||||
|
||||
/// #if MTPROTO_HTTP
|
||||
// @ts-ignore
|
||||
const upload = (options.fileUpload || options.fileDownload)
|
||||
&& (dcConfigurator.chooseServer(dcID, true) instanceof HTTP || Modes.multipleConnections);
|
||||
&& (transport instanceof HTTP || Modes.multipleConnections);
|
||||
/// #else
|
||||
// @ts-ignore
|
||||
const upload = (options.fileUpload || options.fileDownload) && Modes.multipleConnections;
|
||||
/// #endif
|
||||
|
||||
const cache = upload ? this.cachedUploadNetworkers : this.cachedNetworkers;
|
||||
|
||||
if(!dcID) {
|
||||
@ -305,14 +317,6 @@ export class ApiManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// mtpGetUserID
|
||||
public getUserID(): Promise<number> {
|
||||
return AppStorage.get<any>('user_auth').then((auth) => {
|
||||
this.telegramMeNotify(auth && auth.id > 0 || false);
|
||||
return auth.id || 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApiManager();
|
||||
|
@ -1,9 +1,15 @@
|
||||
import Socket from './transports/websocket';
|
||||
import MTTransport from './transports/transport';
|
||||
import HTTP from './transports/http';
|
||||
import { Modes } from './mtproto_config';
|
||||
|
||||
type TransportTypes = 'websocket' | 'https' | 'http';
|
||||
/// #if !MTPROTO_HTTP
|
||||
import Socket from './transports/websocket';
|
||||
// @ts-ignore
|
||||
type TransportTypes = 'websocket';
|
||||
/// #else
|
||||
import HTTP from './transports/http';
|
||||
// @ts-ignore
|
||||
type TransportTypes = 'https' | 'http';
|
||||
/// #endif
|
||||
type Servers = {
|
||||
[transportType in TransportTypes]: {
|
||||
[dcID: number]: MTTransport[]
|
||||
@ -27,17 +33,30 @@ export class DcConfigurator {
|
||||
{id: 5, host: '149.154.171.5', port: 80}
|
||||
];
|
||||
|
||||
/// #if !MTPROTO_HTTP
|
||||
private chosenServers: Servers = {
|
||||
websocket: {},
|
||||
websocket: {}
|
||||
};
|
||||
|
||||
private chosenUploadServers: Servers = {
|
||||
websocket: {}
|
||||
};
|
||||
|
||||
/// #else
|
||||
// @ts-ignore
|
||||
private chosenServers: Servers = {
|
||||
// @ts-ignore
|
||||
https: {},
|
||||
http: {}
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
private chosenUploadServers: Servers = {
|
||||
websocket: {},
|
||||
// @ts-ignore
|
||||
https: {},
|
||||
http: {}
|
||||
};
|
||||
/// #endif
|
||||
|
||||
public chooseServer(dcID: number, upload?: boolean, transportType: TransportTypes = 'websocket') {
|
||||
const servers = upload && (transportType != 'websocket' || Modes.multipleConnections)
|
||||
@ -53,12 +72,16 @@ export class DcConfigurator {
|
||||
if(!transports.length || (upload && transports.length < 1)) {
|
||||
let transport: MTTransport;
|
||||
|
||||
if(transportType == 'websocket') {
|
||||
/// #if !MTPROTO_HTTP
|
||||
//if(transportType == 'websocket') {
|
||||
const subdomain = this.sslSubdomains[dcID - 1];
|
||||
const path = Modes.test ? 'apiws_test' : 'apiws';
|
||||
const chosenServer = 'wss://' + subdomain + '.web.telegram.org/' + path;
|
||||
transport = new Socket(dcID, chosenServer);
|
||||
} else if(Modes.ssl || !Modes.http || transportType == 'https') {
|
||||
//} else
|
||||
/// #else
|
||||
// @ts-ignore
|
||||
if(Modes.ssl || !Modes.http || transportType == 'https') {
|
||||
const subdomain = this.sslSubdomains[dcID - 1] + (upload ? '-1' : '');
|
||||
const path = Modes.test ? 'apiw_test1' : 'apiw1';
|
||||
const chosenServer = 'https://' + subdomain + '.web.telegram.org/' + path;
|
||||
@ -72,6 +95,7 @@ export class DcConfigurator {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// #endif
|
||||
|
||||
if(!transport) {
|
||||
console.error('No chosenServer!', dcID);
|
||||
|
@ -7,10 +7,10 @@ import AppStorage from '../storage';
|
||||
import cryptoWorker from "../crypto/cryptoworker";
|
||||
import networkerFactory from "./networkerFactory";
|
||||
import apiFileManager from './apiFileManager';
|
||||
import { logger, LogLevels } from '../logger';
|
||||
//import { logger, LogLevels } from '../logger';
|
||||
import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.service';
|
||||
|
||||
const log = logger('DW', LogLevels.error);
|
||||
//const log = logger('DW', LogLevels.error);
|
||||
|
||||
const ctx = self as any as DedicatedWorkerGlobalScope;
|
||||
|
||||
@ -62,7 +62,7 @@ ctx.addEventListener('message', async(e) => {
|
||||
const task = e.data;
|
||||
const taskID = task.taskID;
|
||||
|
||||
log.debug('got message:', taskID, task);
|
||||
//log.debug('got message:', taskID, task);
|
||||
|
||||
//debugger;
|
||||
|
||||
|
@ -1,3 +1,18 @@
|
||||
export type UserAuth = {
|
||||
dcID: number,
|
||||
id: number
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
IMPORTANT NOTICE
|
||||
================
|
||||
|
||||
Do not publish your Webogram fork with my app credentials (below), or your application may be blocked.
|
||||
You can get your own api_id, api_hash at https://my.telegram.org, see manual at https://core.telegram.org/api/obtaining_api_id.
|
||||
|
||||
*/
|
||||
|
||||
export const App = {
|
||||
id: 1025907,
|
||||
hash: '452b0359b988148995f22ff0f4229750',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {isObject, $rootScope} from '../utils';
|
||||
import {isObject} from '../utils';
|
||||
import AppStorage from '../storage';
|
||||
import CryptoWorkerMethods from '../crypto/crypto_methods';
|
||||
import { logger } from '../logger';
|
||||
@ -6,9 +6,9 @@ import webpWorkerController from '../webp/webpWorkerController';
|
||||
import MTProtoWorker from 'worker-loader!./mtproto.worker';
|
||||
import type { DownloadOptions } from './apiFileManager';
|
||||
import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.service';
|
||||
import { isServiceWorkerSupported } from '../config';
|
||||
import { MethodDeclMap } from '../../layer';
|
||||
import { MOUNT_CLASS_TO } from './mtproto_config';
|
||||
import $rootScope from '../rootScope';
|
||||
|
||||
type Task = {
|
||||
taskID: number,
|
||||
@ -45,7 +45,7 @@ class ApiManagerProxy extends CryptoWorkerMethods {
|
||||
}
|
||||
|
||||
private registerServiceWorker() {
|
||||
if(!isServiceWorkerSupported) return;
|
||||
if(!('serviceWorker' in navigator)) return;
|
||||
|
||||
navigator.serviceWorker.register('./sw.js', {scope: './'}).then(registration => {
|
||||
|
||||
@ -209,10 +209,6 @@ class ApiManagerProxy extends CryptoWorkerMethods {
|
||||
return this.performTaskWorker('getNetworker', dc_id);
|
||||
}
|
||||
|
||||
public getUserID(): Promise<number> {
|
||||
return this.performTaskWorker('getUserID');
|
||||
}
|
||||
|
||||
public logOut(): Promise<void> {
|
||||
return this.performTaskWorker('logOut');
|
||||
}
|
||||
|
@ -10,12 +10,17 @@ import Schema from './schema';
|
||||
import timeManager from './timeManager';
|
||||
import NetworkerFactory from './networkerFactory';
|
||||
import dcConfigurator from './dcConfigurator';
|
||||
import Socket from './transports/websocket';
|
||||
import HTTP from './transports/http';
|
||||
import { logger, LogLevels } from '../logger';
|
||||
import { Modes, App } from './mtproto_config';
|
||||
import { InvokeApiOptions } from '../../types';
|
||||
import { longToBytes } from '../crypto/crypto_utils';
|
||||
import MTTransport from './transports/transport';
|
||||
|
||||
/// #if MTPROTO_HTTP
|
||||
import type HTTP from './transports/http';
|
||||
/// #else
|
||||
import type Socket from './transports/websocket';
|
||||
/// #endif
|
||||
|
||||
//console.error('networker included!', new Error().stack);
|
||||
|
||||
@ -61,31 +66,29 @@ class MTPNetworker {
|
||||
private pendingResends: Array<string> = [];
|
||||
private connectionInited = false;
|
||||
|
||||
/// #if MTPROTO_HTTP
|
||||
//private longPollInt: number;
|
||||
private longPollPending = 0;
|
||||
private nextReqTimeout: number;
|
||||
private nextReq: number = 0;
|
||||
private checkConnectionTimeout: number;
|
||||
private checkConnectionPeriod = 0;
|
||||
private onOnlineCb = this.checkConnection.bind(this);
|
||||
private sleepAfter = 0;
|
||||
/// #endif
|
||||
|
||||
private seqNo: number = 0;
|
||||
private prevSessionID: Array<number> = [];
|
||||
private sessionID: Array<number> = [];
|
||||
|
||||
private sleepAfter = 0;
|
||||
|
||||
private offline = false;
|
||||
|
||||
private checkConnectionTimeout: number;
|
||||
private checkConnectionPeriod = 0;
|
||||
|
||||
private nextReqTimeout: number;
|
||||
private nextReq: number = 0;
|
||||
|
||||
private onOnlineCb = this.checkConnection.bind(this);
|
||||
|
||||
private lastResendReq: {
|
||||
req_msg_id: string,
|
||||
resend_msg_ids: Array<string>
|
||||
} | null = null;
|
||||
|
||||
private transport: Socket | HTTP;
|
||||
private transport: MTTransport;
|
||||
|
||||
private log: ReturnType<typeof logger>;
|
||||
|
||||
@ -113,12 +116,15 @@ class MTPNetworker {
|
||||
|
||||
this.transport = dcConfigurator.chooseServer(this.dcID, this.upload);
|
||||
|
||||
if(this.transport instanceof HTTP) {
|
||||
/// #if MTPROTO_HTTP
|
||||
//if(this.transport instanceof HTTP) {
|
||||
/* this.longPollInt = */setInterval(this.checkLongPoll.bind(this), 10000);
|
||||
this.checkLongPoll();
|
||||
} else {
|
||||
/// #else
|
||||
//} else {
|
||||
(this.transport as Socket).networker = this;
|
||||
}
|
||||
//}
|
||||
/// #endif
|
||||
}
|
||||
|
||||
public updateSession() {
|
||||
@ -126,7 +132,6 @@ class MTPNetworker {
|
||||
this.prevSessionID = this.sessionID;
|
||||
this.sessionID = new Array(8);
|
||||
this.sessionID = [...new Uint8Array(this.sessionID.length).randomize()];
|
||||
//MTProto.secureRandom.nextBytes(this.sessionID);
|
||||
}
|
||||
|
||||
public updateSentMessage(sentMessageID: any) {
|
||||
@ -278,6 +283,7 @@ class MTPNetworker {
|
||||
return this.pushMessage(message, options);
|
||||
}
|
||||
|
||||
/// #if MTPROTO_HTTP
|
||||
public checkLongPoll() {
|
||||
const isClean = this.cleanupSent();
|
||||
//this.log('Check lp', this.longPollPending, tsNow(), this.dcID, isClean, this);
|
||||
@ -321,6 +327,7 @@ class MTPNetworker {
|
||||
this.log('Long-poll failed', error);
|
||||
});
|
||||
}
|
||||
/// #endif
|
||||
|
||||
// тут можно сделать таймаут и выводить дисконнект
|
||||
public pushMessage(message: {
|
||||
@ -407,6 +414,7 @@ class MTPNetworker {
|
||||
});
|
||||
}
|
||||
|
||||
/// #if MTPROTO_HTTP
|
||||
public checkConnection(event: Event | string) {
|
||||
/* $rootScope.offlineConnecting = true */
|
||||
|
||||
@ -442,6 +450,7 @@ class MTPNetworker {
|
||||
}, 1000); */
|
||||
});
|
||||
}
|
||||
/// #endif
|
||||
|
||||
public toggleOffline(enabled: boolean) {
|
||||
// this.log('toggle ', enabled, this.dcID, this.iii)
|
||||
@ -453,11 +462,13 @@ class MTPNetworker {
|
||||
/* $rootScope.offline = enabled;
|
||||
$rootScope.offlineConnecting = false; */
|
||||
|
||||
if(!(this.transport instanceof HTTP)) {
|
||||
/// #if !MTPROTO_HTTP
|
||||
//if(!(this.transport instanceof HTTP)) {
|
||||
this.log('toggle ', enabled, this.dcID);
|
||||
return;
|
||||
}
|
||||
//}
|
||||
|
||||
/// #else
|
||||
if(this.offline) {
|
||||
clearTimeout(this.nextReqTimeout);
|
||||
this.nextReqTimeout = 0;
|
||||
@ -483,6 +494,7 @@ class MTPNetworker {
|
||||
clearTimeout(this.checkConnectionTimeout);
|
||||
this.checkConnectionTimeout = 0;
|
||||
}
|
||||
/// #endif
|
||||
}
|
||||
|
||||
public performScheduledRequest() {
|
||||
@ -582,7 +594,8 @@ class MTPNetworker {
|
||||
}
|
||||
}
|
||||
|
||||
if(hasApiCall && !hasHttpWait && this.transport instanceof HTTP) {
|
||||
/// #if MTPROTO_HTTP
|
||||
if(hasApiCall && !hasHttpWait/* && this.transport instanceof HTTP */) {
|
||||
var serializer = new TLSerialization({mtproto: true});
|
||||
serializer.storeMethod('http_wait', {
|
||||
max_delay: 500,
|
||||
@ -596,6 +609,7 @@ class MTPNetworker {
|
||||
body: serializer.getBytes()
|
||||
});
|
||||
}
|
||||
/// #endif
|
||||
|
||||
if(!messages.length) {
|
||||
// this.log('no scheduled messages')
|
||||
@ -653,56 +667,59 @@ class MTPNetworker {
|
||||
|
||||
let promise = this.sendEncryptedRequest(message);
|
||||
|
||||
if(!(this.transport instanceof HTTP)) {
|
||||
/// #if !MTPROTO_HTTP
|
||||
//if(!(this.transport instanceof HTTP)) {
|
||||
if(noResponseMsgs.length) this.log.error('noResponseMsgs length!', noResponseMsgs);
|
||||
} else promise.then((result) => {
|
||||
self.toggleOffline(false);
|
||||
// this.log('parse for', message)
|
||||
self.parseResponse(result).then((response) => {
|
||||
if(Modes.debug) {
|
||||
this.log('Server response', self.dcID, response);
|
||||
//} else {
|
||||
/// #else
|
||||
promise.then((result) => {
|
||||
self.toggleOffline(false);
|
||||
// this.log('parse for', message)
|
||||
self.parseResponse(result).then((response) => {
|
||||
if(Modes.debug) {
|
||||
this.log('Server response', self.dcID, response);
|
||||
}
|
||||
|
||||
self.processMessage(response.response, response.messageID, response.sessionID);
|
||||
|
||||
noResponseMsgs.forEach((msgID) => {
|
||||
if(self.sentMessages[msgID]) {
|
||||
var deferred = self.sentMessages[msgID].deferred;
|
||||
delete self.sentMessages[msgID];
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
self.checkLongPoll();
|
||||
|
||||
this.checkConnectionPeriod = Math.max(1.1, Math.sqrt(this.checkConnectionPeriod));
|
||||
});
|
||||
}, (error) => {
|
||||
this.log.error('Encrypted request failed', error, message);
|
||||
|
||||
if(message.container) {
|
||||
message.inner.forEach((msgID: string) => {
|
||||
self.pendingMessages[msgID] = 0;
|
||||
});
|
||||
|
||||
delete self.sentMessages[message.msg_id];
|
||||
} else {
|
||||
self.pendingMessages[message.msg_id] = 0;
|
||||
}
|
||||
|
||||
self.processMessage(response.response, response.messageID, response.sessionID);
|
||||
|
||||
|
||||
noResponseMsgs.forEach((msgID) => {
|
||||
if(self.sentMessages[msgID]) {
|
||||
var deferred = self.sentMessages[msgID].deferred;
|
||||
delete self.sentMessages[msgID];
|
||||
deferred.resolve();
|
||||
delete self.pendingMessages[msgID];
|
||||
deferred.reject();
|
||||
}
|
||||
});
|
||||
|
||||
if(self.transport instanceof HTTP) {
|
||||
self.checkLongPoll();
|
||||
|
||||
this.checkConnectionPeriod = Math.max(1.1, Math.sqrt(this.checkConnectionPeriod));
|
||||
}
|
||||
})
|
||||
|
||||
self.toggleOffline(true);
|
||||
});
|
||||
}, (error) => {
|
||||
this.log.error('Encrypted request failed', error, message);
|
||||
|
||||
if(message.container) {
|
||||
message.inner.forEach((msgID: string) => {
|
||||
self.pendingMessages[msgID] = 0;
|
||||
});
|
||||
|
||||
delete self.sentMessages[message.msg_id];
|
||||
} else {
|
||||
self.pendingMessages[message.msg_id] = 0;
|
||||
}
|
||||
|
||||
noResponseMsgs.forEach((msgID) => {
|
||||
if(self.sentMessages[msgID]) {
|
||||
var deferred = self.sentMessages[msgID].deferred;
|
||||
delete self.sentMessages[msgID];
|
||||
delete self.pendingMessages[msgID];
|
||||
deferred.reject();
|
||||
}
|
||||
})
|
||||
|
||||
self.toggleOffline(true);
|
||||
});
|
||||
//}
|
||||
/// #endif
|
||||
|
||||
if(lengthOverflow || singlesCount > 1) {
|
||||
this.scheduleRequest();
|
||||
@ -780,7 +797,9 @@ class MTPNetworker {
|
||||
};
|
||||
|
||||
let promise = this.transport.send(requestData);
|
||||
if(!(this.transport instanceof HTTP)) return promise;
|
||||
/// #if !MTPROTO_HTTP
|
||||
/* if(!(this.transport instanceof HTTP)) */ return promise;
|
||||
/// #else
|
||||
|
||||
return promise.then((result) => {
|
||||
if(!result || !result.byteLength) {
|
||||
@ -797,6 +816,7 @@ class MTPNetworker {
|
||||
}
|
||||
return Promise.reject(error);
|
||||
});
|
||||
/// #endif
|
||||
});
|
||||
}
|
||||
|
||||
@ -925,10 +945,9 @@ class MTPNetworker {
|
||||
}
|
||||
|
||||
public scheduleRequest(delay = 0) {
|
||||
if(!(this.transport instanceof HTTP)) { // if socket
|
||||
return this.performScheduledRequest();
|
||||
}
|
||||
|
||||
/// #if !MTPROTO_HTTP
|
||||
return this.performScheduledRequest();
|
||||
/// #else
|
||||
if(this.offline/* && this.transport instanceof HTTP */) {
|
||||
this.checkConnection('forced schedule');
|
||||
}
|
||||
@ -955,6 +974,7 @@ class MTPNetworker {
|
||||
}
|
||||
|
||||
this.nextReq = nextReq;
|
||||
/// #endif
|
||||
}
|
||||
|
||||
public ackMessage(msgID: string) {
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,10 +1,3 @@
|
||||
/*!
|
||||
* Webogram v0.7.0 - messaging web application for MTProto
|
||||
* https://github.com/zhukov/webogram
|
||||
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
|
||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import {bigint, bigStringInt, bytesToHex, isObject} from '../bin_utils';
|
||||
import Schema from './schema';
|
||||
|
||||
|
@ -30,8 +30,8 @@ Uint8Array.prototype.concat = function(...args: Array<Uint8Array | ArrayBuffer |
|
||||
}; */
|
||||
|
||||
Uint8Array.prototype.toJSON = function() {
|
||||
//return [...this];
|
||||
return {type: 'bytes', value: [...this]};
|
||||
return [...this];
|
||||
//return {type: 'bytes', value: [...this]};
|
||||
};
|
||||
|
||||
Array.prototype.forEachReverse = function<T>(callback: (value: T, index?: number, array?: Array<T>) => void) {
|
||||
@ -64,8 +64,8 @@ declare global {
|
||||
randomize: () => Uint8Array,
|
||||
concat: (...args: Array<Uint8Array | ArrayBuffer | number[]>) => Uint8Array,
|
||||
//toString: () => string,
|
||||
//toJSON: () => number[],
|
||||
toJSON: () => {type: 'bytes', value: number[]},
|
||||
toJSON: () => number[],
|
||||
//toJSON: () => {type: 'bytes', value: number[]},
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
|
92
src/lib/rootScope.ts
Normal file
92
src/lib/rootScope.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import type { StickerSet } from "../layer";
|
||||
import type { MyDocument } from "./appManagers/appDocsManager";
|
||||
import type { Poll, PollResults } from "./appManagers/appPollsManager";
|
||||
import type { AppMessagesManager, Dialog, MyDialogFilter } from "./appManagers/appMessagesManager";
|
||||
import { MOUNT_CLASS_TO } from "./mtproto/mtproto_config";
|
||||
|
||||
type BroadcastEvents = {
|
||||
'user_update': number,
|
||||
'user_auth': {dcID?: number, id: number},
|
||||
'peer_changed': number,
|
||||
|
||||
'filter_delete': MyDialogFilter,
|
||||
'filter_update': MyDialogFilter,
|
||||
|
||||
'dialog_draft': {peerID: number, draft: any, index: number},
|
||||
'dialog_unread': {peerID: number, count?: number},
|
||||
'dialog_flush': {peerID: number},
|
||||
'dialog_drop': {peerID: number, dialog?: Dialog},
|
||||
'dialog_migrate': {migrateFrom: number, migrateTo: number},
|
||||
'dialog_top': Dialog,
|
||||
'dialog_notify_settings': number,
|
||||
'dialogs_multiupdate': {[peerID: string]: Dialog},
|
||||
'dialogs_archived_unread': {count: number},
|
||||
|
||||
'history_append': {peerID: number, messageID: number, my?: boolean},
|
||||
'history_update': {peerID: number, mid: number},
|
||||
'history_reply_markup': {peerID: number},
|
||||
'history_multiappend': AppMessagesManager['newMessagesToHandle'],
|
||||
'history_delete': {peerID: number, msgs: {[mid: number]: true}},
|
||||
'history_forbidden': number,
|
||||
'history_reload': number,
|
||||
'history_request': void,
|
||||
|
||||
'message_edit': {peerID: number, id: number, mid: number, justMedia: boolean},
|
||||
'message_views': {mid: number, views: number},
|
||||
'message_sent': {tempID: number, mid: number},
|
||||
'messages_pending': void,
|
||||
'messages_read': void,
|
||||
'messages_downloaded': number[],
|
||||
|
||||
'stickers_installed': StickerSet.stickerSet,
|
||||
'stickers_deleted': StickerSet.stickerSet,
|
||||
|
||||
'audio_play': {doc: MyDocument, mid: number},
|
||||
'audio_pause': void,
|
||||
|
||||
//'contacts_update': any,
|
||||
'avatar_update': number,
|
||||
'chat_full_update': number,
|
||||
'peer_pinned_message': number,
|
||||
'poll_update': {poll: Poll, results: PollResults},
|
||||
'chat_update': number,
|
||||
'stateSynchronized': void,
|
||||
'channel_settings': {channelID: number},
|
||||
'webpage_updated': {id: string, msgs: number[]},
|
||||
|
||||
'apiUpdate': any,
|
||||
'download_progress': any,
|
||||
//'draft_updated': any,
|
||||
};
|
||||
|
||||
const $rootScope = {
|
||||
$broadcast: <T extends keyof BroadcastEvents>(name: T, detail?: BroadcastEvents[T]) => {
|
||||
/* if(name != 'user_update') {
|
||||
console.debug(dT(), 'Broadcasting ' + name + ' event, with args:', detail);
|
||||
} */
|
||||
|
||||
let myCustomEvent = new CustomEvent(name, {detail});
|
||||
document.dispatchEvent(myCustomEvent);
|
||||
},
|
||||
$on: <T extends keyof BroadcastEvents>(name: T, callback: (e: Omit<CustomEvent, 'detail'> & {detail: BroadcastEvents[T]}) => any) => {
|
||||
// @ts-ignore
|
||||
document.addEventListener(name, callback);
|
||||
},
|
||||
$off: <T extends keyof BroadcastEvents>(name: T, callback: (e: Omit<CustomEvent, 'detail'> & {detail: BroadcastEvents[T]}) => any) => {
|
||||
// @ts-ignore
|
||||
document.removeEventListener(name, callback);
|
||||
},
|
||||
|
||||
selectedPeerID: 0,
|
||||
myID: 0,
|
||||
idle: {
|
||||
isIDLE: false
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$on('user_auth', (e) => {
|
||||
$rootScope.myID = e.detail.id;
|
||||
});
|
||||
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.$rootScope = $rootScope);
|
||||
export default $rootScope;
|
@ -1,6 +1,6 @@
|
||||
import { Modes } from './mtproto/mtproto_config';
|
||||
import { notifySomeone, isWorker } from '../helpers/context';
|
||||
import { parse, stringify } from '../helpers/json';
|
||||
import { stringify } from '../helpers/json';
|
||||
|
||||
class ConfigStorage {
|
||||
public keyPrefix = '';
|
||||
@ -41,11 +41,14 @@ class ConfigStorage {
|
||||
this.useLs = false;
|
||||
}
|
||||
|
||||
// const str = `[get] ${keys.join(', ')}`;
|
||||
// console.time(str);
|
||||
try {
|
||||
value = (value === undefined || value === null) ? false : parse(value);
|
||||
value = (value === undefined || value === null) ? false : JSON.parse(value);
|
||||
} catch(e) {
|
||||
value = false;
|
||||
}
|
||||
//console.timeEnd(str);
|
||||
result.push(this.cache[key] = value);
|
||||
} else {
|
||||
allFound = false;
|
||||
|
100
src/lib/utils.ts
100
src/lib/utils.ts
@ -1,22 +1,6 @@
|
||||
import type { StickerSet } from "../layer";
|
||||
import type { MyDocument } from "./appManagers/appDocsManager";
|
||||
import type { Poll, PollResults } from "./appManagers/appPollsManager";
|
||||
import type { AppMessagesManager, Dialog, MyDialogFilter } from "./appManagers/appMessagesManager";
|
||||
/*!
|
||||
* Webogram v0.7.0 - messaging web application for MTProto
|
||||
* https://github.com/zhukov/webogram
|
||||
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
|
||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import type { DownloadOptions } from "./mtproto/apiFileManager";
|
||||
import { RichTextProcessor } from "./richtextprocessor";
|
||||
|
||||
var _logTimer = Date.now();
|
||||
export function dT () {
|
||||
return '[' + ((Date.now() - _logTimer) / 1000).toFixed(3) + ']';
|
||||
}
|
||||
|
||||
/* export function isInDOM(element: Element, parentNode?: HTMLElement): boolean {
|
||||
if(!element) {
|
||||
return false;
|
||||
@ -32,7 +16,7 @@ export function isInDOM(element: Element): boolean {
|
||||
return element?.isConnected;
|
||||
}
|
||||
|
||||
export function checkDragEvent(e: any) {
|
||||
/* export function checkDragEvent(e: any) {
|
||||
if(!e || e.target && (e.target.tagName == 'IMG' || e.target.tagName == 'A')) return false
|
||||
if(e.dataTransfer && e.dataTransfer.types) {
|
||||
for(var i = 0; i < e.dataTransfer.types.length; i++) {
|
||||
@ -45,7 +29,7 @@ export function checkDragEvent(e: any) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} */
|
||||
|
||||
export function cancelEvent (event: Event) {
|
||||
event = event || window.event;
|
||||
@ -159,86 +143,6 @@ export function getRichElementValue(node: any, lines: string[], line: string[],
|
||||
}
|
||||
} */
|
||||
|
||||
type BroadcastEvents = {
|
||||
'user_update': number,
|
||||
'user_auth': {dcID?: number, id: number},
|
||||
'peer_changed': number,
|
||||
|
||||
'filter_delete': MyDialogFilter,
|
||||
'filter_update': MyDialogFilter,
|
||||
|
||||
'dialog_draft': {peerID: number, draft: any, index: number},
|
||||
'dialog_unread': {peerID: number, count?: number},
|
||||
'dialog_flush': {peerID: number},
|
||||
'dialog_drop': {peerID: number, dialog?: Dialog},
|
||||
'dialog_migrate': {migrateFrom: number, migrateTo: number},
|
||||
'dialog_top': Dialog,
|
||||
'dialog_notify_settings': number,
|
||||
'dialogs_multiupdate': {[peerID: string]: Dialog},
|
||||
'dialogs_archived_unread': {count: number},
|
||||
|
||||
'history_append': {peerID: number, messageID: number, my?: boolean},
|
||||
'history_update': {peerID: number, mid: number},
|
||||
'history_reply_markup': {peerID: number},
|
||||
'history_multiappend': AppMessagesManager['newMessagesToHandle'],
|
||||
'history_delete': {peerID: number, msgs: {[mid: number]: true}},
|
||||
'history_forbidden': number,
|
||||
'history_reload': number,
|
||||
'history_request': void,
|
||||
|
||||
'message_edit': {peerID: number, id: number, mid: number, justMedia: boolean},
|
||||
'message_views': {mid: number, views: number},
|
||||
'message_sent': {tempID: number, mid: number},
|
||||
'messages_pending': void,
|
||||
'messages_read': void,
|
||||
'messages_downloaded': number[],
|
||||
|
||||
'stickers_installed': StickerSet.stickerSet,
|
||||
'stickers_deleted': StickerSet.stickerSet,
|
||||
|
||||
'audio_play': {doc: MyDocument, mid: number},
|
||||
'audio_pause': void,
|
||||
|
||||
//'contacts_update': any,
|
||||
'avatar_update': number,
|
||||
'chat_full_update': number,
|
||||
'peer_pinned_message': number,
|
||||
'poll_update': {poll: Poll, results: PollResults},
|
||||
'chat_update': number,
|
||||
'stateSynchronized': void,
|
||||
'channel_settings': {channelID: number},
|
||||
'webpage_updated': {id: string, msgs: number[]},
|
||||
|
||||
'apiUpdate': any,
|
||||
'download_progress': any,
|
||||
//'draft_updated': any,
|
||||
};
|
||||
|
||||
export const $rootScope = {
|
||||
$broadcast: <T extends keyof BroadcastEvents>(name: T, detail?: BroadcastEvents[T]) => {
|
||||
/* if(name != 'user_update') {
|
||||
console.debug(dT(), 'Broadcasting ' + name + ' event, with args:', detail);
|
||||
} */
|
||||
|
||||
let myCustomEvent = new CustomEvent(name, {detail});
|
||||
document.dispatchEvent(myCustomEvent);
|
||||
},
|
||||
$on: <T extends keyof BroadcastEvents>(name: T, callback: (e: Omit<CustomEvent, 'detail'> & {detail: BroadcastEvents[T]}) => any) => {
|
||||
// @ts-ignore
|
||||
document.addEventListener(name, callback);
|
||||
},
|
||||
$off: <T extends keyof BroadcastEvents>(name: T, callback: (e: Omit<CustomEvent, 'detail'> & {detail: BroadcastEvents[T]}) => any) => {
|
||||
// @ts-ignore
|
||||
document.removeEventListener(name, callback);
|
||||
},
|
||||
|
||||
selectedPeerID: 0,
|
||||
myID: 0,
|
||||
idle: {
|
||||
isIDLE: false
|
||||
}
|
||||
};
|
||||
|
||||
// generate a path's arc data parameter
|
||||
// http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
|
||||
var arcParameter = function(rx: number, ry: number, xAxisRotation: number, largeArcFlag: number, sweepFlag: number, x: number, y: number) {
|
||||
|
@ -138,7 +138,7 @@ let onFirstMount = () => {
|
||||
});
|
||||
selectCountryCode.addEventListener('blur', function(this: typeof selectCountryCode, e) {
|
||||
wrapper.classList.remove('active');
|
||||
hideTimeout = setTimeout(() => {
|
||||
hideTimeout = window.setTimeout(() => {
|
||||
wrapper.classList.add('hide');
|
||||
}, 200);
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
18
src/test_cache_and_local_storage_speed.js
Normal file
18
src/test_cache_and_local_storage_speed.js
Normal file
@ -0,0 +1,18 @@
|
||||
console.time('open');
|
||||
caches.open('sessions').then(cache => {
|
||||
console.timeEnd('open');
|
||||
cache.put('/state', new Response(JSON.stringify(appStateManager.state), {headers: {'Content-Type': 'application/json'}}));
|
||||
});
|
||||
|
||||
console.time('match');
|
||||
caches.open('sessions').then(async(cache) => {
|
||||
const response = await cache.match('/state');
|
||||
const promise = response.json();
|
||||
promise.then((json) => {
|
||||
console.timeEnd('match');
|
||||
});
|
||||
});
|
||||
|
||||
console.time('getItem');
|
||||
var value = JSON.parse(localStorage.getItem('state'));
|
||||
console.timeEnd('getItem');
|
@ -14,6 +14,7 @@ console.log('DEVMODE:', devMode);
|
||||
|
||||
const opts = {
|
||||
MTPROTO_WORKER: true,
|
||||
MTPROTO_HTTP: false,
|
||||
version: 3,
|
||||
"ifdef-verbose": true, // add this for verbose output
|
||||
"ifdef-triple-slash": true // add this to use double slash comment instead of default triple slash
|
||||
|
Loading…
x
Reference in New Issue
Block a user