2021-04-08 15:52:31 +02:00
|
|
|
|
/*
|
|
|
|
|
* https://github.com/morethanwords/tweb
|
|
|
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
|
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
|
|
|
*/
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
import type {GroupCallId, MyGroupCall} from './appGroupCallsManager';
|
|
|
|
|
import type GroupCallInstance from '../calls/groupCallInstance';
|
|
|
|
|
import type CallInstance from '../calls/callInstance';
|
2022-08-13 14:14:06 +02:00
|
|
|
|
import animationIntersector, {AnimationItemGroup} from '../../components/animationIntersector';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import appSidebarLeft, {LEFT_COLUMN_ACTIVE_CLASSNAME} from '../../components/sidebarLeft';
|
|
|
|
|
import appSidebarRight, {RIGHT_COLUMN_ACTIVE_CLASSNAME} from '../../components/sidebarRight';
|
|
|
|
|
import mediaSizes, {ScreenSize} from '../../helpers/mediaSizes';
|
|
|
|
|
import {logger, LogTypes} from '../logger';
|
2020-11-15 04:33:47 +01:00
|
|
|
|
import rootScope from '../rootScope';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import Chat, {ChatType} from '../../components/chat/chat';
|
|
|
|
|
import PopupNewMedia, {getCurrentNewMediaPopup} from '../../components/popups/newMedia';
|
2020-12-01 16:38:36 +01:00
|
|
|
|
import MarkupTooltip from '../../components/chat/markupTooltip';
|
2022-06-17 18:01:43 +02:00
|
|
|
|
import IS_TOUCH_SUPPORTED from '../../environment/touchSupport';
|
2020-12-12 01:52:11 +01:00
|
|
|
|
import SetTransition from '../../components/singleTransition';
|
|
|
|
|
import ChatDragAndDrop from '../../components/chat/dragAndDrop';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {doubleRaf} from '../../helpers/schedulers';
|
2021-12-11 17:37:08 +01:00
|
|
|
|
import lottieLoader from '../rlottie/lottieLoader';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import useHeavyAnimationCheck, {dispatchHeavyAnimationEvent} from '../../hooks/useHeavyAnimationCheck';
|
2021-06-06 16:22:29 +02:00
|
|
|
|
import stateStorage from '../stateStorage';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {MOUNT_CLASS_TO} from '../../config/debug';
|
2021-02-16 16:36:26 +01:00
|
|
|
|
import appNavigationController from '../../components/appNavigationController';
|
2021-03-12 17:49:09 +01:00
|
|
|
|
import AppPrivateSearchTab from '../../components/sidebarRight/tabs/search';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import I18n, {i18n, join, LangPackKey} from '../langPack';
|
2023-01-25 15:21:38 +01:00
|
|
|
|
import {ChatFull, ChatInvite, ChatParticipant, ChatParticipants, Message, MessageAction, MessageMedia, SendMessageAction, User, Chat as MTChat, UrlAuthResult, WallPaper} from '../../layer';
|
2021-04-20 20:00:38 +02:00
|
|
|
|
import PeerTitle from '../../components/peerTitle';
|
2023-01-09 14:44:17 +01:00
|
|
|
|
import PopupPeer, {PopupPeerCheckboxOptions} from '../../components/popups/peer';
|
2021-05-08 19:46:50 +02:00
|
|
|
|
import blurActiveElement from '../../helpers/dom/blurActiveElement';
|
2022-04-15 14:09:21 +02:00
|
|
|
|
import cancelEvent from '../../helpers/dom/cancelEvent';
|
2021-05-08 19:46:50 +02:00
|
|
|
|
import disableTransition from '../../helpers/dom/disableTransition';
|
|
|
|
|
import placeCaretAtEnd from '../../helpers/dom/placeCaretAtEnd';
|
|
|
|
|
import replaceContent from '../../helpers/dom/replaceContent';
|
|
|
|
|
import whichChild from '../../helpers/dom/whichChild';
|
2021-05-25 12:45:35 +02:00
|
|
|
|
import PopupElement from '../../components/popups';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import singleInstance, {InstanceDeactivateReason, SingleInstance} from '../mtproto/singleInstance';
|
2021-06-29 15:17:10 +02:00
|
|
|
|
import PopupStickers from '../../components/popups/stickers';
|
2021-06-29 16:21:16 +02:00
|
|
|
|
import PopupJoinChatInvite from '../../components/popups/joinChatInvite';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {toast, toastNew} from '../../components/toast';
|
2021-08-03 03:44:13 +02:00
|
|
|
|
import debounce from '../../helpers/schedulers/debounce';
|
2022-04-15 14:09:21 +02:00
|
|
|
|
import pause from '../../helpers/schedulers/pause';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {InternalLink, InternalLinkTypeMap, INTERNAL_LINK_TYPE} from './internalLink';
|
2021-09-26 15:59:10 +02:00
|
|
|
|
import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport';
|
2023-02-27 14:11:37 +01:00
|
|
|
|
import IMAGE_MIME_TYPES_SUPPORTED from '../../environment/imageMimeTypesSupport';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {NULL_PEER_ID} from '../mtproto/mtproto_config';
|
2021-10-21 15:16:43 +02:00
|
|
|
|
import telegramMeWebManager from '../mtproto/telegramMeWebManager';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {ONE_DAY} from '../../helpers/date';
|
2021-12-11 17:37:08 +01:00
|
|
|
|
import TopbarCall from '../../components/topbarCall';
|
|
|
|
|
import confirmationPopup from '../../components/confirmationPopup';
|
|
|
|
|
import IS_GROUP_CALL_SUPPORTED from '../../environment/groupCallSupport';
|
2022-01-08 13:52:14 +01:00
|
|
|
|
import IS_CALL_SUPPORTED from '../../environment/callSupport';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {CallType} from '../calls/types';
|
2023-01-06 20:27:29 +01:00
|
|
|
|
import {Modify, SendMessageEmojiInteractionData} from '../../types';
|
2022-01-23 20:45:34 +01:00
|
|
|
|
import htmlToSpan from '../../helpers/dom/htmlToSpan';
|
|
|
|
|
import getVisibleRect from '../../helpers/dom/getVisibleRect';
|
2023-01-06 20:27:29 +01:00
|
|
|
|
import {simulateClickEvent} from '../../helpers/dom/clickEvent';
|
2022-03-23 16:15:07 +01:00
|
|
|
|
import PopupCall from '../../components/call';
|
|
|
|
|
import copy from '../../helpers/object/copy';
|
|
|
|
|
import getObjectKeysAndSort from '../../helpers/object/getObjectKeysAndSort';
|
2022-03-25 00:16:03 +01:00
|
|
|
|
import numberThousandSplitter from '../../helpers/number/numberThousandSplitter';
|
2022-04-09 00:43:30 +02:00
|
|
|
|
import ChatBackgroundPatternRenderer from '../../components/chat/patternRenderer';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {IS_FIREFOX} from '../../environment/userAgent';
|
2022-04-17 14:59:55 +02:00
|
|
|
|
import compareVersion from '../../helpers/compareVersion';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {AppManagers} from './managers';
|
2022-04-25 16:54:30 +02:00
|
|
|
|
import uiNotificationsManager from './uiNotificationsManager';
|
|
|
|
|
import appMediaPlaybackController from '../../components/appMediaPlaybackController';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {PHONE_NUMBER_REG_EXP} from '../richTextProcessor';
|
2022-04-25 16:54:30 +02:00
|
|
|
|
import wrapEmojiText from '../richTextProcessor/wrapEmojiText';
|
2022-11-07 15:25:27 +01:00
|
|
|
|
import wrapRichText, {CustomEmojiRendererElement, renderEmojis} from '../richTextProcessor/wrapRichText';
|
2022-04-25 16:54:30 +02:00
|
|
|
|
import wrapUrl from '../richTextProcessor/wrapUrl';
|
2022-06-17 18:01:43 +02:00
|
|
|
|
import generateMessageId from './utils/messageId/generateMessageId';
|
|
|
|
|
import getUserStatusString from '../../components/wrappers/getUserStatusString';
|
|
|
|
|
import getChatMembersString from '../../components/wrappers/getChatMembersString';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {STATE_INIT} from '../../config/state';
|
2022-08-04 04:42:17 +02:00
|
|
|
|
import CacheStorageController from '../files/cacheStorage';
|
2022-06-17 18:01:43 +02:00
|
|
|
|
import themeController from '../../helpers/themeController';
|
|
|
|
|
import overlayCounter from '../../helpers/overlayCounter';
|
|
|
|
|
import appDialogsManager from './appDialogsManager';
|
|
|
|
|
import idleController from '../../helpers/idleController';
|
|
|
|
|
import EventListenerBase from '../../helpers/eventListenerBase';
|
2022-08-04 08:49:54 +02:00
|
|
|
|
import {AckedResult} from '../mtproto/superMessagePort';
|
2022-06-17 18:01:43 +02:00
|
|
|
|
import groupCallsController from '../calls/groupCallsController';
|
|
|
|
|
import callsController from '../calls/callsController';
|
|
|
|
|
import getFilesFromEvent from '../../helpers/files/getFilesFromEvent';
|
|
|
|
|
import apiManagerProxy from '../mtproto/mtprotoworker';
|
2022-06-24 19:23:12 +02:00
|
|
|
|
import appRuntimeManager from './appRuntimeManager';
|
2022-07-19 16:17:01 +02:00
|
|
|
|
import paymentsWrapCurrencyAmount from '../../helpers/paymentsWrapCurrencyAmount';
|
2022-07-23 00:41:11 +02:00
|
|
|
|
import findUpClassName from '../../helpers/dom/findUpClassName';
|
2022-08-09 17:35:11 +02:00
|
|
|
|
import {CLICK_EVENT_NAME} from '../../helpers/dom/clickEvent';
|
2022-07-18 19:05:50 +02:00
|
|
|
|
import PopupPayment from '../../components/popups/payment';
|
2022-11-01 18:39:23 +01:00
|
|
|
|
import wrapPeerTitle from '../../components/wrappers/peerTitle';
|
2022-11-06 14:48:41 +01:00
|
|
|
|
import NBSP from '../../helpers/string/nbsp';
|
2022-11-07 15:25:27 +01:00
|
|
|
|
import {makeMediaSize, MediaSize} from '../../helpers/mediaSize';
|
|
|
|
|
import {MiddleEllipsisElement} from '../../components/middleEllipsis';
|
2022-11-18 10:43:52 +01:00
|
|
|
|
import addAnchorListener from '../../helpers/addAnchorListener';
|
|
|
|
|
import parseUriParams from '../../helpers/string/parseUriParams';
|
2023-01-06 20:27:29 +01:00
|
|
|
|
import getMessageThreadId from './utils/messages/getMessageThreadId';
|
2023-01-09 14:44:17 +01:00
|
|
|
|
import findUpTag from '../../helpers/dom/findUpTag';
|
|
|
|
|
import {MTAppConfig} from '../mtproto/appConfig';
|
2023-01-25 15:21:38 +01:00
|
|
|
|
import PopupForward from '../../components/popups/forward';
|
2023-01-28 12:52:24 +01:00
|
|
|
|
import AppBackgroundTab from '../../components/sidebarLeft/tabs/background';
|
2023-02-27 14:11:37 +01:00
|
|
|
|
import partition from '../../helpers/array/partition';
|
|
|
|
|
import indexOfAndSplice from '../../helpers/array/indexOfAndSplice';
|
2020-08-24 16:09:31 +02:00
|
|
|
|
|
2021-04-13 18:19:52 +02:00
|
|
|
|
export type ChatSavedPosition = {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
mids: number[],
|
2021-04-13 18:19:52 +02:00
|
|
|
|
top: number
|
|
|
|
|
};
|
|
|
|
|
|
2022-01-13 00:54:33 +01:00
|
|
|
|
export type ChatSetPeerOptions = {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
peerId: PeerId,
|
2022-08-04 08:49:54 +02:00
|
|
|
|
lastMsgId?: number,
|
2022-01-13 00:54:33 +01:00
|
|
|
|
threadId?: number,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
startParam?: string,
|
|
|
|
|
stack?: number,
|
|
|
|
|
commentId?: number,
|
|
|
|
|
type?: ChatType
|
2022-01-13 00:54:33 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export type ChatSetInnerPeerOptions = Modify<ChatSetPeerOptions, {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
peerId: PeerId,
|
2022-01-13 00:54:33 +01:00
|
|
|
|
type?: ChatType
|
2023-01-06 20:27:29 +01:00
|
|
|
|
}>;
|
2022-01-13 00:54:33 +01:00
|
|
|
|
|
2023-01-17 20:28:27 +01:00
|
|
|
|
export enum APP_TABS {
|
|
|
|
|
CHATLIST,
|
|
|
|
|
CHAT,
|
|
|
|
|
PROFILE
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
export class AppImManager extends EventListenerBase<{
|
|
|
|
|
chat_changing: (details: {from: Chat, to: Chat}) => void,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
peer_changed: (chat: Chat) => void,
|
2022-06-17 18:01:43 +02:00
|
|
|
|
peer_changing: (chat: Chat) => void,
|
2023-01-17 20:28:27 +01:00
|
|
|
|
tab_changing: (tabId: number) => void
|
2022-06-17 18:01:43 +02:00
|
|
|
|
}> {
|
2020-06-05 18:01:06 +02:00
|
|
|
|
public columnEl = document.getElementById('column-center') as HTMLDivElement;
|
2020-12-01 16:38:36 +01:00
|
|
|
|
public chatsContainer: HTMLElement;
|
|
|
|
|
|
2020-02-06 16:43:07 +01:00
|
|
|
|
public offline = false;
|
|
|
|
|
public updateStatusInterval = 0;
|
2020-04-16 02:48:41 +02:00
|
|
|
|
|
2020-02-07 07:38:55 +01:00
|
|
|
|
public log: ReturnType<typeof logger>;
|
2020-04-16 02:48:41 +02:00
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
public setPeerPromise: Promise<void> = null;
|
2020-05-30 08:44:54 +02:00
|
|
|
|
|
2023-01-17 20:28:27 +01:00
|
|
|
|
private tabId: APP_TABS;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-03-10 15:08:28 +01:00
|
|
|
|
public chats: Chat[] = [];
|
2020-12-21 04:11:26 +01:00
|
|
|
|
private prevTab: HTMLElement;
|
|
|
|
|
private chatsSelectTabDebounced: () => void;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
public markupTooltip: MarkupTooltip;
|
2022-03-13 21:51:16 +01:00
|
|
|
|
private backgroundPromises: {[slug: string]: Promise<string>};
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-12-11 17:37:08 +01:00
|
|
|
|
private topbarCall: TopbarCall;
|
2022-03-13 21:51:16 +01:00
|
|
|
|
public emojiAnimationContainer: HTMLDivElement;
|
|
|
|
|
|
|
|
|
|
private lastBackgroundUrl: string;
|
2020-06-05 18:01:06 +02:00
|
|
|
|
|
2022-04-25 16:54:30 +02:00
|
|
|
|
public managers: AppManagers;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
public cacheStorage = new CacheStorageController('cachedFiles');
|
2022-11-07 15:25:27 +01:00
|
|
|
|
public customEmojiSize: MediaSize;
|
2022-04-25 16:54:30 +02:00
|
|
|
|
|
2020-12-11 03:06:16 +01:00
|
|
|
|
get myId() {
|
|
|
|
|
return rootScope.myId;
|
2020-10-02 22:33:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
get chat(): Chat {
|
|
|
|
|
return this.chats[this.chats.length - 1];
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 16:54:30 +02:00
|
|
|
|
public construct(managers: AppManagers) {
|
|
|
|
|
this.managers = managers;
|
|
|
|
|
|
|
|
|
|
const {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
apiUpdatesManager
|
2022-04-25 16:54:30 +02:00
|
|
|
|
} = managers;
|
2022-04-15 23:48:39 +02:00
|
|
|
|
apiUpdatesManager.attach(I18n.lastRequestedLangCode);
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-04-25 16:54:30 +02:00
|
|
|
|
appMediaPlaybackController.construct(managers);
|
|
|
|
|
uiNotificationsManager.construct(managers);
|
2022-08-21 13:52:00 +02:00
|
|
|
|
uiNotificationsManager.start();
|
2020-10-03 02:35:26 +02:00
|
|
|
|
|
2021-04-27 17:45:53 +02:00
|
|
|
|
this.log = logger('IM', LogTypes.Log | LogTypes.Warn | LogTypes.Debug | LogTypes.Error);
|
2020-09-26 00:47:43 +02:00
|
|
|
|
|
2022-03-13 21:51:16 +01:00
|
|
|
|
this.backgroundPromises = {};
|
2022-06-17 18:01:43 +02:00
|
|
|
|
STATE_INIT.settings.themes.forEach((theme) => {
|
2023-01-25 15:21:38 +01:00
|
|
|
|
const themeSettings = theme.settings;
|
|
|
|
|
if(!themeSettings) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const {wallpaper} = themeSettings;
|
|
|
|
|
const slug = (wallpaper as WallPaper.wallPaper).slug;
|
|
|
|
|
if(!slug) {
|
|
|
|
|
return;
|
2022-03-13 21:51:16 +01:00
|
|
|
|
}
|
2023-01-25 15:21:38 +01:00
|
|
|
|
|
|
|
|
|
const url = 'assets/img/' + slug + '.svg' + (IS_FIREFOX ? '?1' : '');
|
|
|
|
|
this.backgroundPromises[slug] = Promise.resolve(url);
|
2022-03-13 21:51:16 +01:00
|
|
|
|
});
|
|
|
|
|
|
2023-01-17 20:28:27 +01:00
|
|
|
|
this.selectTab(APP_TABS.CHATLIST);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
|
|
|
|
|
idleController.addEventListener('change', (idle) => {
|
|
|
|
|
this.offline = idle;
|
2020-02-06 16:43:07 +01:00
|
|
|
|
this.updateStatus();
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(idle) {
|
|
|
|
|
clearInterval(this.updateStatusInterval);
|
|
|
|
|
} else {
|
2020-02-06 16:43:07 +01:00
|
|
|
|
this.updateStatusInterval = window.setInterval(() => this.updateStatus(), 50e3);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
}
|
2020-02-06 16:43:07 +01:00
|
|
|
|
});
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
this.chatsContainer = document.createElement('div');
|
|
|
|
|
this.chatsContainer.classList.add('chats-container', 'tabs-container');
|
2021-01-18 19:34:41 +01:00
|
|
|
|
this.chatsContainer.dataset.animation = 'navigation';
|
2020-08-19 14:29:10 +02:00
|
|
|
|
|
2022-01-23 20:45:34 +01:00
|
|
|
|
this.emojiAnimationContainer = document.createElement('div');
|
|
|
|
|
this.emojiAnimationContainer.classList.add('emoji-animation-container');
|
2022-01-25 06:27:22 +01:00
|
|
|
|
this.appendEmojiAnimationContainer(mediaSizes.activeScreen);
|
2022-01-23 20:45:34 +01:00
|
|
|
|
|
2020-12-21 04:11:26 +01:00
|
|
|
|
this.columnEl.append(this.chatsContainer);
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
this.createNewChat();
|
2020-12-21 04:11:26 +01:00
|
|
|
|
this.chatsSelectTab(this.chat.container);
|
2020-11-25 20:36:18 +01:00
|
|
|
|
|
2021-03-27 16:34:08 +01:00
|
|
|
|
appNavigationController.onHashChange = this.onHashChange;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// window.addEventListener('hashchange', this.onHashChange);
|
2021-01-03 13:02:35 +01:00
|
|
|
|
|
|
|
|
|
this.setSettings();
|
2021-06-11 14:52:53 +02:00
|
|
|
|
rootScope.addEventListener('settings_updated', this.setSettings);
|
2021-01-07 13:36:21 +01:00
|
|
|
|
|
2022-08-15 16:02:15 +02:00
|
|
|
|
const onPremiumToggle = (isPremium: boolean) => {
|
2022-07-26 23:50:05 +02:00
|
|
|
|
document.body.classList.toggle('is-premium', isPremium);
|
2022-08-15 16:02:15 +02:00
|
|
|
|
};
|
|
|
|
|
rootScope.addEventListener('premium_toggle', onPremiumToggle);
|
|
|
|
|
onPremiumToggle(rootScope.premium);
|
2023-01-06 20:27:29 +01:00
|
|
|
|
this.managers.rootScope.getPremium().then(onPremiumToggle);
|
2022-07-26 23:50:05 +02:00
|
|
|
|
|
2021-01-07 13:36:21 +01:00
|
|
|
|
useHeavyAnimationCheck(() => {
|
|
|
|
|
animationIntersector.setOnlyOnePlayableGroup('lock');
|
2022-11-06 14:48:41 +01:00
|
|
|
|
animationIntersector.checkAnimations2(true);
|
2021-01-07 13:36:21 +01:00
|
|
|
|
}, () => {
|
2022-08-15 16:02:15 +02:00
|
|
|
|
animationIntersector.setOnlyOnePlayableGroup();
|
2022-11-06 14:48:41 +01:00
|
|
|
|
animationIntersector.checkAnimations2(false);
|
2021-01-07 13:36:21 +01:00
|
|
|
|
});
|
2021-01-26 01:40:53 +01:00
|
|
|
|
|
2023-01-28 12:52:24 +01:00
|
|
|
|
themeController.AppBackgroundTab = AppBackgroundTab;
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(IS_FIREFOX && apiManagerProxy.oldVersion && compareVersion(apiManagerProxy.oldVersion, '1.4.3') === -1) {
|
2022-04-17 14:59:55 +02:00
|
|
|
|
this.deleteFilesIterative((response) => {
|
|
|
|
|
return response.headers.get('Content-Type') === 'image/svg+xml';
|
|
|
|
|
}).then(() => {
|
|
|
|
|
this.applyCurrentTheme();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.applyCurrentTheme();
|
|
|
|
|
}
|
2021-01-31 02:52:14 +01:00
|
|
|
|
|
2021-02-16 16:36:26 +01:00
|
|
|
|
// * fix simultaneous opened both sidebars, can happen when floating sidebar is opened with left sidebar
|
2021-03-16 17:50:25 +01:00
|
|
|
|
mediaSizes.addEventListener('changeScreen', (from, to) => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
if(document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME) &&
|
|
|
|
|
document.body.classList.contains(RIGHT_COLUMN_ACTIVE_CLASSNAME)) {
|
2021-02-16 16:36:26 +01:00
|
|
|
|
appSidebarRight.toggleSidebar(false);
|
|
|
|
|
}
|
2022-01-23 20:45:34 +01:00
|
|
|
|
|
2022-01-25 06:27:22 +01:00
|
|
|
|
this.appendEmojiAnimationContainer(to);
|
2021-02-16 16:36:26 +01:00
|
|
|
|
});
|
|
|
|
|
|
2022-03-13 21:51:16 +01:00
|
|
|
|
mediaSizes.addEventListener('resize', () => {
|
2022-04-09 00:43:30 +02:00
|
|
|
|
// const perf = performance.now();
|
|
|
|
|
const rect = this.chatsContainer.getBoundingClientRect();
|
|
|
|
|
ChatBackgroundPatternRenderer.resizeInstances(rect.width, rect.height).then(() => {
|
|
|
|
|
// this.log.warn('resize bg time:', performance.now() - perf);
|
|
|
|
|
// for(const chat of this.chats) {
|
|
|
|
|
// if(chat.renderDarkPattern) {
|
|
|
|
|
// chat.renderDarkPattern();
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
});
|
2022-03-13 21:51:16 +01:00
|
|
|
|
});
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.addEventListener('peer_changing', (chat) => {
|
2021-01-26 01:40:53 +01:00
|
|
|
|
this.saveChatPosition(chat);
|
|
|
|
|
});
|
|
|
|
|
|
2021-06-11 14:52:53 +02:00
|
|
|
|
rootScope.addEventListener('theme_change', () => {
|
2021-04-30 16:58:00 +02:00
|
|
|
|
this.applyCurrentTheme();
|
|
|
|
|
});
|
|
|
|
|
|
2021-11-29 16:24:29 +01:00
|
|
|
|
rootScope.addEventListener('choosing_sticker', (choosing) => {
|
|
|
|
|
this.setChoosingStickerTyping(!choosing);
|
|
|
|
|
});
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
rootScope.addEventListener('peer_title_edit', ({peerId, threadId}) => {
|
2023-01-17 20:28:27 +01:00
|
|
|
|
if(this.chat?.peerId === peerId && !threadId && this.tabId !== undefined) {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
this.overrideHash(peerId);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-01-23 20:45:34 +01:00
|
|
|
|
rootScope.addEventListener('peer_typings', ({peerId, typings}) => {
|
|
|
|
|
const chat = this.chat;
|
|
|
|
|
if(
|
2022-08-04 08:49:54 +02:00
|
|
|
|
!chat ||
|
|
|
|
|
chat.peerId !== peerId ||
|
2022-06-17 18:01:43 +02:00
|
|
|
|
overlayCounter.isOverlayActive || (
|
2022-08-04 08:49:54 +02:00
|
|
|
|
mediaSizes.activeScreen === ScreenSize.mobile &&
|
2023-01-17 20:28:27 +01:00
|
|
|
|
this.tabId !== APP_TABS.CHAT
|
2022-01-23 20:45:34 +01:00
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const typing = typings.find((typing) => typing.action._ === 'sendMessageEmojiInteraction');
|
2022-01-23 20:45:34 +01:00
|
|
|
|
if(typing?.action?._ === 'sendMessageEmojiInteraction') {
|
|
|
|
|
const action = typing.action;
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const bubble = chat.bubbles.bubbles[generateMessageId(typing.action.msg_id)];
|
2022-09-03 19:04:48 +02:00
|
|
|
|
if(bubble && bubble.classList.contains('emoji-big') && getVisibleRect(bubble, chat.bubbles.scrollable.container)) {
|
2022-02-10 11:52:48 +01:00
|
|
|
|
const stickerWrapper: HTMLElement = bubble.querySelector('.media-sticker-wrapper:not(.bubble-hover-reaction-sticker):not(.reaction-sticker)');
|
2022-01-23 20:45:34 +01:00
|
|
|
|
|
|
|
|
|
const data: SendMessageEmojiInteractionData = JSON.parse(action.interaction.data);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
data.a.forEach((a) => {
|
2022-01-23 20:45:34 +01:00
|
|
|
|
setTimeout(() => {
|
|
|
|
|
simulateClickEvent(stickerWrapper);
|
|
|
|
|
}, a.t * 1000);
|
|
|
|
|
});
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.managers.appMessagesManager.setTyping(peerId, {
|
2022-01-23 20:45:34 +01:00
|
|
|
|
_: 'sendMessageEmojiInteractionSeen',
|
|
|
|
|
emoticon: action.emoticon
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-06-24 19:23:12 +02:00
|
|
|
|
const onInstanceDeactivated = (reason: InstanceDeactivateReason) => {
|
|
|
|
|
const isUpdated = reason === 'version';
|
2022-07-18 15:00:41 +02:00
|
|
|
|
const popup = new PopupElement('popup-instance-deactivated', {overlayClosable: true});
|
2021-05-25 12:45:35 +02:00
|
|
|
|
const c = document.createElement('div');
|
|
|
|
|
c.classList.add('instance-deactivated-container');
|
|
|
|
|
(popup as any).container.replaceWith(c);
|
|
|
|
|
|
|
|
|
|
const header = document.createElement('div');
|
|
|
|
|
header.classList.add('header');
|
2022-06-24 19:23:12 +02:00
|
|
|
|
header.append(i18n(isUpdated ? 'Deactivated.Version.Title' : 'Deactivated.Title'));
|
2021-05-25 12:45:35 +02:00
|
|
|
|
|
|
|
|
|
const subtitle = document.createElement('div');
|
|
|
|
|
subtitle.classList.add('subtitle');
|
2022-06-24 19:23:12 +02:00
|
|
|
|
subtitle.append(i18n(isUpdated ? 'Deactivated.Version.Subtitle' : 'Deactivated.Subtitle'));
|
2021-05-25 12:45:35 +02:00
|
|
|
|
|
|
|
|
|
c.append(header, subtitle);
|
|
|
|
|
|
|
|
|
|
document.body.classList.add('deactivated');
|
|
|
|
|
|
2022-06-24 19:23:12 +02:00
|
|
|
|
const onClose = isUpdated ? () => {
|
|
|
|
|
appRuntimeManager.reload();
|
|
|
|
|
} : () => {
|
2021-05-25 12:45:35 +02:00
|
|
|
|
document.body.classList.add('deactivated-backwards');
|
|
|
|
|
|
2021-06-18 04:30:36 +02:00
|
|
|
|
singleInstance.activateInstance();
|
2021-05-25 12:45:35 +02:00
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
document.body.classList.remove('deactivated', 'deactivated-backwards');
|
|
|
|
|
}, 333);
|
2022-06-24 19:23:12 +02:00
|
|
|
|
};
|
2021-05-25 12:45:35 +02:00
|
|
|
|
|
2022-06-24 19:23:12 +02:00
|
|
|
|
popup.addEventListener('close', onClose);
|
2021-05-25 12:45:35 +02:00
|
|
|
|
popup.show();
|
2022-06-24 19:23:12 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
singleInstance.addEventListener('deactivated', onInstanceDeactivated);
|
|
|
|
|
if(singleInstance.deactivatedReason) {
|
|
|
|
|
onInstanceDeactivated(singleInstance.deactivatedReason);
|
|
|
|
|
}
|
2021-05-25 12:45:35 +02:00
|
|
|
|
|
2022-03-13 21:51:16 +01:00
|
|
|
|
// remove scroll listener when setting chat to tray
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.addEventListener('chat_changing', ({to}) => {
|
2022-03-13 21:51:16 +01:00
|
|
|
|
this.toggleChatGradientAnimation(to);
|
|
|
|
|
});
|
|
|
|
|
|
2022-04-13 00:51:20 +02:00
|
|
|
|
rootScope.addEventListener('service_notification', (update) => {
|
|
|
|
|
confirmationPopup({
|
|
|
|
|
button: {langKey: 'OK', isCancel: true},
|
2022-04-25 16:54:30 +02:00
|
|
|
|
description: wrapRichText(update.message)
|
2022-04-13 00:51:20 +02:00
|
|
|
|
});
|
|
|
|
|
});
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-07-19 16:17:01 +02:00
|
|
|
|
rootScope.addEventListener('payment_sent', async({peerId, mid, receiptMessage}) => {
|
|
|
|
|
const message = await this.managers.appMessagesManager.getMessageByPeer(peerId, mid);
|
|
|
|
|
if(!message) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const action = receiptMessage.action as MessageAction.messageActionPaymentSent;
|
|
|
|
|
toastNew({
|
|
|
|
|
langPackKey: 'PaymentInfoHint',
|
|
|
|
|
langPackArguments: [
|
|
|
|
|
paymentsWrapCurrencyAmount(action.total_amount, action.currency),
|
|
|
|
|
wrapEmojiText(((message as Message.message).media as MessageMedia.messageMediaInvoice).title)
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
});
|
2022-07-23 00:41:11 +02:00
|
|
|
|
|
|
|
|
|
(window as any).onSpoilerClick = (e: MouseEvent) => {
|
|
|
|
|
const spoiler = findUpClassName(e.target, 'spoiler');
|
2022-08-31 06:22:16 +02:00
|
|
|
|
const parentElement = findUpClassName(spoiler, 'spoilers-container') || spoiler.parentElement;
|
2022-07-23 00:41:11 +02:00
|
|
|
|
|
|
|
|
|
const className = 'is-spoiler-visible';
|
|
|
|
|
const isVisible = parentElement.classList.contains(className);
|
|
|
|
|
if(!isVisible) {
|
|
|
|
|
cancelEvent(e);
|
2022-07-26 07:22:46 +02:00
|
|
|
|
|
|
|
|
|
if(CLICK_EVENT_NAME !== 'click') {
|
|
|
|
|
window.addEventListener('click', cancelEvent, {capture: true, once: true});
|
|
|
|
|
}
|
2022-07-23 00:41:11 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const duration = 400 / 2;
|
|
|
|
|
const showDuration = 5000;
|
|
|
|
|
const useRafs = !isVisible ? 2 : 0;
|
|
|
|
|
if(useRafs) {
|
|
|
|
|
parentElement.classList.add('will-change');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const spoilerTimeout = parentElement.dataset.spoilerTimeout;
|
|
|
|
|
if(spoilerTimeout !== null) {
|
|
|
|
|
clearTimeout(+spoilerTimeout);
|
|
|
|
|
delete parentElement.dataset.spoilerTimeout;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
SetTransition({
|
|
|
|
|
element: parentElement,
|
|
|
|
|
className,
|
|
|
|
|
forwards: true,
|
|
|
|
|
duration,
|
|
|
|
|
onTransitionEnd: () => {
|
|
|
|
|
parentElement.dataset.spoilerTimeout = '' + window.setTimeout(() => {
|
|
|
|
|
SetTransition({
|
|
|
|
|
element: parentElement,
|
|
|
|
|
className,
|
|
|
|
|
forwards: false,
|
|
|
|
|
duration,
|
|
|
|
|
onTransitionEnd: () => {
|
|
|
|
|
parentElement.classList.remove('will-change');
|
|
|
|
|
delete parentElement.dataset.spoilerTimeout;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}, showDuration);
|
|
|
|
|
},
|
|
|
|
|
useRafs
|
|
|
|
|
});
|
2022-07-23 00:41:11 +02:00
|
|
|
|
};
|
2022-08-09 17:35:11 +02:00
|
|
|
|
|
2022-08-18 13:21:19 +02:00
|
|
|
|
rootScope.addEventListener('sticker_updated', ({type, faved}) => {
|
|
|
|
|
if(type === 'faved') {
|
|
|
|
|
toastNew({
|
|
|
|
|
langPackKey: faved ? 'AddedToFavorites' : 'RemovedFromFavorites'
|
|
|
|
|
});
|
|
|
|
|
} else if(!faved) {
|
|
|
|
|
toastNew({
|
|
|
|
|
langPackKey: 'RemovedFromRecent'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
apiManagerProxy.addEventListener('notificationBuild', async(options) => {
|
|
|
|
|
const isForum = await this.managers.appPeersManager.isForum(options.message.peerId);
|
|
|
|
|
const threadId = getMessageThreadId(options.message, isForum);
|
|
|
|
|
if(this.chat.peerId === options.message.peerId && this.chat.threadId === threadId && !idleController.isIdle) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
uiNotificationsManager.buildNotification(options);
|
|
|
|
|
});
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
this.addEventListener('peer_changed', async({peerId}) => {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
document.body.classList.toggle('has-chat', !!peerId);
|
|
|
|
|
|
2022-08-13 14:14:06 +02:00
|
|
|
|
this.emojiAnimationContainer.textContent = '';
|
|
|
|
|
|
2022-07-26 07:43:27 +02:00
|
|
|
|
this.overrideHash(peerId);
|
2022-06-24 19:23:12 +02:00
|
|
|
|
|
|
|
|
|
apiManagerProxy.updateTabState('chatPeerIds', this.chats.map((chat) => chat.peerId).filter(Boolean));
|
2021-04-13 18:19:52 +02:00
|
|
|
|
});
|
2021-04-24 15:35:00 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
// stateStorage.get('chatPositions').then((c) => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
stateStorage.setToCache('chatPositions', /* c || */{});
|
2022-06-17 18:01:43 +02:00
|
|
|
|
// });
|
|
|
|
|
|
2022-01-08 13:52:14 +01:00
|
|
|
|
if(IS_CALL_SUPPORTED || IS_GROUP_CALL_SUPPORTED) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.topbarCall = new TopbarCall(managers);
|
2022-01-08 13:52:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-23 16:15:07 +01:00
|
|
|
|
if(IS_CALL_SUPPORTED) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
callsController.addEventListener('instance', ({instance/* , hasCurrent */}) => {
|
2022-03-24 15:16:41 +01:00
|
|
|
|
// if(hasCurrent) {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// return;
|
2022-03-24 15:16:41 +01:00
|
|
|
|
// }
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const popup = new PopupCall(instance);
|
2022-03-24 15:16:41 +01:00
|
|
|
|
|
|
|
|
|
instance.addEventListener('acceptCallOverride', () => {
|
|
|
|
|
return this.discardCurrentCall(instance.interlocutorUserId.toPeerId(), undefined, instance)
|
|
|
|
|
.then(() => {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
callsController.dispatchEvent('accepting', instance);
|
2022-03-24 15:16:41 +01:00
|
|
|
|
return true;
|
|
|
|
|
})
|
|
|
|
|
.catch(() => false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
popup.addEventListener('close', () => {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const currentCall = callsController.currentCall;
|
2022-03-24 15:16:41 +01:00
|
|
|
|
if(currentCall && currentCall !== instance && !instance.wasTryingToJoin) {
|
|
|
|
|
instance.hangUp('phoneCallDiscardReasonBusy');
|
|
|
|
|
}
|
|
|
|
|
}, {once: true});
|
|
|
|
|
|
|
|
|
|
popup.show();
|
2022-01-08 13:52:14 +01:00
|
|
|
|
});
|
2022-03-25 17:42:35 +01:00
|
|
|
|
|
2022-11-01 18:39:23 +01:00
|
|
|
|
callsController.addEventListener('incompatible', async(userId) => {
|
2022-03-25 17:42:35 +01:00
|
|
|
|
toastNew({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
langPackKey: 'VoipPeerIncompatible',
|
2022-03-25 17:42:35 +01:00
|
|
|
|
langPackArguments: [
|
2022-11-01 18:39:23 +01:00
|
|
|
|
await wrapPeerTitle({peerId: userId.toPeerId()})
|
2022-03-25 17:42:35 +01:00
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
});
|
2022-03-23 16:15:07 +01:00
|
|
|
|
}
|
2021-12-11 17:37:08 +01:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// ! do not remove this line
|
2021-08-13 19:48:20 +02:00
|
|
|
|
// ! instance can be deactivated before the UI starts, because it waits in background for RAF that is delayed
|
|
|
|
|
singleInstance.activateInstance();
|
|
|
|
|
|
2021-10-21 15:16:43 +02:00
|
|
|
|
const setAuthorized = () => {
|
|
|
|
|
telegramMeWebManager.setAuthorized(true);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
setInterval(setAuthorized, ONE_DAY);
|
|
|
|
|
setAuthorized();
|
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{}>({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
name: 'showMaskedAlert',
|
2021-06-29 16:21:16 +02:00
|
|
|
|
callback: (params, element) => {
|
|
|
|
|
const href = element.href;
|
|
|
|
|
|
|
|
|
|
const a = element.cloneNode(true) as HTMLAnchorElement;
|
|
|
|
|
a.className = 'anchor-url';
|
|
|
|
|
a.innerText = href;
|
|
|
|
|
a.removeAttribute('onclick');
|
|
|
|
|
|
|
|
|
|
new PopupPeer('popup-masked-url', {
|
|
|
|
|
titleLangKey: 'OpenUrlTitle',
|
|
|
|
|
descriptionLangKey: 'OpenUrlAlert2',
|
|
|
|
|
descriptionLangArgs: [a],
|
|
|
|
|
buttons: [{
|
|
|
|
|
langKey: 'Open',
|
|
|
|
|
callback: () => {
|
|
|
|
|
a.click();
|
2022-08-04 08:49:54 +02:00
|
|
|
|
}
|
2021-06-29 16:21:16 +02:00
|
|
|
|
}]
|
|
|
|
|
}).show();
|
2021-08-10 19:07:04 +02:00
|
|
|
|
}
|
2021-06-29 16:21:16 +02:00
|
|
|
|
});
|
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{uriParams: {command: string, bot: string}}>({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
name: 'execBotCommand',
|
2021-08-10 19:07:04 +02:00
|
|
|
|
callback: ({uriParams}) => {
|
|
|
|
|
const {command, bot} = uriParams;
|
2021-06-29 16:21:16 +02:00
|
|
|
|
|
|
|
|
|
/* const promise = bot ? this.openUsername(bot).then(() => this.chat.peerId) : Promise.resolve(this.chat.peerId);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
promise.then((peerId) => {
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.managers.appMessagesManager.sendText(peerId, '/' + command);
|
2021-06-29 16:21:16 +02:00
|
|
|
|
}); */
|
2021-04-24 15:35:00 +02:00
|
|
|
|
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.managers.appMessagesManager.sendText(this.chat.peerId, '/' + command + (bot ? '@' + bot : ''));
|
2021-06-29 16:21:16 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// console.log(command, bot);
|
2021-08-11 21:24:13 +02:00
|
|
|
|
}
|
2021-06-29 15:17:10 +02:00
|
|
|
|
});
|
2021-05-28 19:01:06 +02:00
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{uriParams: {hashtag: string}}>({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
name: 'searchByHashtag',
|
2021-08-10 19:07:04 +02:00
|
|
|
|
callback: ({uriParams}) => {
|
|
|
|
|
const {hashtag} = uriParams;
|
2021-08-10 13:17:17 +02:00
|
|
|
|
if(!hashtag) {
|
2021-06-29 16:21:16 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.chat.initSearch('#' + hashtag + ' ');
|
2021-08-11 21:24:13 +02:00
|
|
|
|
}
|
2021-06-29 16:21:16 +02:00
|
|
|
|
});
|
2021-05-28 19:01:06 +02:00
|
|
|
|
|
2022-09-13 14:27:28 +02:00
|
|
|
|
([
|
|
|
|
|
['addstickers', INTERNAL_LINK_TYPE.STICKER_SET],
|
|
|
|
|
['addemoji', INTERNAL_LINK_TYPE.EMOJI_SET]
|
|
|
|
|
] as [
|
|
|
|
|
'addstickers' | 'addemoji',
|
|
|
|
|
INTERNAL_LINK_TYPE.STICKER_SET | INTERNAL_LINK_TYPE.EMOJI_SET
|
|
|
|
|
][]).forEach(([name, type]) => {
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{pathnameParams: [typeof name, string]}>({
|
2022-09-13 14:27:28 +02:00
|
|
|
|
name,
|
|
|
|
|
callback: ({pathnameParams}) => {
|
|
|
|
|
if(!pathnameParams[1]) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-09-04 19:59:00 +02:00
|
|
|
|
|
2022-09-13 14:27:28 +02:00
|
|
|
|
const link: InternalLink = {
|
|
|
|
|
_: type,
|
|
|
|
|
set: pathnameParams[1]
|
|
|
|
|
};
|
2021-08-11 21:24:13 +02:00
|
|
|
|
|
2022-09-13 14:27:28 +02:00
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{
|
2022-09-13 14:27:28 +02:00
|
|
|
|
uriParams: {
|
|
|
|
|
set: string
|
|
|
|
|
}
|
|
|
|
|
}>({
|
|
|
|
|
name,
|
|
|
|
|
protocol: 'tg',
|
|
|
|
|
callback: ({uriParams}) => {
|
|
|
|
|
const link = this.makeLink(type, uriParams);
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-06-29 15:17:10 +02:00
|
|
|
|
});
|
|
|
|
|
|
2022-07-18 19:05:50 +02:00
|
|
|
|
// * t.me/invoice/asdasdad
|
|
|
|
|
// * t.me/$asdasdad
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{pathnameParams: ['invoice', string] | string}>({
|
2022-07-18 19:05:50 +02:00
|
|
|
|
name: 'invoice',
|
|
|
|
|
callback: ({pathnameParams}) => {
|
|
|
|
|
const link: InternalLink = {
|
|
|
|
|
_: INTERNAL_LINK_TYPE.INVOICE,
|
|
|
|
|
slug: pathnameParams.length > 1 ? pathnameParams[1] : pathnameParams[0].slice(1)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2021-10-27 19:31:05 +02:00
|
|
|
|
// Support old t.me/joinchat/asd and new t.me/+asd
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{pathnameParams: ['joinchat', string]}>({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
name: 'joinchat',
|
2021-08-10 19:07:04 +02:00
|
|
|
|
callback: ({pathnameParams}) => {
|
2021-08-11 21:24:13 +02:00
|
|
|
|
const link: InternalLink = {
|
|
|
|
|
_: INTERNAL_LINK_TYPE.JOIN_CHAT,
|
2021-10-27 19:31:05 +02:00
|
|
|
|
invite: pathnameParams[1] || decodeURIComponent(pathnameParams[0]).slice(1)
|
2021-08-11 21:24:13 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2021-12-11 17:37:08 +01:00
|
|
|
|
if(IS_GROUP_CALL_SUPPORTED) {
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{
|
2021-12-11 17:37:08 +01:00
|
|
|
|
uriParams: Omit<InternalLink.InternalLinkVoiceChat, '_'>
|
|
|
|
|
}>({
|
|
|
|
|
name: 'voicechat',
|
|
|
|
|
protocol: 'tg',
|
|
|
|
|
callback: ({uriParams}) => {
|
|
|
|
|
const link = this.makeLink(INTERNAL_LINK_TYPE.VOICE_CHAT, uriParams);
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{
|
2021-08-11 21:24:13 +02:00
|
|
|
|
// pathnameParams: ['c', string, string],
|
|
|
|
|
// uriParams: {thread?: number}
|
|
|
|
|
// } | {
|
|
|
|
|
// pathnameParams: [string, string?],
|
|
|
|
|
// uriParams: {comment?: number}
|
|
|
|
|
pathnameParams: ['c', string, string] | [string, string?],
|
2022-01-13 00:54:33 +01:00
|
|
|
|
uriParams: {thread?: string, comment?: string} | {comment?: string, start?: string}
|
2021-08-11 21:24:13 +02:00
|
|
|
|
}>({
|
|
|
|
|
name: 'im',
|
2023-01-06 20:27:29 +01:00
|
|
|
|
callback: async({pathnameParams, uriParams}, element) => {
|
2021-08-11 21:24:13 +02:00
|
|
|
|
let link: InternalLink;
|
2022-04-25 16:54:30 +02:00
|
|
|
|
if(PHONE_NUMBER_REG_EXP.test(pathnameParams[0])) {
|
2022-03-25 16:50:41 +01:00
|
|
|
|
link = {
|
|
|
|
|
_: INTERNAL_LINK_TYPE.USER_PHONE_NUMBER,
|
|
|
|
|
phone: pathnameParams[0].slice(1)
|
|
|
|
|
};
|
|
|
|
|
} else if(pathnameParams[0] === 'c') {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
pathnameParams.shift();
|
|
|
|
|
const thread = 'thread' in uriParams ? uriParams.thread : pathnameParams[2] && pathnameParams[1];
|
2021-08-11 21:24:13 +02:00
|
|
|
|
link = {
|
|
|
|
|
_: INTERNAL_LINK_TYPE.PRIVATE_POST,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
channel: pathnameParams[0],
|
|
|
|
|
post: pathnameParams[2] || pathnameParams[1],
|
|
|
|
|
thread,
|
|
|
|
|
comment: uriParams.comment,
|
|
|
|
|
stack: this.getStackFromElement(element)
|
2021-08-11 21:24:13 +02:00
|
|
|
|
};
|
|
|
|
|
} else {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
const thread = 'thread' in uriParams ? uriParams.thread : pathnameParams[2] && pathnameParams[1];
|
2021-08-11 21:24:13 +02:00
|
|
|
|
link = {
|
|
|
|
|
_: INTERNAL_LINK_TYPE.MESSAGE,
|
|
|
|
|
domain: pathnameParams[0],
|
2023-01-06 20:27:29 +01:00
|
|
|
|
post: pathnameParams[2] || pathnameParams[1],
|
|
|
|
|
thread,
|
2022-01-13 00:54:33 +01:00
|
|
|
|
comment: uriParams.comment,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
start: 'start' in uriParams ? uriParams.start : undefined,
|
|
|
|
|
stack: this.getStackFromElement(element)
|
2021-08-11 21:24:13 +02:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{
|
2021-08-11 21:24:13 +02:00
|
|
|
|
uriParams: {
|
|
|
|
|
domain: string,
|
|
|
|
|
|
|
|
|
|
// telegrampassport
|
|
|
|
|
scope?: string,
|
|
|
|
|
nonce?: string,
|
|
|
|
|
payload?: string,
|
|
|
|
|
bot_id?: string,
|
|
|
|
|
public_key?: string,
|
|
|
|
|
callback_url?: string,
|
|
|
|
|
|
|
|
|
|
// regular
|
|
|
|
|
start?: string,
|
|
|
|
|
startgroup?: string,
|
|
|
|
|
game?: string,
|
|
|
|
|
voicechat?: string,
|
|
|
|
|
post?: string,
|
|
|
|
|
thread?: string,
|
2022-03-25 16:50:41 +01:00
|
|
|
|
comment?: string,
|
|
|
|
|
phone?: string
|
2021-08-11 21:24:13 +02:00
|
|
|
|
}
|
|
|
|
|
}>({
|
|
|
|
|
name: 'resolve',
|
|
|
|
|
protocol: 'tg',
|
2023-01-06 20:27:29 +01:00
|
|
|
|
callback: ({uriParams}, element) => {
|
2021-08-11 21:24:13 +02:00
|
|
|
|
let link: InternalLink;
|
2022-03-25 16:50:41 +01:00
|
|
|
|
if(uriParams.phone) {
|
|
|
|
|
link = this.makeLink(INTERNAL_LINK_TYPE.USER_PHONE_NUMBER, uriParams as Required<typeof uriParams>);
|
|
|
|
|
} else if(uriParams.domain === 'telegrampassport') {
|
2021-08-11 21:24:13 +02:00
|
|
|
|
|
|
|
|
|
} else {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
link = this.makeLink(INTERNAL_LINK_TYPE.MESSAGE, {
|
|
|
|
|
...uriParams,
|
|
|
|
|
stack: this.getStackFromElement(element)
|
|
|
|
|
});
|
2021-08-11 21:24:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{
|
2021-08-11 21:24:13 +02:00
|
|
|
|
uriParams: {
|
|
|
|
|
channel: string,
|
|
|
|
|
post: string,
|
|
|
|
|
thread?: string,
|
|
|
|
|
comment?: string
|
|
|
|
|
}
|
|
|
|
|
}>({
|
|
|
|
|
name: 'privatepost',
|
|
|
|
|
protocol: 'tg',
|
|
|
|
|
callback: ({uriParams}) => {
|
|
|
|
|
const link = this.makeLink(INTERNAL_LINK_TYPE.PRIVATE_POST, uriParams);
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{
|
2022-07-18 19:05:50 +02:00
|
|
|
|
uriParams: {
|
|
|
|
|
slug: string
|
|
|
|
|
}
|
|
|
|
|
}>({
|
|
|
|
|
name: 'invoice',
|
|
|
|
|
protocol: 'tg',
|
|
|
|
|
callback: ({uriParams}) => {
|
|
|
|
|
const link = this.makeLink(INTERNAL_LINK_TYPE.INVOICE, uriParams);
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
['joinchat' as const, 'join' as const].forEach((name) => {
|
2022-11-18 10:43:52 +01:00
|
|
|
|
addAnchorListener<{
|
2022-01-16 16:48:56 +01:00
|
|
|
|
uriParams: {
|
|
|
|
|
invite: string
|
|
|
|
|
}
|
|
|
|
|
}>({
|
|
|
|
|
name,
|
|
|
|
|
protocol: 'tg',
|
|
|
|
|
callback: ({uriParams}) => {
|
|
|
|
|
const link = this.makeLink(INTERNAL_LINK_TYPE.JOIN_CHAT, uriParams);
|
|
|
|
|
this.processInternalLink(link);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-08-11 21:24:13 +02:00
|
|
|
|
});
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.onHashChange(true);
|
2021-09-25 14:55:58 +02:00
|
|
|
|
this.attachKeydownListener();
|
2023-01-09 14:44:17 +01:00
|
|
|
|
this.handleAutologinDomains();
|
2023-01-25 15:21:38 +01:00
|
|
|
|
this.checkForShare();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private checkForShare() {
|
|
|
|
|
const share = apiManagerProxy.share;
|
|
|
|
|
if(share) {
|
|
|
|
|
apiManagerProxy.share = undefined;
|
|
|
|
|
new PopupForward(undefined, async(peerId) => {
|
|
|
|
|
await this.setPeer({peerId});
|
|
|
|
|
if(share.files?.length) {
|
|
|
|
|
const foundMedia = share.files.some((file) => MEDIA_MIME_TYPES_SUPPORTED.has(file.type));
|
|
|
|
|
new PopupNewMedia(this.chat, share.files, foundMedia ? 'media' : 'document');
|
|
|
|
|
} else {
|
|
|
|
|
this.managers.appMessagesManager.sendText(peerId, share.text);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-01-09 14:44:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public handleUrlAuth(options: {
|
|
|
|
|
peerId?: PeerId,
|
|
|
|
|
mid?: number,
|
|
|
|
|
buttonId?: number,
|
|
|
|
|
url: string
|
|
|
|
|
}) {
|
|
|
|
|
const {peerId, mid, buttonId, url} = options;
|
|
|
|
|
|
|
|
|
|
const openWindow = (url: string) => {
|
|
|
|
|
window.open(url, '_blank');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onUrlAuthResultAccepted = (urlAuthResult: UrlAuthResult.urlAuthResultAccepted) => {
|
|
|
|
|
openWindow(urlAuthResult.url);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onUrlAuthResult = async(urlAuthResult: UrlAuthResult): Promise<void> => {
|
|
|
|
|
if(urlAuthResult._ === 'urlAuthResultRequest') {
|
|
|
|
|
const b = document.createElement('b');
|
|
|
|
|
b.append(urlAuthResult.domain);
|
|
|
|
|
const peerTitle = await wrapPeerTitle({peerId: rootScope.myId});
|
|
|
|
|
const botPeerTitle = await wrapPeerTitle({peerId: urlAuthResult.bot.id.toPeerId()});
|
|
|
|
|
|
|
|
|
|
const logInCheckbox: PopupPeerCheckboxOptions = {
|
|
|
|
|
text: 'OpenUrlOption1',
|
|
|
|
|
textArgs: [b.cloneNode(true), peerTitle],
|
|
|
|
|
checked: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const allowMessagesCheckbox: PopupPeerCheckboxOptions = urlAuthResult.pFlags.request_write_access ? {
|
|
|
|
|
text: 'OpenUrlOption2',
|
|
|
|
|
textArgs: [botPeerTitle],
|
|
|
|
|
checked: true
|
|
|
|
|
} : undefined;
|
|
|
|
|
|
|
|
|
|
const checkboxes: PopupPeerCheckboxOptions[] = [
|
|
|
|
|
logInCheckbox,
|
|
|
|
|
allowMessagesCheckbox
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const confirmationPromise = confirmationPopup({
|
|
|
|
|
titleLangKey: 'OpenUrlTitle',
|
|
|
|
|
button: {
|
|
|
|
|
langKey: 'Open'
|
|
|
|
|
},
|
|
|
|
|
descriptionLangKey: 'OpenUrlAlert2',
|
|
|
|
|
descriptionLangArgs: [b],
|
|
|
|
|
checkboxes: checkboxes.filter(Boolean)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(allowMessagesCheckbox) {
|
|
|
|
|
logInCheckbox.checkboxField.input.addEventListener('change', () => {
|
|
|
|
|
const disabled = !logInCheckbox.checkboxField.checked;
|
|
|
|
|
allowMessagesCheckbox.checkboxField.toggleDisability(disabled);
|
|
|
|
|
|
|
|
|
|
if(disabled) {
|
|
|
|
|
allowMessagesCheckbox.checkboxField.checked = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const [logInChecked, allowMessagesChecked] = await confirmationPromise;
|
|
|
|
|
|
|
|
|
|
if(!logInChecked) {
|
|
|
|
|
openWindow(url);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await this.managers.appSeamlessLoginManager.acceptUrlAuth(
|
|
|
|
|
url,
|
|
|
|
|
peerId,
|
|
|
|
|
mid,
|
|
|
|
|
buttonId,
|
|
|
|
|
allowMessagesChecked
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return onUrlAuthResult(result);
|
|
|
|
|
} else if(urlAuthResult._ === 'urlAuthResultAccepted') {
|
|
|
|
|
onUrlAuthResultAccepted(urlAuthResult);
|
|
|
|
|
} else {
|
|
|
|
|
openWindow(url);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return this.managers.appSeamlessLoginManager.requestUrlAuth(
|
|
|
|
|
url,
|
|
|
|
|
peerId,
|
|
|
|
|
mid,
|
|
|
|
|
buttonId
|
|
|
|
|
).then((urlAuthResult) => {
|
|
|
|
|
onUrlAuthResult(urlAuthResult);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleAutologinDomains() {
|
|
|
|
|
let appConfig: MTAppConfig;
|
|
|
|
|
rootScope.addEventListener('app_config', (_appConfig) => {
|
|
|
|
|
appConfig = _appConfig;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const onAnchorClick = (element: HTMLAnchorElement) => {
|
|
|
|
|
const url = new URL(element.href);
|
|
|
|
|
if(appConfig.url_auth_domains.includes(url.hostname)) {
|
|
|
|
|
this.handleUrlAuth({url: element.href});
|
|
|
|
|
cancelEvent();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!appConfig.autologin_token || !appConfig.autologin_domains) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const originalUrl = element.dataset.originalUrl ??= element.href;
|
|
|
|
|
if(appConfig.autologin_domains.includes(url.hostname)) {
|
|
|
|
|
url.searchParams.set('autologin_token', appConfig.autologin_token);
|
|
|
|
|
element.href = url.toString();
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
element.href = originalUrl;
|
|
|
|
|
delete element.dataset.originalUrl;
|
|
|
|
|
}, 0);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
document.addEventListener('click', (e) => {
|
|
|
|
|
const anchor = findUpTag(e.target as HTMLElement, 'A') as HTMLAnchorElement;
|
|
|
|
|
if(anchor?.href) {
|
|
|
|
|
onAnchorClick(anchor);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// addAnchorListener({
|
|
|
|
|
// name: 'handleUrlClick',
|
|
|
|
|
// callback: (_, element) => {
|
|
|
|
|
// onAnchorClick(element);
|
|
|
|
|
// },
|
|
|
|
|
// noCancelEvent: true,
|
|
|
|
|
// noPathnameParams: true,
|
|
|
|
|
// noUriParams: true
|
|
|
|
|
// });
|
2021-09-25 14:55:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
private getStackFromElement(element: HTMLElement) {
|
|
|
|
|
const possibleBubble = findUpClassName(element, 'bubble');
|
|
|
|
|
return possibleBubble ? +possibleBubble.dataset.mid : undefined;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-17 14:59:55 +02:00
|
|
|
|
private deleteFilesIterative(callback: (response: Response) => boolean) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return this.cacheStorage.timeoutOperation((cache) => {
|
2022-04-17 14:59:55 +02:00
|
|
|
|
const perf = performance.now();
|
|
|
|
|
return cache.keys().then((requests) => {
|
|
|
|
|
const promises = requests.map((request) => {
|
|
|
|
|
return cache.match(request).then((response) => {
|
|
|
|
|
return callback(response);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return Promise.all(promises).then((values) => {
|
|
|
|
|
values.map((isBad, idx) => {
|
|
|
|
|
if(!isBad) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const request = requests[idx];
|
|
|
|
|
return cache.delete(request);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return Promise.all(values.filter(Boolean));
|
|
|
|
|
});
|
|
|
|
|
}).then(() => {
|
|
|
|
|
this.log('deleted files', performance.now() - perf);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-13 21:51:16 +01:00
|
|
|
|
private toggleChatGradientAnimation(activatingChat: Chat) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.chats.forEach((chat) => {
|
2022-03-13 21:51:16 +01:00
|
|
|
|
if(chat.gradientRenderer) {
|
|
|
|
|
chat.gradientRenderer.scrollAnimate(rootScope.settings.animationsEnabled && chat === activatingChat);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-25 06:27:22 +01:00
|
|
|
|
private appendEmojiAnimationContainer(screen: ScreenSize) {
|
|
|
|
|
const appendTo = screen === ScreenSize.mobile ? this.columnEl : document.body;
|
|
|
|
|
if(this.emojiAnimationContainer.parentElement !== appendTo) {
|
|
|
|
|
appendTo.append(this.emojiAnimationContainer)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-25 14:55:58 +02:00
|
|
|
|
private attachKeydownListener() {
|
|
|
|
|
const IGNORE_KEYS = new Set(['PageUp', 'PageDown', 'Meta', 'Control']);
|
|
|
|
|
const onKeyDown = (e: KeyboardEvent) => {
|
2021-12-01 13:46:58 +01:00
|
|
|
|
const key = e.key;
|
2022-11-01 18:39:23 +01:00
|
|
|
|
const isSelectionCollapsed = document.getSelection().isCollapsed;
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(overlayCounter.isOverlayActive || IGNORE_KEYS.has(key)) return;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-09-25 14:55:58 +02:00
|
|
|
|
const target = e.target as HTMLElement;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
|
|
|
|
// if(target.tagName === 'INPUT') return;
|
|
|
|
|
|
|
|
|
|
// this.log('onkeydown', e, document.activeElement);
|
2021-09-25 14:55:58 +02:00
|
|
|
|
|
|
|
|
|
const chat = this.chat;
|
|
|
|
|
|
2022-11-01 18:39:23 +01:00
|
|
|
|
if((key.startsWith('Arrow') || (e.shiftKey && key === 'Shift')) && !isSelectionCollapsed) {
|
|
|
|
|
return;
|
|
|
|
|
} else if(e.code === 'KeyC' && (e.ctrlKey || e.metaKey) && target.tagName !== 'INPUT') {
|
2021-09-25 14:55:58 +02:00
|
|
|
|
return;
|
2021-11-24 14:40:18 +01:00
|
|
|
|
} else if(e.altKey && (key === 'ArrowUp' || key === 'ArrowDown')) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
cancelEvent(e);
|
|
|
|
|
this.managers.dialogsStorage.getNextDialog(this.chat.peerId, key === 'ArrowDown', appDialogsManager.filterId).then((dialog) => {
|
|
|
|
|
if(dialog) {
|
|
|
|
|
this.setPeer({peerId: dialog.peerId});
|
2021-09-25 14:55:58 +02:00
|
|
|
|
}
|
2022-06-17 18:01:43 +02:00
|
|
|
|
});
|
|
|
|
|
} else if(key === 'ArrowUp' && this.chat.type !== 'scheduled') {
|
2021-09-25 14:55:58 +02:00
|
|
|
|
if(!chat.input.editMsgId && chat.input.isInputEmpty()) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.managers.appMessagesManager.getFirstMessageToEdit(chat.peerId, chat.threadId).then((message) => {
|
|
|
|
|
if(message) {
|
|
|
|
|
chat.input.initMessageEditing(message.mid);
|
2021-09-25 14:55:58 +02:00
|
|
|
|
cancelEvent(e); // * prevent from scrolling
|
|
|
|
|
}
|
2022-06-17 18:01:43 +02:00
|
|
|
|
});
|
2021-09-25 14:55:58 +02:00
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-11-24 14:40:18 +01:00
|
|
|
|
} else if(key === 'ArrowDown') {
|
2021-09-25 14:55:58 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-10-22 20:31:54 +02:00
|
|
|
|
if(
|
2022-08-04 08:49:54 +02:00
|
|
|
|
chat?.input?.messageInput &&
|
2023-03-01 13:57:50 +01:00
|
|
|
|
target !== chat.input.messageInput &&
|
2022-08-04 08:49:54 +02:00
|
|
|
|
target.tagName !== 'INPUT' &&
|
2022-11-01 18:39:23 +01:00
|
|
|
|
!target.isContentEditable &&
|
2022-08-04 08:49:54 +02:00
|
|
|
|
!IS_TOUCH_SUPPORTED &&
|
2023-01-17 20:28:27 +01:00
|
|
|
|
(!mediaSizes.isMobile || this.tabId === APP_TABS.CHAT) &&
|
2022-08-04 08:49:54 +02:00
|
|
|
|
!chat.selection.isSelecting &&
|
2023-03-01 13:57:50 +01:00
|
|
|
|
!chat.input.recording &&
|
|
|
|
|
chat.input.messageInput.isContentEditable
|
2021-10-22 20:31:54 +02:00
|
|
|
|
) {
|
2021-09-25 14:55:58 +02:00
|
|
|
|
chat.input.messageInput.focus();
|
|
|
|
|
placeCaretAtEnd(chat.input.messageInput);
|
2021-10-22 20:31:54 +02:00
|
|
|
|
|
|
|
|
|
// clone and dispatch same event to new input. it is needed for sending message if input was blurred
|
|
|
|
|
const newEvent = new KeyboardEvent(e.type, e);
|
|
|
|
|
chat.input.messageInput.dispatchEvent(newEvent);
|
2021-09-25 14:55:58 +02:00
|
|
|
|
}
|
|
|
|
|
};
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-09-25 14:55:58 +02:00
|
|
|
|
document.body.addEventListener('keydown', onKeyDown);
|
2021-08-11 21:24:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private makeLink<T extends INTERNAL_LINK_TYPE>(type: T, uriParams: Omit<InternalLinkTypeMap[T], '_'>) {
|
|
|
|
|
return {
|
|
|
|
|
_: type,
|
|
|
|
|
...uriParams
|
|
|
|
|
} as any as InternalLinkTypeMap[T];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async processInternalLink(link: InternalLink) {
|
|
|
|
|
switch(link?._) {
|
|
|
|
|
case INTERNAL_LINK_TYPE.MESSAGE: {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const postId = link.post ? generateMessageId(+link.post) : undefined;
|
|
|
|
|
const commentId = link.comment ? generateMessageId(+link.comment) : undefined;
|
2023-01-06 20:27:29 +01:00
|
|
|
|
const threadId = link.thread ? generateMessageId(+link.thread) : undefined;
|
2021-08-11 21:24:13 +02:00
|
|
|
|
|
2022-01-14 23:01:50 +01:00
|
|
|
|
this.openUsername({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
userName: link.domain,
|
|
|
|
|
lastMsgId: postId,
|
2022-01-14 23:01:50 +01:00
|
|
|
|
commentId,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
startParam: link.start,
|
|
|
|
|
stack: link.stack,
|
|
|
|
|
threadId
|
2022-01-14 23:01:50 +01:00
|
|
|
|
});
|
2021-08-11 21:24:13 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case INTERNAL_LINK_TYPE.PRIVATE_POST: {
|
2021-10-21 17:51:25 +02:00
|
|
|
|
const chatId = link.channel.toChatId();
|
|
|
|
|
const peerId = chatId.toPeerId(true);
|
2021-08-11 21:24:13 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const chat = await this.managers.appChatsManager.getChat(chatId);
|
2023-01-06 20:27:29 +01:00
|
|
|
|
if(!chat) {
|
2021-08-11 21:24:13 +02:00
|
|
|
|
try {
|
2022-04-25 16:54:30 +02:00
|
|
|
|
await this.managers.appChatsManager.resolveChannel(chatId);
|
2021-08-11 21:24:13 +02:00
|
|
|
|
} catch(err) {
|
|
|
|
|
toastNew({langPackKey: 'LinkNotFound'});
|
|
|
|
|
throw err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const postId = generateMessageId(+link.post);
|
|
|
|
|
const threadId = link.thread ? generateMessageId(+link.thread) : undefined;
|
2021-08-11 21:24:13 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
this.op({
|
|
|
|
|
peer: chat,
|
2022-01-13 00:54:33 +01:00
|
|
|
|
lastMsgId: postId,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
threadId,
|
|
|
|
|
stack: link.stack
|
2022-01-13 00:54:33 +01:00
|
|
|
|
});
|
2021-08-11 21:24:13 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 14:27:28 +02:00
|
|
|
|
case INTERNAL_LINK_TYPE.EMOJI_SET:
|
2021-08-11 21:24:13 +02:00
|
|
|
|
case INTERNAL_LINK_TYPE.STICKER_SET: {
|
2022-09-13 14:27:28 +02:00
|
|
|
|
new PopupStickers({id: link.set}, link._ === INTERNAL_LINK_TYPE.EMOJI_SET).show();
|
2021-08-11 21:24:13 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case INTERNAL_LINK_TYPE.JOIN_CHAT: {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.managers.appChatsManager.checkChatInvite(link.invite).then((chatInvite) => {
|
2021-06-29 16:21:16 +02:00
|
|
|
|
if((chatInvite as ChatInvite.chatInvitePeek).chat) {
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.managers.appChatsManager.saveApiChat((chatInvite as ChatInvite.chatInvitePeek).chat, true);
|
2021-06-29 16:21:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// console.log(chatInvite);
|
|
|
|
|
|
|
|
|
|
if(chatInvite._ === 'chatInviteAlready' ||
|
|
|
|
|
chatInvite._ === 'chatInvitePeek'/* && chatInvite.expires > tsNow(true) */) {
|
2022-01-13 00:54:33 +01:00
|
|
|
|
this.setInnerPeer({
|
|
|
|
|
peerId: chatInvite.chat.id.toPeerId(true)
|
|
|
|
|
});
|
2021-06-29 16:21:16 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
new PopupJoinChatInvite(link.invite, chatInvite);
|
2021-07-02 19:43:49 +02:00
|
|
|
|
}, (err) => {
|
|
|
|
|
if(err.type === 'INVITE_HASH_EXPIRED') {
|
|
|
|
|
toast(i18n('InviteExpired'));
|
|
|
|
|
}
|
2021-06-29 16:21:16 +02:00
|
|
|
|
});
|
2021-08-11 21:24:13 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-08-10 13:17:17 +02:00
|
|
|
|
|
2021-12-11 17:37:08 +01:00
|
|
|
|
case INTERNAL_LINK_TYPE.VOICE_CHAT: {
|
|
|
|
|
if(IS_GROUP_CALL_SUPPORTED) {
|
|
|
|
|
this.joinGroupCall(link.chat_id.toPeerId(true), link.id);
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-12-11 17:37:08 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 16:50:41 +01:00
|
|
|
|
case INTERNAL_LINK_TYPE.USER_PHONE_NUMBER: {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.managers.appUsersManager.resolvePhone(link.phone).then((user) => {
|
2022-03-25 16:50:41 +01:00
|
|
|
|
this.setInnerPeer({
|
|
|
|
|
peerId: user.id.toPeerId(false)
|
|
|
|
|
});
|
2022-06-17 18:01:43 +02:00
|
|
|
|
}).catch((err) => {
|
2022-03-25 16:50:41 +01:00
|
|
|
|
if(err.type === 'PHONE_NOT_OCCUPIED') {
|
|
|
|
|
toastNew({langPackKey: 'Alert.UserDoesntExists'});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-18 19:05:50 +02:00
|
|
|
|
case INTERNAL_LINK_TYPE.INVOICE: {
|
|
|
|
|
this.managers.appPaymentsManager.getInputInvoiceBySlug(link.slug).then((inputInvoice) => {
|
|
|
|
|
this.managers.appPaymentsManager.getPaymentForm(inputInvoice).then((paymentForm) => {
|
|
|
|
|
// const message: Message.message = {
|
|
|
|
|
// _: 'message',
|
|
|
|
|
// date: 0,
|
|
|
|
|
// id: 0,
|
|
|
|
|
// peerId: 0,
|
|
|
|
|
// peer_id: undefined,
|
|
|
|
|
// message: '',
|
|
|
|
|
// media: {
|
|
|
|
|
// _: 'messageMediaInvoice',
|
|
|
|
|
// currency: paymentForm.invoice.currency,
|
|
|
|
|
// description: paymentForm.description,
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
new PopupPayment(undefined, inputInvoice, paymentForm);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-11 21:24:13 +02:00
|
|
|
|
default: {
|
|
|
|
|
this.log.warn('Not supported internal link:', link);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-29 15:17:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-05 16:00:15 +02:00
|
|
|
|
public openUrl(url: string) {
|
2022-04-25 16:54:30 +02:00
|
|
|
|
const {url: wrappedUrl, onclick} = wrapUrl(url);
|
2022-11-18 10:43:52 +01:00
|
|
|
|
if(!onclick) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-05 16:00:15 +02:00
|
|
|
|
const a = document.createElement('a');
|
|
|
|
|
a.href = wrappedUrl;
|
|
|
|
|
(window as any)[onclick](a);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
private onHashChange = (saveState?: boolean) => {
|
2022-11-27 14:09:10 +01:00
|
|
|
|
try {
|
|
|
|
|
this.onHashChangeUnsafe(saveState);
|
|
|
|
|
} catch(err) {
|
|
|
|
|
this.log.error('hash change error', err);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private onHashChangeUnsafe = (saveState?: boolean) => {
|
2021-05-28 19:01:06 +02:00
|
|
|
|
const hash = location.hash;
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(!saveState) {
|
|
|
|
|
appNavigationController.replaceState();
|
|
|
|
|
}
|
2021-05-28 19:01:06 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const splitted = hash.split('?');
|
2022-11-18 10:43:52 +01:00
|
|
|
|
const params = parseUriParams(hash, splitted);
|
2021-03-27 16:34:08 +01:00
|
|
|
|
this.log('hashchange', hash, splitted[0], params);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(!hash) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-03-27 16:34:08 +01:00
|
|
|
|
|
2021-08-11 21:24:13 +02:00
|
|
|
|
if(params.tgaddr) {
|
2022-11-18 10:43:52 +01:00
|
|
|
|
this.openUrl(params.tgaddr);
|
2021-08-11 21:24:13 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-27 16:34:08 +01:00
|
|
|
|
switch(splitted[0]) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
default: {
|
|
|
|
|
params.p = splitted[0].slice(1);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-27 16:34:08 +01:00
|
|
|
|
case '#/im': {
|
2022-11-27 14:09:10 +01:00
|
|
|
|
if(!Object.keys(params).length) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-21 15:16:43 +02:00
|
|
|
|
const p: string = params.p;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
const postId = params.post !== undefined ? generateMessageId(+params.post) : undefined;
|
2021-03-27 16:34:08 +01:00
|
|
|
|
|
|
|
|
|
switch(p[0]) {
|
|
|
|
|
case '@': {
|
2022-01-14 23:01:50 +01:00
|
|
|
|
this.openUsername({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
userName: p,
|
2022-01-14 23:01:50 +01:00
|
|
|
|
lastMsgId: postId
|
|
|
|
|
});
|
2021-03-27 16:34:08 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default: { // peerId
|
2022-01-13 00:54:33 +01:00
|
|
|
|
this.setInnerPeer({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
peerId: postId ? p.toPeerId(true) : p.toPeerId(),
|
2022-01-13 00:54:33 +01:00
|
|
|
|
lastMsgId: postId
|
|
|
|
|
});
|
2021-03-27 16:34:08 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// appNavigationController.replaceState();
|
|
|
|
|
// location.hash = '';
|
2021-03-27 16:34:08 +01:00
|
|
|
|
};
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
private async op(options: {
|
|
|
|
|
peer: User.user | MTChat
|
|
|
|
|
} & Omit<ChatSetPeerOptions, 'peerId'>) {
|
|
|
|
|
let {peer, commentId, threadId, lastMsgId} = options;
|
|
|
|
|
const isUser = peer._ === 'user';
|
|
|
|
|
const peerId = peer.id.toPeerId(!isUser);
|
|
|
|
|
|
|
|
|
|
const isForum = peer._ === 'channel' && peer.pFlags.forum;
|
|
|
|
|
// open forum tab
|
|
|
|
|
if(!commentId && !threadId && !lastMsgId && isForum) {
|
|
|
|
|
appDialogsManager.toggleForumTabByPeerId(peerId, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-02 16:32:10 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
// handle t.me/username/thread or t.me/username/messageId
|
|
|
|
|
if(isForum && lastMsgId && !threadId) {
|
|
|
|
|
const message = await this.managers.appMessagesManager.reloadMessages(peerId, lastMsgId);
|
|
|
|
|
if(message) {
|
|
|
|
|
threadId = options.threadId = getMessageThreadId(message, isForum);
|
|
|
|
|
} else {
|
|
|
|
|
threadId = options.threadId = lastMsgId;
|
|
|
|
|
lastMsgId = options.lastMsgId = undefined;
|
2022-01-13 00:54:33 +01:00
|
|
|
|
}
|
2023-01-06 20:27:29 +01:00
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
if(threadId) {
|
|
|
|
|
return this.openThread({
|
|
|
|
|
...(options as any as Parameters<AppImManager['openThread']>[0]),
|
|
|
|
|
peerId
|
|
|
|
|
});
|
|
|
|
|
} else if(commentId) {
|
|
|
|
|
return this.openComment({
|
2022-01-13 00:54:33 +01:00
|
|
|
|
peerId,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
msgId: lastMsgId,
|
|
|
|
|
commentId
|
2022-01-13 00:54:33 +01:00
|
|
|
|
});
|
2023-01-06 20:27:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.setInnerPeer({
|
|
|
|
|
...options,
|
|
|
|
|
peerId
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 22:28:45 +01:00
|
|
|
|
public openPremiumBot() {
|
|
|
|
|
return this.managers.apiManager.getAppConfig().then((appConfig) => {
|
|
|
|
|
return this.openUsername({userName: appConfig.premium_bot_username});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
public openUsername(options: {
|
|
|
|
|
userName: string
|
|
|
|
|
} & Omit<ChatSetPeerOptions, 'peerId'>) {
|
|
|
|
|
const {userName} = options;
|
|
|
|
|
return this.managers.appUsersManager.resolveUsername(userName).then((peer) => {
|
|
|
|
|
return this.op({
|
|
|
|
|
peer,
|
|
|
|
|
...options
|
|
|
|
|
});
|
|
|
|
|
}, (err: ApiError) => {
|
2021-07-02 19:43:49 +02:00
|
|
|
|
if(err.type === 'USERNAME_NOT_OCCUPIED') {
|
2021-08-11 16:03:03 +02:00
|
|
|
|
toastNew({langPackKey: 'NoUsernameFound'});
|
|
|
|
|
} else if(err.type === 'USERNAME_INVALID') {
|
|
|
|
|
toastNew({langPackKey: 'Alert.UserDoesntExists'});
|
2021-07-02 19:43:49 +02:00
|
|
|
|
}
|
2021-04-02 16:32:10 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-10 13:17:17 +02:00
|
|
|
|
/**
|
|
|
|
|
* Opens thread when peerId of discussion group is known
|
|
|
|
|
*/
|
2023-01-06 20:27:29 +01:00
|
|
|
|
public async openThread(options: {
|
|
|
|
|
peerId: PeerId,
|
|
|
|
|
lastMsgId: number,
|
|
|
|
|
threadId: number,
|
|
|
|
|
stack?: number
|
|
|
|
|
}) {
|
|
|
|
|
if(await this.managers.appChatsManager.isForum(options.peerId.toChatId())) {
|
|
|
|
|
await this.managers.dialogsStorage.getForumTopicOrReload(options.peerId, options.threadId);
|
|
|
|
|
return this.setInnerPeer(options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.managers.appMessagesManager.reloadMessages(options.peerId, options.threadId).then((message) => {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(!message) {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
options.lastMsgId = undefined;
|
2022-01-13 00:54:33 +01:00
|
|
|
|
} else {
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.managers.appMessagesManager.generateThreadServiceStartMessage(message);
|
2022-01-13 00:54:33 +01:00
|
|
|
|
}
|
2021-08-10 13:17:17 +02:00
|
|
|
|
|
2022-01-13 00:54:33 +01:00
|
|
|
|
return this.setInnerPeer({
|
2023-01-06 20:27:29 +01:00
|
|
|
|
...options,
|
2022-01-13 00:54:33 +01:00
|
|
|
|
type: 'discussion'
|
|
|
|
|
});
|
2021-08-10 13:17:17 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Opens comment directly from original channel
|
|
|
|
|
*/
|
2023-01-06 20:27:29 +01:00
|
|
|
|
public openComment(options: {
|
|
|
|
|
peerId: PeerId,
|
|
|
|
|
msgId: number,
|
|
|
|
|
commentId: number
|
|
|
|
|
}) {
|
|
|
|
|
return this.managers.appMessagesManager.getDiscussionMessage(options.peerId, options.msgId).then((message) => {
|
|
|
|
|
return this.openThread({
|
|
|
|
|
peerId: message.peerId,
|
|
|
|
|
lastMsgId: options.commentId,
|
|
|
|
|
threadId: message.mid
|
|
|
|
|
});
|
2021-08-10 13:17:17 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-08 13:52:14 +01:00
|
|
|
|
public async callUser(userId: UserId, type: CallType) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const call = callsController.getCallByUserId(userId);
|
2022-01-08 13:52:14 +01:00
|
|
|
|
if(call) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-04-25 16:54:30 +02:00
|
|
|
|
const userFull = await this.managers.appProfileManager.getProfile(userId);
|
2022-01-08 13:52:14 +01:00
|
|
|
|
if(userFull.pFlags.phone_calls_private) {
|
2022-11-01 18:39:23 +01:00
|
|
|
|
wrapPeerTitle({peerId: userId.toPeerId()}).then((element) => {
|
|
|
|
|
return confirmationPopup({
|
|
|
|
|
descriptionLangKey: 'Call.PrivacyErrorMessage',
|
|
|
|
|
descriptionLangArgs: [element],
|
|
|
|
|
button: {
|
|
|
|
|
langKey: 'OK',
|
|
|
|
|
isCancel: true
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-01-08 13:52:14 +01:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await this.discardCurrentCall(userId.toPeerId());
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
callsController.startCallInternal(userId, type === 'video');
|
2022-01-08 13:52:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-24 15:16:41 +01:00
|
|
|
|
private discardCurrentCall(toPeerId: PeerId, ignoreGroupCall?: GroupCallInstance, ignoreCall?: CallInstance) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(groupCallsController.groupCall && groupCallsController.groupCall !== ignoreGroupCall) return this.discardGroupCallConfirmation(toPeerId);
|
|
|
|
|
else if(callsController.currentCall && callsController.currentCall !== ignoreCall) return this.discardCallConfirmation(toPeerId);
|
2022-03-23 16:15:07 +01:00
|
|
|
|
else return Promise.resolve();
|
2022-01-08 13:52:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async discardCallConfirmation(toPeerId: PeerId) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const currentCall = callsController.currentCall;
|
2022-01-08 13:52:14 +01:00
|
|
|
|
if(currentCall) {
|
2022-11-01 18:39:23 +01:00
|
|
|
|
await Promise.all([
|
|
|
|
|
wrapPeerTitle({peerId: currentCall.interlocutorUserId.toPeerId(false)}),
|
|
|
|
|
wrapPeerTitle({peerId: toPeerId})
|
|
|
|
|
]).then(([title1, title2]) => {
|
|
|
|
|
return confirmationPopup({
|
|
|
|
|
titleLangKey: 'Call.Confirm.Discard.Call.Header',
|
|
|
|
|
descriptionLangKey: toPeerId.isUser() ? 'Call.Confirm.Discard.Call.ToCall.Text' : 'Call.Confirm.Discard.Call.ToVoice.Text',
|
|
|
|
|
descriptionLangArgs: [title1, title2],
|
|
|
|
|
button: {
|
|
|
|
|
langKey: 'OK'
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-01-08 13:52:14 +01:00
|
|
|
|
});
|
|
|
|
|
|
2022-03-24 15:16:41 +01:00
|
|
|
|
if(!currentCall.isClosing) {
|
|
|
|
|
await currentCall.hangUp('phoneCallDiscardReasonDisconnect');
|
2022-01-08 13:52:14 +01:00
|
|
|
|
}
|
2022-03-23 16:15:07 +01:00
|
|
|
|
}
|
2022-01-08 13:52:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async discardGroupCallConfirmation(toPeerId: PeerId) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const currentGroupCall = groupCallsController.groupCall;
|
2022-01-08 13:52:14 +01:00
|
|
|
|
if(currentGroupCall) {
|
2022-11-01 18:39:23 +01:00
|
|
|
|
await Promise.all([
|
|
|
|
|
wrapPeerTitle({peerId: currentGroupCall.chatId.toPeerId(true)}),
|
|
|
|
|
wrapPeerTitle({peerId: toPeerId})
|
|
|
|
|
]).then(([title1, title2]) => {
|
|
|
|
|
return confirmationPopup({
|
|
|
|
|
titleLangKey: 'Call.Confirm.Discard.Voice.Header',
|
|
|
|
|
descriptionLangKey: toPeerId.isUser() ? 'Call.Confirm.Discard.Voice.ToCall.Text' : 'Call.Confirm.Discard.Voice.ToVoice.Text',
|
|
|
|
|
descriptionLangArgs: [title1, title2],
|
|
|
|
|
button: {
|
|
|
|
|
langKey: 'OK'
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-01-08 13:52:14 +01:00
|
|
|
|
});
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(groupCallsController.groupCall === currentGroupCall) {
|
2022-01-08 13:52:14 +01:00
|
|
|
|
await currentGroupCall.hangUp();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-11 17:37:08 +01:00
|
|
|
|
public async joinGroupCall(peerId: PeerId, groupCallId?: GroupCallId) {
|
|
|
|
|
const chatId = peerId.toChatId();
|
2022-04-25 16:54:30 +02:00
|
|
|
|
const hasRights = this.managers.appChatsManager.hasRights(chatId, 'manage_call');
|
2021-12-11 17:37:08 +01:00
|
|
|
|
const next = async() => {
|
2022-04-25 16:54:30 +02:00
|
|
|
|
const chatFull = await this.managers.appProfileManager.getChatFull(chatId);
|
2021-12-11 17:37:08 +01:00
|
|
|
|
let call: MyGroupCall;
|
|
|
|
|
if(!chatFull.call) {
|
|
|
|
|
if(!hasRights) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-04-25 16:54:30 +02:00
|
|
|
|
call = await this.managers.appGroupCallsManager.createGroupCall(chatId);
|
2021-12-11 17:37:08 +01:00
|
|
|
|
} else {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
call = chatFull.call;
|
2021-12-11 17:37:08 +01:00
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
groupCallsController.joinGroupCall(chatId, call.id, true, false);
|
2021-12-11 17:37:08 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(groupCallId) {
|
2022-04-25 16:54:30 +02:00
|
|
|
|
const groupCall = await this.managers.appGroupCallsManager.getGroupCallFull(groupCallId);
|
2021-12-11 17:37:08 +01:00
|
|
|
|
if(groupCall._ === 'groupCallDiscarded') {
|
|
|
|
|
if(!hasRights) {
|
|
|
|
|
toastNew({
|
|
|
|
|
langPackKey: 'VoiceChat.Chat.Ended'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await confirmationPopup({
|
|
|
|
|
descriptionLangKey: 'VoiceChat.Chat.StartNew',
|
|
|
|
|
button: {
|
|
|
|
|
langKey: 'VoiceChat.Chat.StartNew.OK'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
// await this.discardCurrentCall(peerId);
|
2021-12-11 17:37:08 +01:00
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-17 14:59:55 +02:00
|
|
|
|
public setCurrentBackground(broadcastEvent = false): ReturnType<AppImManager['setBackground']> {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const theme = themeController.getTheme();
|
2021-04-19 17:30:51 +02:00
|
|
|
|
|
2023-01-25 15:21:38 +01:00
|
|
|
|
const slug = (theme.settings?.wallpaper as WallPaper.wallPaper)?.slug;
|
|
|
|
|
if(slug) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const defaultTheme = STATE_INIT.settings.themes.find((t) => t.name === theme.name);
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// const isDefaultBackground = theme.background.blur === defaultTheme.background.blur &&
|
2023-01-25 15:21:38 +01:00
|
|
|
|
// slug === defaultslug;
|
2021-04-19 17:30:51 +02:00
|
|
|
|
|
2022-03-13 21:51:16 +01:00
|
|
|
|
// if(!isDefaultBackground) {
|
2023-01-25 15:21:38 +01:00
|
|
|
|
return this.getBackground(slug).then((url) => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
return this.setBackground(url, broadcastEvent);
|
|
|
|
|
}, () => { // * if NO_ENTRY_FOUND
|
2023-01-25 15:21:38 +01:00
|
|
|
|
theme.settings = copy(defaultTheme.settings); // * reset background
|
2022-08-04 08:49:54 +02:00
|
|
|
|
return this.setCurrentBackground(true);
|
|
|
|
|
});
|
2022-03-13 21:51:16 +01:00
|
|
|
|
// }
|
2021-04-19 12:36:14 +02:00
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-04-19 17:30:51 +02:00
|
|
|
|
return this.setBackground('', broadcastEvent);
|
2021-04-19 12:36:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getBackground(slug: string) {
|
|
|
|
|
if(this.backgroundPromises[slug]) return this.backgroundPromises[slug];
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return this.backgroundPromises[slug] = this.cacheStorage.getFile('backgrounds/' + slug).then((blob) => {
|
2021-04-19 12:36:14 +02:00
|
|
|
|
return URL.createObjectURL(blob);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-31 02:52:14 +01:00
|
|
|
|
public setBackground(url: string, broadcastEvent = true): Promise<void> {
|
2022-03-13 21:51:16 +01:00
|
|
|
|
this.lastBackgroundUrl = url;
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const promises = this.chats.map((chat) => chat.setBackground(url));
|
2021-01-31 02:52:14 +01:00
|
|
|
|
return promises[promises.length - 1].then(() => {
|
|
|
|
|
if(broadcastEvent) {
|
2021-06-11 14:52:53 +02:00
|
|
|
|
rootScope.dispatchEvent('background_change');
|
2021-01-31 02:52:14 +01:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-13 18:19:52 +02:00
|
|
|
|
public saveChatPosition(chat: Chat) {
|
|
|
|
|
if(!(['chat', 'discussion'] as ChatType[]).includes(chat.type) || !chat.peerId) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// const bubble = chat.bubbles.getBubbleByPoint('top');
|
|
|
|
|
// if(bubble) {
|
|
|
|
|
// const top = bubble.getBoundingClientRect().top;
|
|
|
|
|
const chatBubbles = chat.bubbles;
|
|
|
|
|
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
|
|
|
|
const chatPositions = stateStorage.getFromCache('chatPositions');
|
|
|
|
|
if(!(chatBubbles.scrollable.getDistanceToEnd() <= 16 && chatBubbles.scrollable.loadedAll.bottom) && chatBubbles.getRenderedLength()) {
|
|
|
|
|
chatBubbles.sliceViewport(true);
|
|
|
|
|
const top = chatBubbles.scrollable.scrollTop;
|
|
|
|
|
|
|
|
|
|
const position = {
|
2022-11-27 14:09:10 +01:00
|
|
|
|
mids: getObjectKeysAndSort(chatBubbles.bubbles, 'desc').filter((mid) => mid > 0 && !chatBubbles.skippedMids.has(mid)),
|
2022-08-04 08:49:54 +02:00
|
|
|
|
top
|
|
|
|
|
};
|
2021-04-13 18:19:52 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
chatPositions[key] = position;
|
2021-04-13 21:29:33 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
this.log('saved chat position:', position);
|
|
|
|
|
} else {
|
|
|
|
|
delete chatPositions[key];
|
2021-04-13 21:29:33 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
this.log('deleted chat position');
|
|
|
|
|
}
|
2021-04-13 18:19:52 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
stateStorage.set({chatPositions}, true);
|
|
|
|
|
// }
|
2021-01-26 01:40:53 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-13 18:19:52 +02:00
|
|
|
|
public getChatSavedPosition(chat: Chat): ChatSavedPosition {
|
2021-04-13 20:48:46 +02:00
|
|
|
|
if(!(['chat', 'discussion'] as ChatType[]).includes(chat.type) || !chat.peerId) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-01-26 01:40:53 +01:00
|
|
|
|
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
2021-06-06 16:22:29 +02:00
|
|
|
|
const cache = stateStorage.getFromCache('chatPositions');
|
2021-04-20 20:00:38 +02:00
|
|
|
|
return cache && cache[key];
|
2021-04-13 18:19:52 +02:00
|
|
|
|
}
|
2021-01-26 01:40:53 +01:00
|
|
|
|
|
2021-04-22 18:58:31 +02:00
|
|
|
|
public applyCurrentTheme(slug?: string, backgroundUrl?: string, broadcastEvent?: boolean) {
|
2021-04-19 12:36:14 +02:00
|
|
|
|
if(backgroundUrl) {
|
|
|
|
|
this.backgroundPromises[slug] = Promise.resolve(backgroundUrl);
|
|
|
|
|
}
|
2022-06-17 18:01:43 +02:00
|
|
|
|
|
|
|
|
|
themeController.setTheme();
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-04-22 18:58:31 +02:00
|
|
|
|
return this.setCurrentBackground(broadcastEvent === undefined ? !!slug : broadcastEvent);
|
2021-04-19 12:36:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private setSettings = () => {
|
2022-11-07 15:25:27 +01:00
|
|
|
|
const {messagesTextSize} = rootScope.settings;
|
|
|
|
|
|
|
|
|
|
this.customEmojiSize = makeMediaSize(messagesTextSize + 4, messagesTextSize + 4);
|
|
|
|
|
document.documentElement.style.setProperty('--messages-text-size', messagesTextSize + 'px');
|
|
|
|
|
|
|
|
|
|
const firstTime = !this.customEmojiSize;
|
|
|
|
|
if(!firstTime) {
|
|
|
|
|
const ellipsisElements = document.querySelectorAll<MiddleEllipsisElement>('middle-ellipsis-element');
|
|
|
|
|
ellipsisElements.forEach((element) => {
|
|
|
|
|
element.disconnectedCallback();
|
|
|
|
|
element.dataset.fontSize = '' + messagesTextSize;
|
|
|
|
|
if(element.title) element.textContent = element.title;
|
|
|
|
|
element.connectedCallback();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const renderers = document.querySelectorAll<CustomEmojiRendererElement>('.chat custom-emoji-renderer-element');
|
|
|
|
|
renderers.forEach((renderer) => {
|
|
|
|
|
renderer.forceRenderAfterSize = true;
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-01-03 16:59:13 +01:00
|
|
|
|
document.body.classList.toggle('animation-level-0', !rootScope.settings.animationsEnabled);
|
|
|
|
|
document.body.classList.toggle('animation-level-1', false);
|
|
|
|
|
document.body.classList.toggle('animation-level-2', rootScope.settings.animationsEnabled);
|
|
|
|
|
|
|
|
|
|
this.chatsSelectTabDebounced = debounce(() => {
|
|
|
|
|
const topbar = this.chat.topbar;
|
2023-01-06 20:27:29 +01:00
|
|
|
|
topbar.pinnedMessage?.setCorrectIndex(0); // * буду молиться богам, чтобы это ничего не сломало, но это исправляет получение пиннеда после анимации
|
2021-01-03 16:59:13 +01:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.managers.apiFileManager.setQueueId(this.chat.bubbles.lazyLoadQueue.queueId);
|
2021-01-03 16:59:13 +01:00
|
|
|
|
}, rootScope.settings.animationsEnabled ? 250 : 0, false, true);
|
2021-01-04 11:09:48 +01:00
|
|
|
|
|
2023-01-28 12:52:24 +01:00
|
|
|
|
if(lottieLoader.setLoop(rootScope.settings.stickers.loop)) {
|
|
|
|
|
animationIntersector.checkAnimations2(false);
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-03-13 11:12:24 +01:00
|
|
|
|
for(const chat of this.chats) {
|
|
|
|
|
chat.setAutoDownloadMedia();
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-11-13 02:30:37 +01:00
|
|
|
|
I18n.setTimeFormat(rootScope.settings.timeFormat);
|
2022-03-13 21:51:16 +01:00
|
|
|
|
|
|
|
|
|
this.toggleChatGradientAnimation(this.chat);
|
2021-03-13 11:12:24 +01:00
|
|
|
|
};
|
2020-06-13 10:19:39 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// * не могу использовать тут TransitionSlider, так как мне нужен отрисованный блок рядом
|
2021-01-18 19:34:41 +01:00
|
|
|
|
// * (или под текущим чатом) чтобы правильно отрендерить чат (напр. scrollTop)
|
2021-02-16 16:36:26 +01:00
|
|
|
|
private chatsSelectTab(tab: HTMLElement, animate?: boolean) {
|
2020-12-21 04:11:26 +01:00
|
|
|
|
if(this.prevTab === tab) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-16 16:36:26 +01:00
|
|
|
|
if(animate === false && this.prevTab) { // * will be used for Safari iOS history swipe
|
|
|
|
|
disableTransition([tab, this.prevTab].filter(Boolean));
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-21 04:11:26 +01:00
|
|
|
|
if(this.prevTab) {
|
|
|
|
|
this.prevTab.classList.remove('active');
|
|
|
|
|
this.chatsSelectTabDebounced();
|
2021-01-18 19:34:41 +01:00
|
|
|
|
|
2021-02-16 16:36:26 +01:00
|
|
|
|
// ! нужно переделать на animation, так как при лаге анимация будет длиться не 250мс
|
2022-08-04 08:49:54 +02:00
|
|
|
|
if(rootScope.settings.animationsEnabled && animate !== false) {
|
2021-02-07 04:35:29 +01:00
|
|
|
|
dispatchHeavyAnimationEvent(pause(250 + 150), 250 + 150);
|
2021-01-18 19:34:41 +01:00
|
|
|
|
}
|
2021-02-16 16:36:26 +01:00
|
|
|
|
|
|
|
|
|
const prevIdx = whichChild(this.prevTab);
|
|
|
|
|
const idx = whichChild(tab);
|
|
|
|
|
if(idx > prevIdx) {
|
|
|
|
|
appNavigationController.pushItem({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
type: 'chat',
|
2021-02-16 16:36:26 +01:00
|
|
|
|
onPop: (canAnimate) => {
|
2022-01-13 00:54:33 +01:00
|
|
|
|
this.setPeer({}, canAnimate);
|
2021-02-16 16:36:26 +01:00
|
|
|
|
blurActiveElement();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-12-21 04:11:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tab.classList.add('active');
|
|
|
|
|
this.prevTab = tab;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
private init() {
|
|
|
|
|
document.addEventListener('paste', this.onDocumentPaste, true);
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2021-09-26 15:59:10 +02:00
|
|
|
|
if(!IS_TOUCH_SUPPORTED) {
|
2020-12-12 01:52:11 +01:00
|
|
|
|
this.attachDragAndDropListeners();
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// if(!isTouchSupported) {
|
|
|
|
|
this.markupTooltip = new MarkupTooltip(this);
|
|
|
|
|
this.markupTooltip.handleSelection();
|
|
|
|
|
// }
|
2020-12-01 16:38:36 +01:00
|
|
|
|
}
|
2020-05-03 14:46:05 +02:00
|
|
|
|
|
2020-12-12 01:52:11 +01:00
|
|
|
|
private attachDragAndDropListeners() {
|
|
|
|
|
const drops: ChatDragAndDrop[] = [];
|
2021-11-26 10:58:12 +01:00
|
|
|
|
const mediaDrops: ChatDragAndDrop[] = [];
|
2020-12-12 01:52:11 +01:00
|
|
|
|
let mounted = false;
|
|
|
|
|
const toggle = async(e: DragEvent, mount: boolean) => {
|
2021-02-03 05:36:59 +01:00
|
|
|
|
if(mount === mounted) return;
|
2020-12-12 01:52:11 +01:00
|
|
|
|
|
2020-12-12 02:04:58 +01:00
|
|
|
|
const _types = e.dataTransfer.types;
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
const isFiles = _types.contains ? _types.contains('Files') : _types.indexOf('Files') >= 0;
|
|
|
|
|
|
2021-11-26 10:58:12 +01:00
|
|
|
|
const newMediaPopup = getCurrentNewMediaPopup();
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const types: string[] = await getFilesFromEvent(e, true);
|
|
|
|
|
if(!isFiles || (!(await this.canDrag()) && !newMediaPopup)) { // * skip dragging text case
|
2020-12-12 02:04:58 +01:00
|
|
|
|
counter = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-27 14:11:37 +01:00
|
|
|
|
const rights = await PopupNewMedia.canSend(this.chat.peerId, true);
|
|
|
|
|
|
2021-11-26 10:58:12 +01:00
|
|
|
|
const _dropsContainer = newMediaPopup ? mediaDropsContainer : dropsContainer;
|
|
|
|
|
const _drops = newMediaPopup ? mediaDrops : drops;
|
|
|
|
|
|
|
|
|
|
if(mount && !_drops.length) {
|
2020-12-12 02:04:58 +01:00
|
|
|
|
const force = isFiles && !types.length; // * can't get file items not from 'drop' on Safari
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2023-02-27 14:11:37 +01:00
|
|
|
|
const [foundMedia, foundDocuments] = partition(types, (t) => MEDIA_MIME_TYPES_SUPPORTED.has(t));
|
|
|
|
|
const [foundPhotos, foundVideos] = partition(foundMedia, (t) => IMAGE_MIME_TYPES_SUPPORTED.has(t));
|
|
|
|
|
|
|
|
|
|
if(!rights.send_docs) {
|
|
|
|
|
foundDocuments.length = 0;
|
|
|
|
|
} else {
|
|
|
|
|
foundDocuments.push(...foundMedia);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!rights.send_photos) {
|
|
|
|
|
foundPhotos.forEach((mimeType) => indexOfAndSplice(foundMedia, mimeType));
|
|
|
|
|
foundPhotos.length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!rights.send_videos) {
|
|
|
|
|
foundVideos.forEach((mimeType) => indexOfAndSplice(foundMedia, mimeType));
|
|
|
|
|
foundVideos.length = 0;
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2023-02-27 14:11:37 +01:00
|
|
|
|
this.log('drag files', types, foundMedia, foundDocuments, foundPhotos, foundVideos);
|
2021-11-26 10:58:12 +01:00
|
|
|
|
|
|
|
|
|
if(newMediaPopup) {
|
|
|
|
|
newMediaPopup.appendDrops(_dropsContainer);
|
|
|
|
|
|
2023-02-27 14:11:37 +01:00
|
|
|
|
const length = (rights.send_docs ? [foundDocuments] : [foundPhotos, foundVideos]).reduce((acc, v) => acc + v.length, 0);
|
|
|
|
|
if(length || force) {
|
2021-11-26 10:58:12 +01:00
|
|
|
|
_drops.push(new ChatDragAndDrop(_dropsContainer, {
|
|
|
|
|
header: 'Preview.Dragging.AddItems',
|
2023-02-27 14:11:37 +01:00
|
|
|
|
headerArgs: [length],
|
2021-11-26 10:58:12 +01:00
|
|
|
|
onDrop: (e: DragEvent) => {
|
|
|
|
|
toggle(e, false);
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.log('drop', e);
|
|
|
|
|
this.onDocumentPaste(e, 'document');
|
2021-11-26 10:58:12 +01:00
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-02-27 14:11:37 +01:00
|
|
|
|
if(foundDocuments.length || force) {
|
2021-11-26 10:58:12 +01:00
|
|
|
|
_drops.push(new ChatDragAndDrop(_dropsContainer, {
|
|
|
|
|
icon: 'dragfiles',
|
|
|
|
|
header: 'Chat.DropTitle',
|
|
|
|
|
subtitle: 'Chat.DropAsFilesDesc',
|
|
|
|
|
onDrop: (e: DragEvent) => {
|
|
|
|
|
toggle(e, false);
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.log('drop', e);
|
|
|
|
|
this.onDocumentPaste(e, 'document');
|
2021-11-26 10:58:12 +01:00
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2023-02-27 14:11:37 +01:00
|
|
|
|
if(foundMedia.length || force) {
|
2021-11-26 10:58:12 +01:00
|
|
|
|
_drops.push(new ChatDragAndDrop(_dropsContainer, {
|
|
|
|
|
icon: 'dragmedia',
|
|
|
|
|
header: 'Chat.DropTitle',
|
|
|
|
|
subtitle: 'Chat.DropQuickDesc',
|
|
|
|
|
onDrop: (e: DragEvent) => {
|
|
|
|
|
toggle(e, false);
|
2022-04-25 16:54:30 +02:00
|
|
|
|
this.log('drop', e);
|
|
|
|
|
this.onDocumentPaste(e, 'media');
|
2021-11-26 10:58:12 +01:00
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.chat.container.append(_dropsContainer);
|
2020-12-12 01:52:11 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// if(!mount) return;
|
2020-12-12 01:52:11 +01:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
SetTransition({
|
|
|
|
|
element: _dropsContainer,
|
|
|
|
|
className: 'is-visible',
|
|
|
|
|
forwards: mount,
|
|
|
|
|
duration: 200,
|
|
|
|
|
onTransitionEnd: () => {
|
|
|
|
|
if(!mount) {
|
|
|
|
|
_drops.forEach((drop) => {
|
|
|
|
|
drop.destroy();
|
|
|
|
|
});
|
2020-12-12 01:52:11 +01:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
_drops.length = 0;
|
|
|
|
|
}
|
2020-12-12 01:52:11 +01:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(mount) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
_drops.forEach((drop) => {
|
2020-12-12 01:52:11 +01:00
|
|
|
|
drop.setPath();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
counter = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.body.classList.toggle('is-dragging', mount);
|
|
|
|
|
mounted = mount;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* document.body.addEventListener('dragover', (e) => {
|
|
|
|
|
cancelEvent(e);
|
|
|
|
|
}); */
|
|
|
|
|
|
|
|
|
|
let counter = 0;
|
|
|
|
|
document.body.addEventListener('dragenter', (e) => {
|
|
|
|
|
counter++;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.body.addEventListener('dragover', (e) => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// this.log('dragover', e/* , e.dataTransfer.types[0] */);
|
2020-12-12 01:52:11 +01:00
|
|
|
|
toggle(e, true);
|
|
|
|
|
cancelEvent(e);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.body.addEventListener('dragleave', (e) => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// this.log('dragleave', e, counter);
|
|
|
|
|
// if((e.pageX <= 0 || e.pageX >= this.managers.appPhotosManager.windowW) || (e.pageY <= 0 || e.pageY >= this.managers.appPhotosManager.windowH)) {
|
2020-12-12 01:52:11 +01:00
|
|
|
|
counter--;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
if(counter === 0) {
|
|
|
|
|
// if(!findUpClassName(e.target, 'drops-container')) {
|
2020-12-12 01:52:11 +01:00
|
|
|
|
toggle(e, false);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const dropsContainer = document.createElement('div');
|
|
|
|
|
dropsContainer.classList.add('drops-container');
|
2021-11-26 10:58:12 +01:00
|
|
|
|
|
|
|
|
|
const mediaDropsContainer = dropsContainer.cloneNode(true) as HTMLElement;
|
2020-12-12 01:52:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
private async canDrag() {
|
2022-01-12 19:17:34 +01:00
|
|
|
|
const chat = this.chat;
|
|
|
|
|
const peerId = chat?.peerId;
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return !(!peerId || overlayCounter.isOverlayActive || !(await chat.canSend('send_media')));
|
2020-12-12 16:06:19 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
private onDocumentPaste = async(e: ClipboardEvent | DragEvent, attachType?: 'media' | 'document') => {
|
2021-11-26 10:58:12 +01:00
|
|
|
|
const newMediaPopup = getCurrentNewMediaPopup();
|
2020-08-19 14:29:10 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// console.log('document paste');
|
|
|
|
|
// console.log('item', event.clipboardData.getData());
|
2020-12-12 01:52:11 +01:00
|
|
|
|
|
2020-12-13 03:32:55 +01:00
|
|
|
|
if(e instanceof DragEvent) {
|
|
|
|
|
const _types = e.dataTransfer.types;
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
const isFiles = _types.contains ? _types.contains('Files') : _types.indexOf('Files') >= 0;
|
|
|
|
|
if(isFiles) {
|
|
|
|
|
cancelEvent(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const files = await getFilesFromEvent(e);
|
|
|
|
|
if(!(await this.canDrag()) && !newMediaPopup) return;
|
|
|
|
|
if(files.length) {
|
|
|
|
|
if(newMediaPopup) {
|
|
|
|
|
newMediaPopup.addFiles(files);
|
|
|
|
|
return;
|
2020-05-03 14:46:05 +02:00
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const chatInput = this.chat.input;
|
|
|
|
|
chatInput.willAttachType = attachType || (MEDIA_MIME_TYPES_SUPPORTED.has(files[0].type) ? 'media' : 'document');
|
|
|
|
|
PopupElement.createPopup(PopupNewMedia, this.chat, files, chatInput.willAttachType);
|
|
|
|
|
}
|
2020-11-23 17:45:50 +01:00
|
|
|
|
};
|
|
|
|
|
|
2022-07-26 07:43:27 +02:00
|
|
|
|
private async overrideHash(peerId?: PeerId) {
|
|
|
|
|
let str: string;
|
|
|
|
|
if(peerId) {
|
|
|
|
|
const username = await this.managers.appPeersManager.getPeerUsername(peerId);
|
|
|
|
|
str = username ? '@' + username : '' + peerId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
appNavigationController.overrideHash(str);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 20:28:27 +01:00
|
|
|
|
public selectTab(id: APP_TABS, animate?: boolean) {
|
2021-02-16 16:36:26 +01:00
|
|
|
|
if(animate === false) { // * will be used for Safari iOS history swipe
|
|
|
|
|
disableTransition([appSidebarLeft.sidebarEl, this.columnEl, appSidebarRight.sidebarEl]);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 20:28:27 +01:00
|
|
|
|
document.body.classList.toggle(LEFT_COLUMN_ACTIVE_CLASSNAME, id === APP_TABS.CHATLIST);
|
2020-09-26 00:47:43 +02:00
|
|
|
|
|
2020-12-11 03:06:16 +01:00
|
|
|
|
const prevTabId = this.tabId;
|
2023-01-17 20:28:27 +01:00
|
|
|
|
if(prevTabId !== undefined) {
|
|
|
|
|
this.overrideHash(id > APP_TABS.CHATLIST ? this.chat?.peerId : undefined);
|
|
|
|
|
this.dispatchEvent('tab_changing', id);
|
2022-07-26 07:47:28 +02:00
|
|
|
|
}
|
2021-01-18 19:34:41 +01:00
|
|
|
|
|
|
|
|
|
this.log('selectTab', id, prevTabId);
|
|
|
|
|
|
2021-09-25 14:18:12 +02:00
|
|
|
|
let animationPromise: Promise<any> = rootScope.settings.animationsEnabled ? doubleRaf() : Promise.resolve();
|
2023-01-06 20:27:29 +01:00
|
|
|
|
if(
|
2023-01-17 20:28:27 +01:00
|
|
|
|
prevTabId !== undefined &&
|
2023-01-06 20:27:29 +01:00
|
|
|
|
prevTabId !== id &&
|
|
|
|
|
rootScope.settings.animationsEnabled &&
|
|
|
|
|
animate !== false/* &&
|
|
|
|
|
mediaSizes.activeScreen !== ScreenSize.large */
|
|
|
|
|
) {
|
2021-02-07 04:35:29 +01:00
|
|
|
|
const transitionTime = (mediaSizes.isMobile ? 250 : 200) + 100; // * cause transition time could be > 250ms
|
2021-02-16 16:36:26 +01:00
|
|
|
|
animationPromise = pause(transitionTime);
|
|
|
|
|
dispatchHeavyAnimationEvent(animationPromise, transitionTime);
|
2021-02-15 16:49:58 +01:00
|
|
|
|
|
2021-09-25 14:18:12 +02:00
|
|
|
|
// ! it's very heavy operation. will blink in firefox
|
|
|
|
|
/* this.columnEl.classList.add('disable-hover');
|
2021-02-16 16:36:26 +01:00
|
|
|
|
animationPromise.finally(() => {
|
2021-02-15 16:49:58 +01:00
|
|
|
|
this.columnEl.classList.remove('disable-hover');
|
2021-09-25 14:18:12 +02:00
|
|
|
|
}); */
|
2021-01-18 19:34:41 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 03:06:16 +01:00
|
|
|
|
this.tabId = id;
|
2021-05-13 02:44:31 +02:00
|
|
|
|
blurActiveElement();
|
2023-01-17 20:28:27 +01:00
|
|
|
|
if(mediaSizes.isMobile && prevTabId === APP_TABS.PROFILE && id < APP_TABS.PROFILE) {
|
2020-10-16 17:16:05 +02:00
|
|
|
|
document.body.classList.remove(RIGHT_COLUMN_ACTIVE_CLASSNAME);
|
|
|
|
|
}
|
2020-10-16 18:53:57 +02:00
|
|
|
|
|
2023-01-17 20:28:27 +01:00
|
|
|
|
if(prevTabId !== undefined && id > prevTabId) {
|
|
|
|
|
if(id < APP_TABS.PROFILE || !appNavigationController.findItemByType('im')) {
|
2021-03-10 15:08:28 +01:00
|
|
|
|
appNavigationController.pushItem({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
type: 'im',
|
2021-03-10 15:08:28 +01:00
|
|
|
|
onPop: (canAnimate) => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// this.selectTab(prevTabId, !isSafari);
|
2022-01-13 00:54:33 +01:00
|
|
|
|
this.setPeer({}, canAnimate);
|
2021-03-10 15:08:28 +01:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-02-16 16:36:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 19:23:12 +02:00
|
|
|
|
const onImTabChange = (window as any).onImTabChange;
|
|
|
|
|
onImTabChange && onImTabChange(id);
|
2021-01-25 20:06:44 +01:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// this._selectTab(id, mediaSizes.isMobile);
|
|
|
|
|
// document.body.classList.toggle(RIGHT_COLUMN_ACTIVE_CLASSNAME, id === 2);
|
2021-02-16 16:36:26 +01:00
|
|
|
|
|
|
|
|
|
return animationPromise;
|
2020-09-26 00:47:43 +02:00
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2020-02-06 16:43:07 +01:00
|
|
|
|
public updateStatus() {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return this.managers.appUsersManager.updateMyOnlineStatus(this.offline);
|
2020-02-06 16:43:07 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
private createNewChat() {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const chat = new Chat(
|
2022-08-04 08:49:54 +02:00
|
|
|
|
this,
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.managers
|
2021-05-18 16:17:54 +02:00
|
|
|
|
);
|
2020-05-01 23:28:40 +02:00
|
|
|
|
|
2021-01-31 02:52:14 +01:00
|
|
|
|
if(this.chats.length) {
|
2022-03-13 21:51:16 +01:00
|
|
|
|
chat.setBackground(this.lastBackgroundUrl, true);
|
2021-01-31 02:52:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
this.chats.push(chat);
|
2022-01-08 13:52:14 +01:00
|
|
|
|
|
|
|
|
|
return chat;
|
2020-05-01 23:28:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-27 16:34:08 +01:00
|
|
|
|
private spliceChats(fromIndex: number, justReturn = true, animate?: boolean, spliced?: Chat[]) {
|
2020-12-01 16:38:36 +01:00
|
|
|
|
if(fromIndex >= this.chats.length) return;
|
2020-11-09 20:57:06 +01:00
|
|
|
|
|
2022-01-08 13:52:14 +01:00
|
|
|
|
const chatFrom = this.chat;
|
2021-01-09 15:08:26 +01:00
|
|
|
|
if(this.chats.length > 1 && justReturn) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.dispatchEvent('peer_changing', this.chat);
|
2021-01-09 15:08:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-27 16:34:08 +01:00
|
|
|
|
if(!spliced) {
|
|
|
|
|
spliced = this.chats.splice(fromIndex, this.chats.length - fromIndex);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const chatTo = this.chat;
|
|
|
|
|
this.dispatchEvent('chat_changing', {from: chatFrom, to: chatTo});
|
2022-01-08 13:52:14 +01:00
|
|
|
|
|
2021-04-05 18:11:15 +02:00
|
|
|
|
// * -1 because one item is being sliced when closing the chat by calling .removeByType
|
|
|
|
|
for(let i = 0; i < spliced.length - 1; ++i) {
|
2021-03-27 16:34:08 +01:00
|
|
|
|
appNavigationController.removeByType('chat', true);
|
|
|
|
|
}
|
2020-04-08 17:46:43 +02:00
|
|
|
|
|
2020-12-23 23:03:34 +01:00
|
|
|
|
// * fix middle chat z-index on animation
|
|
|
|
|
if(spliced.length > 1) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
spliced.slice(0, -1).forEach((chat) => {
|
2020-12-23 23:03:34 +01:00
|
|
|
|
chat.container.remove();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.chatsSelectTab(chatTo.container, animate);
|
2020-04-08 17:46:43 +02:00
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
if(justReturn) {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
this.dispatchEvent('peer_changed', chatTo);
|
2020-04-22 21:10:09 +02:00
|
|
|
|
|
2021-03-12 17:49:09 +01:00
|
|
|
|
const searchTab = appSidebarRight.getTab(AppPrivateSearchTab);
|
2022-11-27 14:09:10 +01:00
|
|
|
|
searchTab?.close();
|
2022-06-17 18:01:43 +02:00
|
|
|
|
|
|
|
|
|
appSidebarRight.replaceSharedMediaTab(chatTo.sharedMediaTab);
|
2020-11-25 20:36:18 +01:00
|
|
|
|
}
|
2021-05-08 20:49:50 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
spliced.forEach((chat) => {
|
2021-05-08 20:49:50 +02:00
|
|
|
|
chat.beforeDestroy();
|
|
|
|
|
});
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
setTimeout(() => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// chat.setPeer(0);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
spliced.forEach((chat) => {
|
2020-12-01 16:38:36 +01:00
|
|
|
|
chat.destroy();
|
|
|
|
|
});
|
2021-02-07 04:35:29 +01:00
|
|
|
|
}, 250 + 100);
|
2020-12-01 16:38:36 +01:00
|
|
|
|
}
|
2020-04-22 21:10:09 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
public async setPeer(options: Partial<ChatSetInnerPeerOptions> = {}, animate?: boolean): Promise<boolean> {
|
2020-12-01 16:38:36 +01:00
|
|
|
|
if(this.init) {
|
|
|
|
|
this.init();
|
|
|
|
|
this.init = null;
|
|
|
|
|
}
|
2020-06-16 22:48:08 +02:00
|
|
|
|
|
2022-01-14 23:01:50 +01:00
|
|
|
|
options.peerId ??= NULL_PEER_ID;
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
const {peerId, lastMsgId, threadId} = options;
|
2022-01-13 00:54:33 +01:00
|
|
|
|
|
2020-12-01 16:38:36 +01:00
|
|
|
|
const chat = this.chat;
|
|
|
|
|
const chatIndex = this.chats.indexOf(chat);
|
2023-01-17 20:28:27 +01:00
|
|
|
|
const isSamePeer = this.isSamePeer(chat, options as any);
|
2020-12-11 03:06:16 +01:00
|
|
|
|
if(!peerId) {
|
2020-12-01 16:38:36 +01:00
|
|
|
|
if(chatIndex > 0) {
|
2021-02-16 16:36:26 +01:00
|
|
|
|
this.spliceChats(chatIndex, undefined, animate);
|
2020-12-01 16:38:36 +01:00
|
|
|
|
return;
|
2020-12-23 04:40:30 +01:00
|
|
|
|
} else if(mediaSizes.activeScreen === ScreenSize.medium) { // * floating sidebar case
|
2021-02-16 16:36:26 +01:00
|
|
|
|
this.selectTab(+!this.tabId, animate);
|
2020-12-01 16:38:36 +01:00
|
|
|
|
return;
|
2020-02-06 16:43:07 +01:00
|
|
|
|
}
|
2023-01-17 20:28:27 +01:00
|
|
|
|
} else if(chatIndex > 0 && chat.peerId && !isSamePeer) {
|
2021-03-27 16:34:08 +01:00
|
|
|
|
// const firstChat = this.chats[0];
|
|
|
|
|
// if(firstChat.peerId !== chat.peerId) {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
/* // * slice idx > 0, set background and slice first, so new one will be the first
|
2021-03-27 16:34:08 +01:00
|
|
|
|
const spliced = this.chats.splice(1, this.chats.length - 1);
|
|
|
|
|
this.createNewChat();
|
|
|
|
|
this.chats.splice(0, 1); */
|
2022-08-04 08:49:54 +02:00
|
|
|
|
const spliced = this.chats.splice(1, this.chats.length - 1);
|
|
|
|
|
if(this.chat.peerId === peerId) {
|
|
|
|
|
this.spliceChats(0, true, true, spliced);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
const ret = this.setPeer(options);
|
|
|
|
|
this.spliceChats(0, false, false, spliced);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2021-03-27 16:34:08 +01:00
|
|
|
|
// } else {
|
|
|
|
|
// this.spliceChats(1, false, animate);
|
|
|
|
|
// }
|
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// return ret;
|
2020-10-30 01:23:10 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-21 04:11:26 +01:00
|
|
|
|
// * don't reset peer if returning
|
2023-01-17 20:28:27 +01:00
|
|
|
|
if(isSamePeer && mediaSizes.activeScreen <= ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) {
|
|
|
|
|
this.selectTab(APP_TABS.CHAT, animate);
|
2020-12-21 04:11:26 +01:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-21 01:38:21 +01:00
|
|
|
|
if(peerId || mediaSizes.activeScreen !== ScreenSize.mobile) {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
const result = await chat.setPeer(options as any as Parameters<Chat['setPeer']>[0]);
|
2020-12-21 01:38:21 +01:00
|
|
|
|
|
2020-12-21 04:11:26 +01:00
|
|
|
|
// * wait for cached render
|
2020-12-21 01:38:21 +01:00
|
|
|
|
const promise = result?.cached ? result.promise : Promise.resolve();
|
|
|
|
|
if(peerId) {
|
2022-03-13 21:51:16 +01:00
|
|
|
|
Promise.all([
|
|
|
|
|
promise,
|
|
|
|
|
chat.setBackgroundPromise
|
|
|
|
|
]).then(() => {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// window.requestAnimationFrame(() => {
|
2020-12-21 01:38:21 +01:00
|
|
|
|
setTimeout(() => { // * setTimeout is better here
|
2020-12-21 04:11:26 +01:00
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.chatsSelectTab(this.chat.container);
|
|
|
|
|
}, 0);
|
2023-01-17 20:28:27 +01:00
|
|
|
|
this.selectTab(APP_TABS.CHAT, animate);
|
2020-12-21 01:38:21 +01:00
|
|
|
|
}, 0);
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-05-18 03:21:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-21 01:38:21 +01:00
|
|
|
|
if(!peerId) {
|
2023-01-17 20:28:27 +01:00
|
|
|
|
this.selectTab(APP_TABS.CHATLIST, animate);
|
2020-04-14 17:46:31 +02:00
|
|
|
|
return false;
|
2020-02-08 07:03:09 +01:00
|
|
|
|
}
|
2020-02-06 16:43:07 +01:00
|
|
|
|
}
|
2020-04-22 21:10:09 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
public async setInnerPeer(options: ChatSetInnerPeerOptions) {
|
2022-01-13 00:54:33 +01:00
|
|
|
|
const {peerId} = options;
|
2021-11-10 02:12:42 +01:00
|
|
|
|
if(peerId === NULL_PEER_ID || !peerId) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
if(!options.type) {
|
|
|
|
|
if(options.threadId && !(await this.managers.appPeersManager.isForum(options.peerId))) {
|
|
|
|
|
options.type = 'discussion';
|
|
|
|
|
}
|
2022-06-24 19:23:12 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
options.type ??= 'chat';
|
|
|
|
|
}
|
2022-01-13 00:54:33 +01:00
|
|
|
|
|
2023-01-17 20:28:27 +01:00
|
|
|
|
// * reuse current chat
|
|
|
|
|
const existingIndex = this.chats.findIndex((chat) => this.isSamePeer(chat, options) || (mediaSizes.activeScreen === ScreenSize.mobile && this.tabId === 0));
|
2020-12-01 16:38:36 +01:00
|
|
|
|
if(existingIndex !== -1) {
|
|
|
|
|
this.spliceChats(existingIndex + 1);
|
2022-01-13 00:54:33 +01:00
|
|
|
|
return this.setPeer(options);
|
2020-04-22 21:10:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-08 13:52:14 +01:00
|
|
|
|
const oldChat = this.chat;
|
|
|
|
|
let chat = oldChat;
|
|
|
|
|
if(oldChat.inited) { // * use first not inited chat
|
|
|
|
|
chat = this.createNewChat();
|
2020-12-29 09:08:50 +01:00
|
|
|
|
}
|
2020-05-18 03:21:58 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
this.dispatchEvent('chat_changing', {from: oldChat, to: chat});
|
2022-01-08 13:52:14 +01:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// this.chatsSelectTab(chat.container);
|
2020-05-30 08:44:54 +02:00
|
|
|
|
|
2022-01-13 00:54:33 +01:00
|
|
|
|
return this.setPeer(options);
|
2020-05-30 08:44:54 +02:00
|
|
|
|
}
|
2020-05-18 03:21:58 +02:00
|
|
|
|
|
2021-10-21 15:16:43 +02:00
|
|
|
|
public openScheduled(peerId: PeerId) {
|
2022-01-13 00:54:33 +01:00
|
|
|
|
this.setInnerPeer({
|
2022-08-04 08:49:54 +02:00
|
|
|
|
peerId,
|
2022-01-13 00:54:33 +01:00
|
|
|
|
type: 'scheduled'
|
|
|
|
|
});
|
2020-12-18 04:07:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-29 20:42:01 +02:00
|
|
|
|
private getTypingElement(action: SendMessageAction) {
|
|
|
|
|
const el = document.createElement('span');
|
2021-11-29 16:24:29 +01:00
|
|
|
|
let c = 'peer-typing';
|
|
|
|
|
el.classList.add(c);
|
2021-04-20 20:00:38 +02:00
|
|
|
|
el.dataset.action = action._;
|
2021-03-29 20:42:01 +02:00
|
|
|
|
switch(action._) {
|
2021-04-20 20:00:38 +02:00
|
|
|
|
case 'sendMessageTypingAction': {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// default: {
|
2021-11-29 16:24:29 +01:00
|
|
|
|
c += '-text';
|
2021-03-29 20:42:01 +02:00
|
|
|
|
for(let i = 0; i < 3; ++i) {
|
|
|
|
|
const dot = document.createElement('span');
|
|
|
|
|
dot.className = c + '-dot';
|
|
|
|
|
el.append(dot);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
|
|
|
|
case 'sendMessageUploadAudioAction':
|
|
|
|
|
case 'sendMessageUploadDocumentAction':
|
|
|
|
|
case 'sendMessageUploadRoundAction':
|
|
|
|
|
case 'sendMessageUploadVideoAction':
|
|
|
|
|
case 'sendMessageUploadPhotoAction': {
|
2021-11-29 16:24:29 +01:00
|
|
|
|
c += '-upload';
|
2021-04-20 20:00:38 +02:00
|
|
|
|
/* const trail = document.createElement('span');
|
|
|
|
|
trail.className = c + '-trail';
|
|
|
|
|
el.append(trail); */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 'sendMessageRecordAudioAction':
|
|
|
|
|
case 'sendMessageRecordRoundAction':
|
|
|
|
|
case 'sendMessageRecordVideoAction': {
|
2021-11-29 16:24:29 +01:00
|
|
|
|
c += '-record';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-23 20:45:34 +01:00
|
|
|
|
case 'sendMessageEmojiInteractionSeen':
|
2021-11-29 16:24:29 +01:00
|
|
|
|
case 'sendMessageChooseStickerAction': {
|
|
|
|
|
c += '-choosing-sticker';
|
|
|
|
|
for(let i = 0; i < 2; ++i) {
|
|
|
|
|
const eye = document.createElement('div');
|
|
|
|
|
eye.className = c + '-eye';
|
|
|
|
|
el.append(eye);
|
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-03-29 20:42:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-29 16:24:29 +01:00
|
|
|
|
el.classList.add(c);
|
|
|
|
|
|
2021-03-29 20:42:01 +02:00
|
|
|
|
return el;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
public async getPeerTyping(peerId: PeerId, container?: HTMLElement, threadId?: number) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
// const log = this.log.bindPrefix('getPeerTyping-' + peerId);
|
|
|
|
|
// log('getting peer typing');
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const isUser = peerId.isUser();
|
|
|
|
|
if(isUser && await this.managers.appUsersManager.isBot(peerId)) {
|
|
|
|
|
// log('a bot');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
const typings = await this.managers.appProfileManager.getPeerTypings(peerId, threadId);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(!typings?.length) {
|
|
|
|
|
// log('have no typing');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const typing = typings[0];
|
|
|
|
|
|
|
|
|
|
const langPackKeys: {
|
|
|
|
|
[peerType in 'private' | 'chat' | 'multi']?: Partial<{[action in SendMessageAction['_']]: LangPackKey}>
|
|
|
|
|
} = {
|
|
|
|
|
private: {
|
|
|
|
|
'sendMessageTypingAction': 'Peer.Activity.User.TypingText',
|
|
|
|
|
'sendMessageUploadAudioAction': 'Peer.Activity.User.SendingFile',
|
|
|
|
|
'sendMessageUploadDocumentAction': 'Peer.Activity.User.SendingFile',
|
|
|
|
|
'sendMessageUploadPhotoAction': 'Peer.Activity.User.SendingPhoto',
|
|
|
|
|
'sendMessageUploadVideoAction': 'Peer.Activity.User.SendingVideo',
|
|
|
|
|
'sendMessageUploadRoundAction': 'Peer.Activity.User.SendingVideo',
|
|
|
|
|
'sendMessageRecordVideoAction': 'Peer.Activity.User.RecordingVideo',
|
|
|
|
|
'sendMessageRecordAudioAction': 'Peer.Activity.User.RecordingAudio',
|
|
|
|
|
'sendMessageRecordRoundAction': 'Peer.Activity.User.RecordingVideo',
|
|
|
|
|
'sendMessageGamePlayAction': 'Peer.Activity.User.PlayingGame',
|
|
|
|
|
'sendMessageChooseStickerAction': 'Peer.Activity.User.ChoosingSticker',
|
|
|
|
|
'sendMessageEmojiInteractionSeen': 'Peer.Activity.User.EnjoyingAnimations'
|
|
|
|
|
},
|
|
|
|
|
chat: {
|
|
|
|
|
'sendMessageTypingAction': 'Peer.Activity.Chat.TypingText',
|
|
|
|
|
'sendMessageUploadAudioAction': 'Peer.Activity.Chat.SendingFile',
|
|
|
|
|
'sendMessageUploadDocumentAction': 'Peer.Activity.Chat.SendingFile',
|
|
|
|
|
'sendMessageUploadPhotoAction': 'Peer.Activity.Chat.SendingPhoto',
|
|
|
|
|
'sendMessageUploadVideoAction': 'Peer.Activity.Chat.SendingVideo',
|
|
|
|
|
'sendMessageUploadRoundAction': 'Peer.Activity.Chat.SendingVideo',
|
|
|
|
|
'sendMessageRecordVideoAction': 'Peer.Activity.Chat.RecordingVideo',
|
|
|
|
|
'sendMessageRecordAudioAction': 'Peer.Activity.Chat.RecordingAudio',
|
|
|
|
|
'sendMessageRecordRoundAction': 'Peer.Activity.Chat.RecordingVideo',
|
|
|
|
|
'sendMessageGamePlayAction': 'Peer.Activity.Chat.PlayingGame',
|
|
|
|
|
'sendMessageChooseStickerAction': 'Peer.Activity.Chat.ChoosingSticker',
|
|
|
|
|
'sendMessageEmojiInteractionSeen': 'Peer.Activity.Chat.EnjoyingAnimations'
|
|
|
|
|
},
|
|
|
|
|
multi: {
|
|
|
|
|
'sendMessageTypingAction': 'Peer.Activity.Chat.Multi.TypingText1',
|
|
|
|
|
'sendMessageUploadAudioAction': 'Peer.Activity.Chat.Multi.SendingFile1',
|
|
|
|
|
'sendMessageUploadDocumentAction': 'Peer.Activity.Chat.Multi.SendingFile1',
|
|
|
|
|
'sendMessageUploadPhotoAction': 'Peer.Activity.Chat.Multi.SendingPhoto1',
|
|
|
|
|
'sendMessageUploadVideoAction': 'Peer.Activity.Chat.Multi.SendingVideo1',
|
|
|
|
|
'sendMessageUploadRoundAction': 'Peer.Activity.Chat.Multi.SendingVideo1',
|
|
|
|
|
'sendMessageRecordVideoAction': 'Peer.Activity.Chat.Multi.RecordingVideo1',
|
|
|
|
|
'sendMessageRecordAudioAction': 'Peer.Activity.Chat.Multi.RecordingAudio1',
|
|
|
|
|
'sendMessageRecordRoundAction': 'Peer.Activity.Chat.Multi.RecordingVideo1',
|
|
|
|
|
'sendMessageGamePlayAction': 'Peer.Activity.Chat.Multi.PlayingGame1',
|
|
|
|
|
'sendMessageChooseStickerAction': 'Peer.Activity.Chat.Multi.ChoosingSticker1'
|
2021-04-20 20:00:38 +02:00
|
|
|
|
}
|
2022-06-17 18:01:43 +02:00
|
|
|
|
};
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const mapa = isUser ? langPackKeys.private : (typings.length > 1 ? langPackKeys.multi : langPackKeys.chat);
|
|
|
|
|
let action = typing.action;
|
|
|
|
|
|
|
|
|
|
if(typings.length > 1) {
|
|
|
|
|
const s: any = {};
|
|
|
|
|
typings.forEach((typing) => {
|
|
|
|
|
const type = typing.action._;
|
|
|
|
|
if(s[type] === undefined) s[type] = 0;
|
|
|
|
|
++s[type];
|
|
|
|
|
});
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(Object.keys(s).length > 1) {
|
|
|
|
|
action = {
|
|
|
|
|
_: 'sendMessageTypingAction'
|
|
|
|
|
};
|
2021-04-20 20:00:38 +02:00
|
|
|
|
}
|
2022-06-17 18:01:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const langPackKey = mapa[action._];
|
|
|
|
|
if(!langPackKey) {
|
|
|
|
|
// log('no langPackKey');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-18 02:02:20 +02:00
|
|
|
|
let peerTitlePromise: Promise<any>;
|
|
|
|
|
let args: any[];
|
|
|
|
|
if(peerId.isAnyChat()) {
|
|
|
|
|
const peerTitle = new PeerTitle();
|
|
|
|
|
peerTitlePromise = peerTitle.update({peerId: typing.userId.toPeerId(false), onlyFirstName: true});
|
|
|
|
|
args = [
|
|
|
|
|
peerTitle.element,
|
|
|
|
|
typings.length - 1
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
await peerTitlePromise;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(!container) {
|
|
|
|
|
container = document.createElement('span');
|
|
|
|
|
container.classList.add('online', 'peer-typing-container');
|
|
|
|
|
}
|
2021-11-29 16:24:29 +01:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
container.classList.toggle('peer-typing-flex', action._ === 'sendMessageChooseStickerAction' || action._ === 'sendMessageEmojiInteractionSeen');
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
let typingElement = container.firstElementChild as HTMLElement;
|
|
|
|
|
if(!typingElement) {
|
|
|
|
|
typingElement = this.getTypingElement(action);
|
|
|
|
|
container.prepend(typingElement);
|
|
|
|
|
} else {
|
|
|
|
|
if(typingElement.dataset.action !== action._) {
|
|
|
|
|
typingElement.replaceWith(this.getTypingElement(action));
|
2021-04-20 20:00:38 +02:00
|
|
|
|
}
|
2022-06-17 18:01:43 +02:00
|
|
|
|
}
|
2022-01-23 20:45:34 +01:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(action._ === 'sendMessageEmojiInteractionSeen') {
|
|
|
|
|
if(args) {
|
|
|
|
|
args.pop();
|
|
|
|
|
} else {
|
|
|
|
|
args = [];
|
2022-01-23 20:45:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const span = htmlToSpan(wrapEmojiText(action.emoticon));
|
|
|
|
|
args.push(span);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const descriptionElement = i18n(langPackKey, args);
|
|
|
|
|
descriptionElement.classList.add('peer-typing-description');
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(container.childElementCount > 1) container.lastElementChild.replaceWith(descriptionElement);
|
|
|
|
|
else container.append(descriptionElement);
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
// log('returning typing');
|
|
|
|
|
return container;
|
2021-04-20 20:00:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
private async getChatStatus(chatId: ChatId, noTyping?: boolean): Promise<AckedResult<HTMLElement>> {
|
|
|
|
|
const typingEl = noTyping ? undefined : await this.getPeerTyping(chatId.toPeerId(true));
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(typingEl) {
|
|
|
|
|
return {cached: true, result: Promise.resolve(typingEl)};
|
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const result = await this.managers.acknowledged.appProfileManager.getChatFull(chatId);
|
|
|
|
|
const dooo = async(chatInfo: ChatFull) => {
|
|
|
|
|
// this.chat.log('chatInfo res:', chatInfo);
|
2020-05-18 03:21:58 +02:00
|
|
|
|
|
2022-08-04 08:49:54 +02:00
|
|
|
|
const participants_count = (chatInfo as ChatFull.channelFull).participants_count ||
|
|
|
|
|
((chatInfo as ChatFull.chatFull).participants as ChatParticipants.chatParticipants)?.participants?.length ||
|
2022-06-17 18:01:43 +02:00
|
|
|
|
1;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
// if(participants_count) {
|
|
|
|
|
let subtitle = await getChatMembersString(chatId);
|
|
|
|
|
|
|
|
|
|
if(participants_count < 2) {
|
2020-12-01 16:38:36 +01:00
|
|
|
|
return subtitle;
|
2022-08-04 08:49:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const onlines = await this.managers.appProfileManager.getOnlines(chatId);
|
|
|
|
|
if(onlines > 1) {
|
|
|
|
|
const span = document.createElement('span');
|
|
|
|
|
|
|
|
|
|
span.append(...join([subtitle, i18n('OnlineCount', [numberThousandSplitter(onlines)])], false));
|
|
|
|
|
subtitle = span;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return subtitle;
|
|
|
|
|
// }
|
|
|
|
|
};
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const promise = Promise.resolve(result.result).then(dooo);
|
|
|
|
|
return {
|
|
|
|
|
cached: result.cached,
|
|
|
|
|
result: promise
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async getUserStatus(userId: UserId, ignoreSelf?: boolean) {
|
|
|
|
|
const result: AckedResult<HTMLElement> = {
|
|
|
|
|
cached: true,
|
|
|
|
|
result: Promise.resolve(undefined as HTMLElement)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const user = await this.managers.appUsersManager.getUser(userId);
|
|
|
|
|
if(!user || (user.pFlags.self && !ignoreSelf)) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const subtitle = getUserStatusString(user);
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
if(!user.pFlags.bot && !user.pFlags.support) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
let typingEl = await this.getPeerTyping(userId.toPeerId());
|
|
|
|
|
if(!typingEl && user.status?._ === 'userStatusOnline') {
|
|
|
|
|
typingEl = document.createElement('span');
|
|
|
|
|
typingEl.classList.add('online');
|
|
|
|
|
typingEl.append(subtitle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(typingEl) {
|
|
|
|
|
result.result = Promise.resolve(typingEl);
|
|
|
|
|
return result;
|
2020-05-18 03:21:58 +02:00
|
|
|
|
}
|
2020-02-09 07:45:43 +01:00
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
result.result = Promise.resolve(subtitle);
|
|
|
|
|
return result;
|
2020-02-09 07:45:43 +01:00
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
private async getPeerStatus(peerId: PeerId, ignoreSelf?: boolean, noTyping?: boolean) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(!peerId) return;
|
|
|
|
|
let promise: Promise<AckedResult<HTMLElement>>;
|
|
|
|
|
if(peerId.isAnyChat()) {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
promise = this.getChatStatus(peerId.toChatId(), noTyping);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
} else {
|
|
|
|
|
promise = this.getUserStatus(peerId.toUserId(), ignoreSelf);
|
2021-04-20 20:00:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return promise;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
public async setPeerStatus(options: {
|
2022-08-04 08:49:54 +02:00
|
|
|
|
peerId: PeerId,
|
|
|
|
|
element: HTMLElement,
|
|
|
|
|
needClear: boolean,
|
|
|
|
|
useWhitespace: boolean,
|
|
|
|
|
middleware: () => boolean,
|
2023-01-06 20:27:29 +01:00
|
|
|
|
ignoreSelf?: boolean,
|
|
|
|
|
noTyping?: boolean
|
|
|
|
|
}) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
// const log = this.log.bindPrefix('status-' + peerId);
|
|
|
|
|
// log('setting status', element);
|
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
const {peerId, element, needClear, useWhitespace, middleware, ignoreSelf, noTyping} = options;
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
if(!needClear) {
|
|
|
|
|
// * good good good
|
|
|
|
|
const typingContainer = element.querySelector('.peer-typing-container') as HTMLElement;
|
|
|
|
|
if(typingContainer && await this.getPeerTyping(peerId, typingContainer)) {
|
|
|
|
|
// log('already have a status');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2023-01-06 20:27:29 +01:00
|
|
|
|
const result = await this.getPeerStatus(peerId, ignoreSelf, noTyping);
|
2022-06-17 18:01:43 +02:00
|
|
|
|
// log('getPeerStatus result', result);
|
|
|
|
|
if(!middleware()) {
|
|
|
|
|
// log.warn('middleware');
|
2021-04-20 20:00:38 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
const set = async() => {
|
|
|
|
|
const subtitle = result && await result.result;
|
2021-04-20 20:00:38 +02:00
|
|
|
|
if(!middleware()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return () => replaceContent(element, subtitle || placeholder);
|
|
|
|
|
};
|
2022-08-04 08:49:54 +02:00
|
|
|
|
|
2022-11-06 14:48:41 +01:00
|
|
|
|
const placeholder = useWhitespace ? NBSP : ''; // ! HERE U CAN FIND WHITESPACE
|
2023-01-06 20:27:29 +01:00
|
|
|
|
if(!result || result.cached || needClear === undefined) {
|
2022-06-17 18:01:43 +02:00
|
|
|
|
return await set();
|
|
|
|
|
} else if(needClear) {
|
|
|
|
|
return () => {
|
|
|
|
|
element.textContent = placeholder;
|
2023-01-06 20:27:29 +01:00
|
|
|
|
return set().then((callback) => callback?.());
|
2022-06-17 18:01:43 +02:00
|
|
|
|
};
|
|
|
|
|
}
|
2021-04-20 20:00:38 +02:00
|
|
|
|
}
|
2021-11-29 16:24:29 +01:00
|
|
|
|
|
|
|
|
|
public setChoosingStickerTyping(cancel: boolean) {
|
2023-01-06 20:27:29 +01:00
|
|
|
|
this.managers.appMessagesManager.setTyping(this.chat.peerId, {_: cancel ? 'sendMessageCancelAction' : 'sendMessageChooseStickerAction'}, undefined, this.chat.threadId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public isSamePeer(options1: {peerId: PeerId, threadId?: number, type?: ChatType}, options2: typeof options1) {
|
|
|
|
|
return options1.peerId === options2.peerId &&
|
|
|
|
|
options1.threadId === options2.threadId &&
|
|
|
|
|
(typeof(options1.type) !== typeof(options2.type) || options1.type === options2.type);
|
2021-11-29 16:24:29 +01:00
|
|
|
|
}
|
2020-02-06 16:43:07 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-10 08:56:15 +01:00
|
|
|
|
const appImManager = new AppImManager();
|
2020-09-29 04:03:26 +02:00
|
|
|
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appImManager = appImManager);
|
2020-02-10 08:56:15 +01:00
|
|
|
|
export default appImManager;
|