tweb/public/12.5fb212a201f60bc4a935.chunk.js.map
Eduard Kuzmenko 183b0a9a31 Build
2021-07-19 18:29:09 +03:00

1 line
179 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"version":3,"sources":["webpack:///./src/pages/pagePassword.ts","webpack:///./src/helpers/dom/replaceContent.ts","webpack:///./src/helpers/cleanUsername.ts","webpack:///./src/lib/appManagers/appUsersManager.ts","webpack:///./src/components/inputField.ts","webpack:///./src/lib/appManagers/appChatsManager.ts","webpack:///./src/lib/appManagers/appPeersManager.ts","webpack:///./src/helpers/dom/getRichValue.ts","webpack:///./src/helpers/dom/toggleDisability.ts","webpack:///./src/lib/mtproto/serverTimeManager.ts","webpack:///./src/helpers/array.ts","webpack:///./src/lib/appManagers/apiUpdatesManager.ts","webpack:///./src/helpers/dom/getRichElementValue.ts","webpack:///./src/helpers/dom/findUpAttribute.ts","webpack:///./src/helpers/dom/isInputEmpty.ts","webpack:///./src/lib/mtproto/passwordManager.ts","webpack:///./src/pages/loginPage.ts","webpack:///./src/components/passwordInputField.ts","webpack:///./src/lib/searchIndex.ts","webpack:///./src/components/monkeys/password.ts","webpack:///./src/helpers/cleanSearchText.ts","webpack:///./src/lib/mtproto/mtproto_config.ts","webpack:///./src/helpers/dom/htmlToSpan.ts"],"names":["passwordInput","page","className","withInputWrapper","titleLangKey","subtitleLangKey","btnNext","btnNextI18n","IntlElement","key","append","element","passwordInputField","label","name","getStateInterval","input","inputWrapper","container","state","getState","window","setInterval","then","_state","hint","wrapEmojiText","setLabel","onSubmit","e","value","length","classList","add","toggle","update","preloader","check","response","_","clearInterval","m","default","mount","monkey","remove","removeAttribute","catch","err","type","select","addEventListener","this","size","isMobile","imageDiv","Promise","all","load","focus","pushToState","replaceContent","elem","node","innerHTML","firstChild","lastChild","replaceWith","textContent","cleanUsername","username","toLowerCase","appUsersManager","storage","appStateManager","storages","users","updateUsersStatuses","timestampNow","i","user","status","expires","was_online","rootScope","dispatchEvent","id","setUserToStateIfNeeded","clear","addMultipleEventsListeners","updateUserStatus","userId","user_id","serverTimeManager","serverTimeOffset","updateUserPhoto","forceUserOnline","photo","console","warn","updateUserName","saveApiUser","Object","assign","first_name","last_name","getSelf","contactsIndex","indexObject","getUserSearchText","storagesResults","contactsList","Array","isArray","forEach","pushContact","contactsFillPromise","resolve","peerId","getFromCache","set","getUser","delete","init","usernames","_userId","isPeerNeeded","findAndSplice","undefined","Set","updatedContactsList","promise","invokeApi","result","saveApiUsers","contacts","contact","onContactsModified","slice","resolvedPeer","appChatsManager","saveApiChats","chats","appPeersManager","getPeer","getPeerId","peer","requestPeer","phone","pFlags","self","format","filter","Boolean","join","query","includeSaved","fillContacts","_contactsList","results","search","has","sort","userId1","userId2","sortName1","sortName","sortName2","localeCompare","testSelfSearch","p","myId","unshift","block","invokeApiSingle","getInputPeerById","apiUpdatesManager","processLocalUpdate","peer_id","getOutputPeer","blocked","index","apiUsers","override","oldUser","min","fullName","searchUsername","deleted","cleanSearchText","initials","getAbbreviation","changedPhoto","changedTitle","photo_id","formatted","access_hash","args","isBot","support","date","now","Date","d","getDate","getMonth","getHours","getMinutes","bot","isRegularUser","isContact","allowMin","eventTimestamp","timestamp","updatesState","syncLoading","getTopPeersPromise","topPeers","correspondents","offset","limit","hash","peerIds","categories","peers","map","topPeer","contactsBlocked","count","u","concat","c","invokeApiCacheable","q","cacheSeconds","my_results","offline","showPhone","getUserInput","add_phone_privacy_exception","updates","processUpdateMessage","onContactUpdated","userIds","document","target","preventDefault","text","originalEvent","clipboardData","getData","entities","parseEntities","wrapRichText","noLinks","wrappingDraft","execCommand","InputState","options","createElement","maxLength","showLengthOn","Math","round","placeholder","plainText","processInput","labelText","firstElementChild","observer","MutationObserver","inputFake","onFakeInput","observe","characterData","childList","subtree","animate","wasInputFakeClientHeight","showScrollDebounced","setAttribute","border","labelEl","lastElementChild","showingLength","wasError","contains","inputLength","diff","isError","labelOptions","scrollHeight","clientHeight","style","height","setValueSilently","event","Event","bubbles","cancelable","fireFakeInput","originalValue","silent","wrapDraftText","Error","Valid","setState","onChatUpdated","chatId","isChannel","updateChannelParticipant","clearCache","params","channel","channel_id","updateChatDefaultBannedRights","chat","default_banned_rights","getChat","_chatId","apiChats","saveApiChat","oldChat","title","participants_count","rights","defaultRights","action","isThread","kicked","left","megagroup","deactivated","creator","admin_rights","banned_rights","myFlags","post_messages","delete_messages","broadcast","until_date","bind","isMegagroup","good","chat_id","about","channelId","getChannelInput","usersInputs","fwdLimit","fwd_limit","deleteChatUser","leaveChannel","leaveChat","deleteChannel","deleteChat","find","bool","inputFile","inputChatPhoto","file","participant","getParticipantPeerId","actor_id","qts","prev_participant","new_participant","keys","kicked_by","editBanned","view_messages","DialogColorsFg","DialogColors","DialogColorsMap","updatePeerBlocked","hasRights","getUserPhoto","getChatPhoto","migrated_to","onlyFirstName","trim","split","getUserString","getChatString","isUser","charAt","peerParams","substr","isBroadcast","ignorePeerId","getChannelInputPeer","getChatInputPeer","pic","getDialogType","getRichValue","field","withEntities","lines","line","push","replace","combineSameEntities","toggleDisability","elements","disable","el","get","to","addTaskListener","task","payload","accumulate","arr","initialValue","reduce","acc","findAndSpliceAll","array","verify","out","idx","findIndex","splice","forEachReverse","callback","insertInDescendSortedArray","property","pos","indexOf","sortProperty","len","error","filterUnique","pendingPtsUpdates","pendingSeqUpdates","syncPending","channelStates","attached","log","Warn","Log","debug","updateMessage","processOpts","seq","seqStart","seq_start","forceGetDifference","processUpdate","isOut","fromId","from_id","toId","message","fwd_from","reply_to","pts","pts_count","Proxy","saveUpdatesState","us","nextSeq","pendingUpdatesData","saveUpdate","popPendingSeqUpdate","seqAwaiting","ptsAwaiting","clearTimeout","timeout","curState","getChannelState","a","b","curPts","goodPts","goodIndex","getDifference","first","wasSyncing","pts_total_limit","differenceResult","other_updates","new_messages","apiMessage","nextState","intermediate_state","justAName","channelState","getChannelDifference","addChannelState","lastPtsUpdateTime","toPeerId","fwdHeader","reason","hasUser","post","hasChat","popPts","popSeq","setTimeout","popPendingPtsUpdate","noErrorBox","stateResult","setUpdatesProcessor","setProxy","markdownTags","bold","match","entityName","underline","italic","monospace","strikethrough","link","mentionName","getRichElementValue","selNode","selOffset","nodeType","nodeValue","parentNode","parentElement","tag","closest","getAttribute","url","href","dataset","follow","isSelected","isBlock","tagName","alt","curChild","nextSibling","findUpAttribute","attribute","isInputEmpty","hasAttribute","passwordManager","settings","currentHashPromise","newHashPromise","password","new_settings","email","currentPassword","invokeCrypto","newAlgo","new_algo","salt1","Uint8Array","randomize","newPassword","hashes","new_password_hash","inputCheckPassword","auth","setUserAuth","code","LoginPage","body","querySelector","subtitle","PasswordInputField","super","passwordVisible","onVisibilityClick","toggleVisible","onVisibilityClickAdditional","autocomplete","stealthy","tabIndex","prepend","insertBefore","cloneNode","SearchIndex","cleanText","latinize","minChars","fullTexts","Map","searchText","newFoundObjs","queryWords","queryWordsLength","fullText","what","found","foundChars","word","fullTextLength","o","PasswordMonkey","needFrame","loadPromise","loadAnimationFromURL","loop","autoplay","width","noCache","_animation","animation","currentFrame","direction","setSpeed","pause","setDirection","curFrame","play","waitForFirstFrame","badCharsRe","trimRe","hasTag","ch","latinizeCh","LatinizeMap","REPLIES_PEER_ID","htmlToSpan","html","span"],"mappings":"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","file":"12.5fb212a201f60bc4a935.chunk.js","sourcesContent":["/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { putPreloader } from '../components/misc';\r\nimport mediaSizes from '../helpers/mediaSizes';\r\nimport { AccountPassword } from '../layer';\r\nimport appStateManager from '../lib/appManagers/appStateManager';\r\nimport passwordManager from '../lib/mtproto/passwordManager';\r\nimport Page from './page';\r\nimport Button from '../components/button';\r\nimport PasswordInputField from '../components/passwordInputField';\r\nimport PasswordMonkey from '../components/monkeys/password';\r\nimport RichTextProcessor from '../lib/richtextprocessor';\r\nimport I18n from '../lib/langPack';\r\nimport LoginPage from './loginPage';\r\nimport { cancelEvent } from '../helpers/dom/cancelEvent';\r\nimport { attachClickEvent } from '../helpers/dom/clickEvent';\r\nimport htmlToSpan from '../helpers/dom/htmlToSpan';\r\nimport replaceContent from '../helpers/dom/replaceContent';\r\nimport toggleDisability from '../helpers/dom/toggleDisability';\r\n\r\nconst TEST = false;\r\nlet passwordInput: HTMLInputElement;\r\n\r\nlet onFirstMount = (): Promise<any> => {\r\n const page = new LoginPage({\r\n className: 'page-password',\r\n withInputWrapper: true,\r\n titleLangKey: 'Login.Password.Title',\r\n subtitleLangKey: 'Login.Password.Subtitle'\r\n });\r\n\r\n const btnNext = Button('btn-primary btn-color-primary');\r\n const btnNextI18n = new I18n.IntlElement({key: 'Login.Next'});\r\n\r\n btnNext.append(btnNextI18n.element);\r\n\r\n const passwordInputField = new PasswordInputField({\r\n label: 'LoginPassword',\r\n name: 'password'\r\n });\r\n\r\n passwordInput = passwordInputField.input as HTMLInputElement;\r\n\r\n page.inputWrapper.append(passwordInputField.container, btnNext);\r\n\r\n let getStateInterval: number;\r\n\r\n let getState = () => {\r\n // * just to check session relevance\r\n if(!getStateInterval) {\r\n getStateInterval = window.setInterval(getState, 10e3);\r\n }\r\n\r\n return !TEST && passwordManager.getState().then(_state => {\r\n state = _state;\r\n\r\n if(state.hint) {\r\n replaceContent(passwordInputField.label, htmlToSpan(RichTextProcessor.wrapEmojiText(state.hint)));\r\n } else {\r\n passwordInputField.setLabel();\r\n }\r\n });\r\n };\r\n\r\n let state: AccountPassword;\r\n \r\n const onSubmit = (e?: Event) => {\r\n if(e) {\r\n cancelEvent(e);\r\n }\r\n\r\n if(!passwordInput.value.length) {\r\n passwordInput.classList.add('error');\r\n return;\r\n }\r\n\r\n const toggle = toggleDisability([passwordInput, btnNext], true);\r\n let value = passwordInput.value;\r\n\r\n btnNextI18n.update({key: 'PleaseWait'});\r\n const preloader = putPreloader(btnNext);\r\n\r\n passwordManager.check(value, state).then((response) => {\r\n //console.log('passwordManager response:', response);\r\n \r\n switch(response._) {\r\n case 'auth.authorization':\r\n clearInterval(getStateInterval);\r\n import('./pageIm').then(m => {\r\n m.default.mount();\r\n });\r\n if(monkey) monkey.remove();\r\n break;\r\n default:\r\n btnNext.removeAttribute('disabled');\r\n btnNextI18n.update({key: response._ as any});\r\n preloader.remove();\r\n break;\r\n }\r\n }).catch((err: any) => {\r\n toggle();\r\n passwordInputField.input.classList.add('error');\r\n \r\n switch(err.type) {\r\n default:\r\n //btnNext.innerText = err.type;\r\n btnNextI18n.update({key: 'PASSWORD_HASH_INVALID'});\r\n passwordInput.select();\r\n break;\r\n }\r\n\r\n preloader.remove();\r\n \r\n getState();\r\n });\r\n };\r\n \r\n attachClickEvent(btnNext, onSubmit);\r\n\r\n passwordInput.addEventListener('keypress', function(this, e) {\r\n this.classList.remove('error');\r\n btnNextI18n.update({key: 'Login.Next'});\r\n\r\n if(e.key === 'Enter') {\r\n return onSubmit();\r\n }\r\n });\r\n\r\n const size = mediaSizes.isMobile ? 100 : 166;\r\n const monkey = new PasswordMonkey(passwordInputField, size);\r\n page.imageDiv.append(monkey.container);\r\n return Promise.all([\r\n monkey.load(),\r\n getState()\r\n ]);\r\n};\r\n\r\nconst page = new Page('page-password', true, onFirstMount, null, () => {\r\n //if(!isAppleMobile) {\r\n passwordInput.focus();\r\n //}\r\n\r\n appStateManager.pushToState('authState', {_: 'authStatePassword'});\r\n});\r\n\r\nexport default page;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nexport default function replaceContent(elem: HTMLElement, node: string | Node) {\r\n if(typeof(node) === 'string') {\r\n elem.innerHTML = node;\r\n return;\r\n }\r\n\r\n // * children.length doesn't count text nodes\r\n const firstChild = elem.firstChild;\r\n if(firstChild) {\r\n if(elem.lastChild === firstChild) {\r\n firstChild.replaceWith(node);\r\n } else {\r\n elem.textContent = '';\r\n elem.append(node);\r\n }\r\n } else {\r\n elem.append(node);\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nexport default function cleanUsername(username: string) {\r\n return username && username.toLowerCase() || '';\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport { formatPhoneNumber } from \"../../components/misc\";\r\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\r\nimport { filterUnique } from \"../../helpers/array\";\r\nimport cleanSearchText from \"../../helpers/cleanSearchText\";\r\nimport cleanUsername from \"../../helpers/cleanUsername\";\r\nimport { tsNow } from \"../../helpers/date\";\r\nimport { safeReplaceObject, isObject } from \"../../helpers/object\";\r\nimport { InputUser, User as MTUser, UserProfilePhoto, UserStatus } from \"../../layer\";\r\nimport I18n, { i18n, LangPackKey } from \"../langPack\";\r\n//import apiManager from '../mtproto/apiManager';\r\nimport apiManager from '../mtproto/mtprotoworker';\r\nimport { REPLIES_PEER_ID } from \"../mtproto/mtproto_config\";\r\nimport serverTimeManager from \"../mtproto/serverTimeManager\";\r\nimport { RichTextProcessor } from \"../richtextprocessor\";\r\nimport rootScope from \"../rootScope\";\r\nimport SearchIndex from \"../searchIndex\";\r\nimport apiUpdatesManager from \"./apiUpdatesManager\";\r\nimport appChatsManager from \"./appChatsManager\";\r\nimport appPeersManager from \"./appPeersManager\";\r\nimport appStateManager from \"./appStateManager\";\r\n\r\n// TODO: updateUserBlocked\r\n\r\nexport type User = MTUser.user;\r\n\r\nexport class AppUsersManager {\r\n private storage = appStateManager.storages.users;\r\n \r\n private users: {[userId: number]: User};\r\n private usernames: {[username: string]: number};\r\n private contactsIndex: SearchIndex<number>;\r\n private contactsFillPromise: Promise<Set<number>>;\r\n private contactsList: Set<number>;\r\n private updatedContactsList: boolean;\r\n \r\n private getTopPeersPromise: Promise<number[]>;\r\n\r\n constructor() {\r\n this.clear(true);\r\n\r\n setInterval(this.updateUsersStatuses, 60000);\r\n\r\n rootScope.addEventListener('state_synchronized', this.updateUsersStatuses);\r\n\r\n rootScope.addMultipleEventsListeners({\r\n updateUserStatus: (update) => {\r\n const userId = update.user_id;\r\n const user = this.users[userId];\r\n if(user) {\r\n user.status = update.status;\r\n if(user.status) {\r\n if('expires' in user.status) {\r\n user.status.expires -= serverTimeManager.serverTimeOffset;\r\n }\r\n\r\n if('was_online' in user.status) {\r\n user.status.was_online -= serverTimeManager.serverTimeOffset;\r\n }\r\n }\r\n\r\n //user.sortStatus = this.getUserStatusForSort(user.status);\r\n rootScope.dispatchEvent('user_update', userId);\r\n this.setUserToStateIfNeeded(user);\r\n } //////else console.warn('No user by id:', userId);\r\n },\r\n\r\n updateUserPhoto: (update) => {\r\n const userId = update.user_id;\r\n const user = this.users[userId];\r\n if(user) {\r\n this.forceUserOnline(userId);\r\n\r\n if(update.photo._ === 'userProfilePhotoEmpty') {\r\n delete user.photo;\r\n } else {\r\n user.photo = safeReplaceObject(user.photo, update.photo);\r\n }\r\n\r\n this.setUserToStateIfNeeded(user);\r\n\r\n rootScope.dispatchEvent('user_update', userId);\r\n rootScope.dispatchEvent('avatar_update', userId);\r\n } else console.warn('No user by id:', userId);\r\n },\r\n\r\n updateUserName: (update) => {\r\n const userId = update.user_id;\r\n const user = this.users[userId];\r\n if(user) {\r\n this.forceUserOnline(userId);\r\n \r\n this.saveApiUser(Object.assign({}, user, {\r\n first_name: update.first_name,\r\n last_name: update.last_name,\r\n username: update.username\r\n }), true);\r\n }\r\n }\r\n });\r\n\r\n /* case 'updateContactLink':\r\n this.onContactUpdated(update.user_id, update.my_link._ === 'contactLinkContact');\r\n break; */\r\n\r\n rootScope.addEventListener('language_change', (e) => {\r\n const userId = this.getSelf().id;\r\n this.contactsIndex.indexObject(userId, this.getUserSearchText(userId));\r\n });\r\n\r\n appStateManager.getState().then((state) => {\r\n const users = appStateManager.storagesResults.users;\r\n if(users.length) {\r\n for(let i = 0, length = users.length; i < length; ++i) {\r\n const user = users[i];\r\n if(user) {\r\n this.users[user.id] = user;\r\n }\r\n }\r\n }\r\n\r\n const contactsList = state.contactsList;\r\n if(contactsList && Array.isArray(contactsList)) {\r\n contactsList.forEach(userId => {\r\n this.pushContact(userId);\r\n });\r\n\r\n if(contactsList.length) {\r\n this.contactsFillPromise = Promise.resolve(this.contactsList);\r\n }\r\n }\r\n\r\n appStateManager.addEventListener('peerNeeded', (peerId: number) => {\r\n if(peerId < 0 || this.storage.getFromCache(peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.set({\r\n [peerId]: this.getUser(peerId)\r\n });\r\n });\r\n\r\n appStateManager.addEventListener('peerUnneeded', (peerId: number) => {\r\n if(peerId < 0 || !this.storage.getFromCache(peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.delete(peerId);\r\n });\r\n });\r\n }\r\n\r\n public clear(init = false) {\r\n if(!init) {\r\n const users = appStateManager.storagesResults.users;\r\n for(const _userId in this.users) {\r\n const userId = +_userId;\r\n if(!userId) continue;\r\n if(!appStateManager.isPeerNeeded(userId)) {\r\n const user = this.users[userId];\r\n if(user.username) {\r\n delete this.usernames[cleanUsername(user.username)];\r\n }\r\n\r\n users.findAndSplice((user) => user.id === userId);\r\n this.storage.delete(userId);\r\n delete this.users[userId];\r\n }\r\n }\r\n } else {\r\n this.users = {};\r\n this.usernames = {};\r\n }\r\n \r\n this.contactsIndex = new SearchIndex();\r\n this.contactsFillPromise = undefined;\r\n this.contactsList = new Set();\r\n this.updatedContactsList = false;\r\n }\r\n\r\n private onContactsModified() {\r\n const contactsList = [...this.contactsList];\r\n appStateManager.pushToState('contactsList', contactsList);\r\n }\r\n\r\n public fillContacts() {\r\n if(this.contactsFillPromise && this.updatedContactsList) {\r\n return this.contactsFillPromise;\r\n }\r\n\r\n this.updatedContactsList = true;\r\n\r\n const promise = apiManager.invokeApi('contacts.getContacts').then((result) => {\r\n if(result._ === 'contacts.contacts') {\r\n this.saveApiUsers(result.users);\r\n\r\n result.contacts.forEach((contact) => {\r\n this.pushContact(contact.user_id);\r\n });\r\n\r\n this.onContactsModified();\r\n }\r\n\r\n this.contactsFillPromise = promise;\r\n\r\n return this.contactsList;\r\n });\r\n\r\n return this.contactsFillPromise || (this.contactsFillPromise = promise);\r\n }\r\n\r\n public resolveUsername(username: string) {\r\n if(username[0] === '@') {\r\n username = username.slice(1);\r\n }\r\n\r\n username = username.toLowerCase();\r\n if(this.usernames[username]) {\r\n return Promise.resolve(this.users[this.usernames[username]]);\r\n }\r\n\r\n return apiManager.invokeApi('contacts.resolveUsername', {username}).then(resolvedPeer => {\r\n this.saveApiUsers(resolvedPeer.users);\r\n appChatsManager.saveApiChats(resolvedPeer.chats);\r\n\r\n return appPeersManager.getPeer(appPeersManager.getPeerId(resolvedPeer.peer));\r\n });\r\n }\r\n\r\n public pushContact(userId: number) {\r\n this.contactsList.add(userId);\r\n this.contactsIndex.indexObject(userId, this.getUserSearchText(userId));\r\n appStateManager.requestPeer(userId, 'contacts');\r\n }\r\n\r\n public getUserSearchText(id: number) {\r\n const user = this.users[id];\r\n if(!user) {\r\n return '';\r\n }\r\n\r\n const arr: string[] = [\r\n user.first_name,\r\n user.last_name,\r\n user.phone,\r\n user.username,\r\n user.pFlags.self ? I18n.format('SavedMessages', true) : '',\r\n user.pFlags.self ? 'Saved Messages' : ''\r\n ];\r\n\r\n return arr.filter(Boolean).join(' ');\r\n }\r\n\r\n public getContacts(query?: string, includeSaved = false) {\r\n return this.fillContacts().then(_contactsList => {\r\n let contactsList = [..._contactsList];\r\n if(query) {\r\n const results = this.contactsIndex.search(query);\r\n const filteredContactsList = [...contactsList].filter(id => results.has(id));\r\n\r\n contactsList = filteredContactsList;\r\n }\r\n\r\n contactsList.sort((userId1: number, userId2: number) => {\r\n const sortName1 = (this.users[userId1] || {}).sortName || '';\r\n const sortName2 = (this.users[userId2] || {}).sortName || '';\r\n\r\n return sortName1.localeCompare(sortName2);\r\n });\r\n\r\n if(includeSaved) {\r\n if(this.testSelfSearch(query)) {\r\n contactsList.findAndSplice(p => p === rootScope.myId);\r\n contactsList.unshift(rootScope.myId);\r\n }\r\n }\r\n\r\n /* contactsList.sort((userId1: number, userId2: number) => {\r\n const sortName1 = (this.users[userId1] || {}).sortName || '';\r\n const sortName2 = (this.users[userId2] || {}).sortName || '';\r\n if(sortName1 === sortName2) {\r\n return 0;\r\n } \r\n \r\n return sortName1 > sortName2 ? 1 : -1;\r\n }); */\r\n\r\n return contactsList;\r\n });\r\n }\r\n\r\n public toggleBlock(peerId: number, block: boolean) {\r\n return apiManager.invokeApiSingle(block ? 'contacts.block' : 'contacts.unblock', {\r\n id: appPeersManager.getInputPeerById(peerId)\r\n }).then(value => {\r\n if(value) {\r\n apiUpdatesManager.processLocalUpdate({\r\n _: 'updatePeerBlocked',\r\n peer_id: appPeersManager.getOutputPeer(peerId),\r\n blocked: block\r\n });\r\n }\r\n\r\n return value;\r\n });\r\n }\r\n\r\n public testSelfSearch(query: string) {\r\n const user = this.getSelf();\r\n const index = new SearchIndex();\r\n index.indexObject(user.id, this.getUserSearchText(user.id));\r\n return index.search(query).has(user.id);\r\n }\r\n\r\n public saveApiUsers(apiUsers: any[], override?: boolean) {\r\n apiUsers.forEach((user) => this.saveApiUser(user, override));\r\n }\r\n\r\n public saveApiUser(user: MTUser, override?: boolean) {\r\n if(user._ === 'userEmpty') return;\r\n\r\n const userId = user.id;\r\n const oldUser = this.users[userId];\r\n\r\n // ! commented block can affect performance !\r\n // if(oldUser && !override) {\r\n // console.log('saveApiUser same');\r\n // return;\r\n // }\r\n\r\n if(user.pFlags === undefined) {\r\n user.pFlags = {};\r\n }\r\n\r\n if(user.pFlags.min && oldUser !== undefined) {\r\n return;\r\n }\r\n\r\n // * exclude from state\r\n // defineNotNumerableProperties(user, ['initials', 'num', 'rFirstName', 'rFullName', 'rPhone', 'sortName', 'sortStatus']);\r\n\r\n const fullName = user.first_name + ' ' + (user.last_name || '');\r\n if(user.username) {\r\n const searchUsername = cleanUsername(user.username);\r\n this.usernames[searchUsername] = userId;\r\n }\r\n\r\n user.sortName = user.pFlags.deleted ? '' : cleanSearchText(fullName, false);\r\n\r\n user.initials = RichTextProcessor.getAbbreviation(fullName);\r\n\r\n if(user.status) {\r\n if((user.status as UserStatus.userStatusOnline).expires) {\r\n (user.status as UserStatus.userStatusOnline).expires -= serverTimeManager.serverTimeOffset;\r\n }\r\n\r\n if((user.status as UserStatus.userStatusOffline).was_online) {\r\n (user.status as UserStatus.userStatusOffline).was_online -= serverTimeManager.serverTimeOffset;\r\n }\r\n }\r\n\r\n //user.sortStatus = user.pFlags.bot ? -1 : this.getUserStatusForSort(user.status);\r\n\r\n let changedPhoto = false, changedTitle = false;\r\n if(oldUser === undefined) {\r\n this.users[userId] = user;\r\n } else {\r\n if(user.first_name !== oldUser.first_name \r\n || user.last_name !== oldUser.last_name \r\n || user.username !== oldUser.username) {\r\n changedTitle = true;\r\n }\r\n\r\n const oldPhotoId = (oldUser.photo as UserProfilePhoto.userProfilePhoto)?.photo_id;\r\n const newPhotoId = (user.photo as UserProfilePhoto.userProfilePhoto)?.photo_id;\r\n if(oldPhotoId !== newPhotoId) {\r\n changedPhoto = true;\r\n }\r\n\r\n /* if(user.pFlags.bot && user.bot_info_version !== oldUser.bot_info_version) {\r\n \r\n } */\r\n\r\n safeReplaceObject(oldUser, user);\r\n rootScope.dispatchEvent('user_update', userId);\r\n }\r\n\r\n if(changedPhoto) {\r\n rootScope.dispatchEvent('avatar_update', user.id);\r\n }\r\n\r\n if(changedTitle) {\r\n rootScope.dispatchEvent('peer_title_edit', user.id);\r\n }\r\n\r\n this.setUserToStateIfNeeded(user);\r\n }\r\n\r\n public setUserToStateIfNeeded(user: User) {\r\n if(appStateManager.isPeerNeeded(user.id)) {\r\n this.storage.set({\r\n [user.id]: user\r\n });\r\n }\r\n }\r\n\r\n public formatUserPhone(phone: string) {\r\n return '+' + formatPhoneNumber(phone).formatted;\r\n }\r\n\r\n public getUserStatusForSort(status: User['status'] | number) {\r\n if(typeof(status) === 'number') {\r\n status = this.getUser(status).status;\r\n }\r\n\r\n if(status) {\r\n const expires = status._ === 'userStatusOnline' ? status.expires : (status._ === 'userStatusOffline' ? status.was_online : 0);\r\n if(expires) {\r\n return expires;\r\n }\r\n\r\n /* const timeNow = tsNow(true);\r\n switch(status._) {\r\n case 'userStatusRecently':\r\n return timeNow - 86400 * 3;\r\n case 'userStatusLastWeek':\r\n return timeNow - 86400 * 7;\r\n case 'userStatusLastMonth':\r\n return timeNow - 86400 * 30;\r\n } */\r\n switch(status._) {\r\n case 'userStatusRecently':\r\n return 3;\r\n case 'userStatusLastWeek':\r\n return 2;\r\n case 'userStatusLastMonth':\r\n return 1;\r\n }\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n public getUser(id: any): User {\r\n if(isObject(id)) {\r\n return id;\r\n }\r\n\r\n return this.users[id] || {id: id, pFlags: {deleted: true}, access_hash: ''} as User;\r\n }\r\n\r\n public getSelf() {\r\n return this.getUser(rootScope.myId);\r\n }\r\n\r\n public getUserStatusString(userId: number): HTMLElement {\r\n let key: LangPackKey;\r\n let args: any[];\r\n\r\n switch(userId) {\r\n case REPLIES_PEER_ID:\r\n key = 'Peer.RepliesNotifications';\r\n break;\r\n case 777000:\r\n key = 'Peer.ServiceNotifications';\r\n break;\r\n default: {\r\n if(this.isBot(userId)) {\r\n key = 'Bot';\r\n break;\r\n }\r\n\r\n const user = this.getUser(userId);\r\n if(!user) {\r\n key = '' as any;\r\n break;\r\n }\r\n\r\n if(user.pFlags.support) {\r\n key = 'SupportStatus';\r\n break;\r\n }\r\n\r\n switch(user.status?._) {\r\n case 'userStatusRecently': {\r\n key = 'Lately';\r\n break;\r\n }\r\n \r\n case 'userStatusLastWeek': {\r\n key = 'WithinAWeek';\r\n break;\r\n }\r\n \r\n case 'userStatusLastMonth': {\r\n key = 'WithinAMonth';\r\n break;\r\n }\r\n \r\n case 'userStatusOffline': {\r\n const date = user.status.was_online;\r\n const now = Date.now() / 1000;\r\n \r\n if((now - date) < 60) {\r\n key = 'Peer.Status.justNow';\r\n } else if((now - date) < 3600) {\r\n key = 'Peer.Status.minAgo';\r\n const c = (now - date) / 60 | 0;\r\n args = [c];\r\n } else if(now - date < 86400) {\r\n key = 'LastSeen.HoursAgo';\r\n const c = (now - date) / 3600 | 0;\r\n args = [c];\r\n } else {\r\n key = 'Peer.Status.LastSeenAt';\r\n const d = new Date(date * 1000);\r\n args = [('0' + d.getDate()).slice(-2) + '.' + ('0' + (d.getMonth() + 1)).slice(-2), \r\n ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2)];\r\n }\r\n \r\n break;\r\n }\r\n \r\n case 'userStatusOnline': {\r\n key = 'Online';\r\n break;\r\n }\r\n \r\n default: {\r\n key = 'ALongTimeAgo';\r\n break;\r\n }\r\n }\r\n\r\n break;\r\n }\r\n }\r\n \r\n return i18n(key, args);\r\n }\r\n\r\n public isBot(id: number) {\r\n return this.users[id] && this.users[id].pFlags.bot;\r\n }\r\n\r\n public isContact(id: number) {\r\n return this.contactsList.has(id) || (this.users[id] && this.users[id].pFlags.contact);\r\n }\r\n \r\n public isRegularUser(id: number) {\r\n const user = this.users[id];\r\n return user && !this.isBot(id) && !user.pFlags.deleted && !user.pFlags.support;\r\n }\r\n\r\n public isNonContactUser(id: number) {\r\n return this.isRegularUser(id) && !this.isContact(id) && id !== rootScope.myId;\r\n }\r\n\r\n public hasUser(id: number, allowMin?: boolean) {\r\n const user = this.users[id];\r\n return isObject(user) && (allowMin || !user.pFlags.min);\r\n }\r\n\r\n public canSendToUser(id: number) {\r\n const user = this.getUser(id);\r\n return !user.pFlags.deleted && user.username !== 'replies';\r\n }\r\n\r\n public getUserPhoto(id: number) {\r\n const user = this.getUser(id);\r\n\r\n return user && user.photo || {\r\n _: 'userProfilePhotoEmpty'\r\n };\r\n }\r\n\r\n public getUserString(id: number) {\r\n const user = this.getUser(id);\r\n return 'u' + id + (user.access_hash ? '_' + user.access_hash : '');\r\n }\r\n\r\n public getUserInput(id: number): InputUser {\r\n const user = this.getUser(id);\r\n if(user.pFlags && user.pFlags.self) {\r\n return {_: 'inputUserSelf'};\r\n }\r\n\r\n return {\r\n _: 'inputUser',\r\n user_id: id,\r\n access_hash: user.access_hash\r\n };\r\n }\r\n\r\n public updateUsersStatuses = () => {\r\n const timestampNow = tsNow(true);\r\n for(const i in this.users) {\r\n const user = this.users[i];\r\n\r\n if(user.status &&\r\n user.status._ === 'userStatusOnline' &&\r\n user.status.expires < timestampNow) {\r\n\r\n user.status = {_: 'userStatusOffline', was_online: user.status.expires};\r\n rootScope.dispatchEvent('user_update', user.id);\r\n\r\n this.setUserToStateIfNeeded(user);\r\n }\r\n }\r\n };\r\n\r\n public forceUserOnline(id: number, eventTimestamp?: number) {\r\n if(this.isBot(id)) {\r\n return;\r\n }\r\n\r\n const timestamp = tsNow(true);\r\n const onlineTimeFor = 60;\r\n if(eventTimestamp) {\r\n if((timestamp - eventTimestamp) >= onlineTimeFor) {\r\n return;\r\n }\r\n } else if(apiUpdatesManager.updatesState.syncLoading) {\r\n return;\r\n }\r\n\r\n const user = this.getUser(id);\r\n if(user &&\r\n user.status &&\r\n user.status._ !== 'userStatusOnline' &&\r\n user.status._ !== 'userStatusEmpty' &&\r\n !user.pFlags.support &&\r\n !user.pFlags.deleted) {\r\n\r\n user.status = {\r\n _: 'userStatusOnline',\r\n expires: timestamp + onlineTimeFor\r\n };\r\n \r\n //user.sortStatus = this.getUserStatusForSort(user.status);\r\n rootScope.dispatchEvent('user_update', id);\r\n\r\n this.setUserToStateIfNeeded(user);\r\n }\r\n }\r\n\r\n /* function importContact (phone, firstName, lastName) {\r\n return MtpApiManager.invokeApi('contacts.importContacts', {\r\n contacts: [{\r\n _: 'inputPhoneContact',\r\n client_id: '1',\r\n phone: phone,\r\n first_name: firstName,\r\n last_name: lastName\r\n }],\r\n replace: false\r\n }).then(function (importedContactsResult) {\r\n saveApiUsers(importedContactsResult.users)\r\n\r\n var foundUserID = false\r\n angular.forEach(importedContactsResult.imported, function (importedContact) {\r\n onContactUpdated(foundUserID = importedContact.user_id, true)\r\n })\r\n\r\n return foundUserID || false\r\n })\r\n }\r\n\r\n function importContacts (contacts) {\r\n var inputContacts = [],\r\n i\r\n var j\r\n\r\n for (i = 0; i < contacts.length; i++) {\r\n for (j = 0; j < contacts[i].phones.length; j++) {\r\n inputContacts.push({\r\n _: 'inputPhoneContact',\r\n client_id: (i << 16 | j).toString(10),\r\n phone: contacts[i].phones[j],\r\n first_name: contacts[i].first_name,\r\n last_name: contacts[i].last_name\r\n })\r\n }\r\n }\r\n\r\n return MtpApiManager.invokeApi('contacts.importContacts', {\r\n contacts: inputContacts,\r\n replace: false\r\n }).then(function (importedContactsResult) {\r\n saveApiUsers(importedContactsResult.users)\r\n\r\n var result = []\r\n angular.forEach(importedContactsResult.imported, function (importedContact) {\r\n onContactUpdated(importedContact.user_id, true)\r\n result.push(importedContact.user_id)\r\n })\r\n\r\n return result\r\n })\r\n } */\r\n\r\n /* public deleteContacts(userIds: number[]) {\r\n var ids: any[] = [];\r\n userIds.forEach((userId) => {\r\n ids.push(this.getUserInput(userId));\r\n })\r\n\r\n return apiManager.invokeApi('contacts.deleteContacts', {\r\n id: ids\r\n }).then(() => {\r\n userIds.forEach((userId) => {\r\n this.onContactUpdated(userId, false);\r\n });\r\n });\r\n } */\r\n\r\n public getTopPeers(): Promise<number[]> {\r\n if(this.getTopPeersPromise) return this.getTopPeersPromise;\r\n\r\n return this.getTopPeersPromise = appStateManager.getState().then((state) => {\r\n if(state?.topPeers?.length) {\r\n return state.topPeers;\r\n }\r\n\r\n return apiManager.invokeApi('contacts.getTopPeers', {\r\n correspondents: true,\r\n offset: 0,\r\n limit: 15,\r\n hash: 0,\r\n }).then((result) => {\r\n let peerIds: number[] = [];\r\n if(result._ === 'contacts.topPeers') {\r\n //console.log(result);\r\n this.saveApiUsers(result.users);\r\n appChatsManager.saveApiChats(result.chats);\r\n\r\n if(result.categories.length) {\r\n peerIds = result.categories[0].peers.map((topPeer) => {\r\n const peerId = appPeersManager.getPeerId(topPeer.peer);\r\n appStateManager.requestPeer(peerId, 'topPeer');\r\n return peerId;\r\n });\r\n }\r\n }\r\n \r\n appStateManager.pushToState('topPeers', peerIds);\r\n \r\n return peerIds;\r\n });\r\n });\r\n }\r\n\r\n public getBlocked(offset = 0, limit = 0) {\r\n return apiManager.invokeApiSingle('contacts.getBlocked', {offset, limit}).then(contactsBlocked => {\r\n this.saveApiUsers(contactsBlocked.users);\r\n appChatsManager.saveApiChats(contactsBlocked.chats);\r\n const count = contactsBlocked._ === 'contacts.blocked' ? contactsBlocked.users.length + contactsBlocked.chats.length : contactsBlocked.count;\r\n\r\n const peerIds = contactsBlocked.users.map(u => u.id).concat(contactsBlocked.chats.map(c => -c.id));\r\n\r\n return {count, peerIds};\r\n });\r\n }\r\n\r\n /* public searchContacts(query: string, limit = 20) {\r\n return Promise.all([\r\n this.getContacts(query),\r\n apiManager.invokeApi('contacts.search', {\r\n q: query,\r\n limit\r\n })\r\n ]).then(results => {\r\n const [myContacts, peers] = results;\r\n\r\n this.saveApiUsers(peers.users);\r\n appChatsManager.saveApiChats(peers.chats);\r\n\r\n // * contacts.search returns duplicates in my_results\r\n const myResults = new Set(myContacts.concat(peers.my_results.map(p => appPeersManager.getPeerID(p))));\r\n\r\n const out = {\r\n my_results: [...myResults].slice(0, limit),\r\n results: peers.results.map(p => appPeersManager.getPeerID(p))\r\n };\r\n\r\n return out;\r\n });\r\n } */\r\n public searchContacts(query: string, limit = 20) {\r\n return apiManager.invokeApiCacheable('contacts.search', {\r\n q: query,\r\n limit\r\n }, {cacheSeconds: 60}).then(peers => {\r\n this.saveApiUsers(peers.users);\r\n appChatsManager.saveApiChats(peers.chats);\r\n\r\n const out = {\r\n my_results: filterUnique(peers.my_results.map(p => appPeersManager.getPeerId(p))), // ! contacts.search returns duplicates in my_results\r\n results: peers.results.map(p => appPeersManager.getPeerId(p))\r\n };\r\n\r\n return out;\r\n });\r\n }\r\n\r\n private onContactUpdated(userId: number, isContact: boolean) {\r\n const curIsContact = this.isContact(userId);\r\n if(isContact !== curIsContact) {\r\n if(isContact) {\r\n this.pushContact(userId);\r\n } else {\r\n this.contactsList.delete(userId);\r\n }\r\n\r\n this.onContactsModified();\r\n\r\n rootScope.dispatchEvent('contacts_update', userId);\r\n }\r\n }\r\n\r\n public updateUsername(username: string) {\r\n return apiManager.invokeApi('account.updateUsername', {\r\n username\r\n }).then((user) => {\r\n this.saveApiUser(user);\r\n });\r\n }\r\n\r\n public setUserStatus(userId: number, offline: boolean) {\r\n if(this.isBot(userId)) {\r\n return;\r\n }\r\n\r\n const user = this.users[userId];\r\n if(user) {\r\n const status: any = offline ? {\r\n _: 'userStatusOffline',\r\n was_online: tsNow(true)\r\n } : {\r\n _: 'userStatusOnline',\r\n expires: tsNow(true) + 500\r\n };\r\n\r\n user.status = status;\r\n //user.sortStatus = this.getUserStatusForSort(user.status);\r\n rootScope.dispatchEvent('user_update', userId);\r\n }\r\n }\r\n\r\n public addContact(userId: number, first_name: string, last_name: string, phone: string, showPhone?: true) {\r\n return apiManager.invokeApi('contacts.addContact', {\r\n id: this.getUserInput(userId),\r\n first_name,\r\n last_name,\r\n phone,\r\n add_phone_privacy_exception: showPhone\r\n }).then((updates) => {\r\n apiUpdatesManager.processUpdateMessage(updates, {override: true});\r\n\r\n this.onContactUpdated(userId, true);\r\n });\r\n }\r\n\r\n public deleteContacts(userIds: number[]) {\r\n return apiManager.invokeApi('contacts.deleteContacts', {\r\n id: userIds.map(userId => this.getUserInput(userId))\r\n }).then((updates) => {\r\n apiUpdatesManager.processUpdateMessage(updates, {override: true});\r\n\r\n userIds.forEach(userId => {\r\n this.onContactUpdated(userId, false);\r\n });\r\n });\r\n }\r\n}\r\n\r\nconst appUsersManager = new AppUsersManager();\r\nMOUNT_CLASS_TO.appUsersManager = appUsersManager;\r\nexport default appUsersManager\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport findUpAttribute from \"../helpers/dom/findUpAttribute\";\r\nimport getRichValue from \"../helpers/dom/getRichValue\";\r\nimport isInputEmpty from \"../helpers/dom/isInputEmpty\";\r\nimport { debounce } from \"../helpers/schedulers\";\r\nimport { i18n, LangPackKey, _i18n } from \"../lib/langPack\";\r\nimport RichTextProcessor from \"../lib/richtextprocessor\";\r\n\r\nlet init = () => {\r\n document.addEventListener('paste', (e) => {\r\n if(!findUpAttribute(e.target, 'contenteditable=\"true\"')) {\r\n return;\r\n }\r\n //console.log('document paste');\r\n\r\n //console.log('messageInput paste');\r\n\r\n e.preventDefault();\r\n // @ts-ignore\r\n let text = (e.originalEvent || e).clipboardData.getData('text/plain');\r\n\r\n let entities = RichTextProcessor.parseEntities(text);\r\n //console.log('messageInput paste', text, entities);\r\n entities = entities.filter(e => e._ === 'messageEntityEmoji' || e._ === 'messageEntityLinebreak');\r\n //text = RichTextProcessor.wrapEmojiText(text);\r\n text = RichTextProcessor.wrapRichText(text, {entities, noLinks: true, wrappingDraft: true});\r\n\r\n // console.log('messageInput paste after', text);\r\n\r\n // @ts-ignore\r\n //let html = (e.originalEvent || e).clipboardData.getData('text/html');\r\n\r\n // @ts-ignore\r\n //console.log('paste text', text, );\r\n window.document.execCommand('insertHTML', false, text);\r\n });\r\n\r\n init = null;\r\n};\r\n\r\n// ! it doesn't respect symbols other than strongs\r\n/* const checkAndSetRTL = (input: HTMLElement) => {\r\n //const isEmpty = isInputEmpty(input);\r\n //console.log('input', isEmpty);\r\n\r\n //const char = [...getRichValue(input)][0];\r\n const char = (input instanceof HTMLInputElement ? input.value : input.innerText)[0];\r\n let direction = 'ltr';\r\n if(char && checkRTL(char)) {\r\n direction = 'rtl';\r\n }\r\n\r\n //console.log('RTL', direction, char);\r\n\r\n input.style.direction = direction;\r\n}; */\r\n\r\nexport enum InputState {\r\n Neutral = 0,\r\n Valid = 1,\r\n Error = 2\r\n};\r\n\r\nexport type InputFieldOptions = {\r\n placeholder?: LangPackKey, \r\n label?: LangPackKey, \r\n labelOptions?: any[],\r\n labelText?: string,\r\n name?: string, \r\n maxLength?: number, \r\n showLengthOn?: number,\r\n plainText?: true,\r\n animate?: true\r\n};\r\n\r\nclass InputField {\r\n public container: HTMLElement;\r\n public input: HTMLElement;\r\n public inputFake: HTMLElement;\r\n public label: HTMLLabelElement;\r\n\r\n public originalValue: string;\r\n\r\n //public onLengthChange: (length: number, isOverflow: boolean) => void;\r\n protected wasInputFakeClientHeight: number;\r\n protected showScrollDebounced: () => void;\r\n\r\n constructor(public options: InputFieldOptions = {}) {\r\n this.container = document.createElement('div');\r\n this.container.classList.add('input-field');\r\n\r\n if(options.maxLength) {\r\n options.showLengthOn = Math.round(options.maxLength / 3);\r\n }\r\n\r\n const {placeholder, maxLength, showLengthOn, name, plainText} = options;\r\n\r\n let label = options.label || options.labelText;\r\n\r\n let input: HTMLElement;\r\n if(!plainText) {\r\n if(init) {\r\n init();\r\n }\r\n\r\n this.container.innerHTML = `\r\n <div contenteditable=\"true\" class=\"input-field-input\"></div>\r\n `;\r\n\r\n input = this.container.firstElementChild as HTMLElement;\r\n const observer = new MutationObserver(() => {\r\n //checkAndSetRTL(input);\r\n\r\n if(processInput) {\r\n processInput();\r\n }\r\n });\r\n\r\n // * because if delete all characters there will br left\r\n input.addEventListener('input', () => {\r\n if(isInputEmpty(input)) {\r\n input.innerHTML = '';\r\n }\r\n\r\n if(this.inputFake) {\r\n this.inputFake.innerHTML = input.innerHTML;\r\n this.onFakeInput();\r\n }\r\n });\r\n \r\n // ! childList for paste first symbol\r\n observer.observe(input, {characterData: true, childList: true, subtree: true});\r\n\r\n if(options.animate) {\r\n input.classList.add('scrollable', 'scrollable-y');\r\n this.wasInputFakeClientHeight = 0;\r\n this.showScrollDebounced = debounce(() => this.input.classList.remove('no-scrollbar'), 150, false, true);\r\n this.inputFake = document.createElement('div');\r\n this.inputFake.setAttribute('contenteditable', 'true');\r\n this.inputFake.className = input.className + ' input-field-input-fake';\r\n }\r\n } else {\r\n this.container.innerHTML = `\r\n <input type=\"text\" ${name ? `name=\"${name}\"` : ''} autocomplete=\"off\" ${label ? 'required=\"\"' : ''} class=\"input-field-input\">\r\n `;\r\n\r\n input = this.container.firstElementChild as HTMLElement;\r\n //input.addEventListener('input', () => checkAndSetRTL(input));\r\n }\r\n\r\n input.setAttribute('dir', 'auto');\r\n\r\n if(placeholder) {\r\n _i18n(input, placeholder, undefined, 'placeholder');\r\n\r\n if(this.inputFake) {\r\n _i18n(this.inputFake, placeholder, undefined, 'placeholder');\r\n }\r\n }\r\n\r\n if(label || placeholder) {\r\n const border = document.createElement('div');\r\n border.classList.add('input-field-border');\r\n this.container.append(border);\r\n }\r\n\r\n if(label) {\r\n this.label = document.createElement('label');\r\n this.setLabel();\r\n this.container.append(this.label);\r\n }\r\n\r\n let processInput: () => void;\r\n if(maxLength) {\r\n const labelEl = this.container.lastElementChild as HTMLLabelElement;\r\n let showingLength = false;\r\n\r\n processInput = () => {\r\n const wasError = input.classList.contains('error');\r\n // * https://stackoverflow.com/a/54369605 #2 to count emoji as 1 symbol\r\n const inputLength = plainText ? (input as HTMLInputElement).value.length : [...getRichValue(input, false).value].length;\r\n const diff = maxLength - inputLength;\r\n const isError = diff < 0;\r\n input.classList.toggle('error', isError);\r\n\r\n //this.onLengthChange && this.onLengthChange(inputLength, isError);\r\n\r\n if(isError || diff <= showLengthOn) {\r\n this.setLabel();\r\n labelEl.append(` (${maxLength - inputLength})`);\r\n if(!showingLength) showingLength = true;\r\n } else if((wasError && !isError) || showingLength) {\r\n this.setLabel();\r\n showingLength = false;\r\n }\r\n };\r\n\r\n input.addEventListener('input', processInput);\r\n }\r\n\r\n this.input = input;\r\n }\r\n\r\n public select() {\r\n if((this.input as HTMLInputElement).value) { // * avoid selecting whole empty field on iOS devices\r\n (this.input as HTMLInputElement).select(); // * select text\r\n }\r\n }\r\n\r\n public setLabel() {\r\n this.label.textContent = '';\r\n if(this.options.labelText) {\r\n this.label.innerHTML = this.options.labelText;\r\n } else {\r\n this.label.append(i18n(this.options.label, this.options.labelOptions));\r\n }\r\n }\r\n\r\n public onFakeInput() {\r\n const {scrollHeight, clientHeight} = this.inputFake;\r\n if(this.wasInputFakeClientHeight && this.wasInputFakeClientHeight !== clientHeight) {\r\n this.input.classList.add('no-scrollbar'); // ! в сафари может вообще не появиться скролл после анимации, так как ему нужен полный reflow блока с overflow.\r\n this.showScrollDebounced();\r\n }\r\n\r\n this.wasInputFakeClientHeight = clientHeight;\r\n this.input.style.height = scrollHeight ? scrollHeight + 'px' : '';\r\n }\r\n\r\n get value() {\r\n return this.options.plainText ? (this.input as HTMLInputElement).value : getRichValue(this.input, false).value;\r\n //return getRichValue(this.input);\r\n }\r\n\r\n set value(value: string) {\r\n this.setValueSilently(value, false);\r\n\r\n const event = new Event('input', {bubbles: true, cancelable: true});\r\n this.input.dispatchEvent(event);\r\n }\r\n\r\n public setValueSilently(value: string, fireFakeInput = true) {\r\n if(this.options.plainText) {\r\n (this.input as HTMLInputElement).value = value;\r\n } else {\r\n this.input.innerHTML = value;\r\n \r\n if(this.inputFake) {\r\n this.inputFake.innerHTML = value;\r\n\r\n if(fireFakeInput) {\r\n this.onFakeInput();\r\n }\r\n }\r\n }\r\n }\r\n\r\n public isValid() {\r\n return !this.input.classList.contains('error') && this.value !== this.originalValue;\r\n }\r\n\r\n public setOriginalValue(value: InputField['originalValue'] = '', silent = false) {\r\n this.originalValue = value;\r\n\r\n if(!this.options.plainText) {\r\n value = RichTextProcessor.wrapDraftText(value);\r\n }\r\n\r\n if(silent) {\r\n this.setValueSilently(value, false); \r\n } else {\r\n this.value = value;\r\n }\r\n }\r\n\r\n public setState(state: InputState, label?: LangPackKey) {\r\n if(label) {\r\n this.label.textContent = '';\r\n this.label.append(i18n(label, this.options.labelOptions));\r\n }\r\n\r\n this.input.classList.toggle('error', !!(state & InputState.Error));\r\n this.input.classList.toggle('valid', !!(state & InputState.Valid));\r\n }\r\n\r\n public setError(label?: LangPackKey) {\r\n this.setState(InputState.Error, label);\r\n }\r\n}\r\n\r\nexport default InputField;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\r\nimport { isObject, safeReplaceObject, copy, deepEqual } from \"../../helpers/object\";\r\nimport { ChannelParticipant, Chat, ChatAdminRights, ChatBannedRights, ChatParticipant, ChatPhoto, InputChannel, InputChatPhoto, InputFile, InputPeer, Update, Updates } from \"../../layer\";\r\nimport apiManagerProxy from \"../mtproto/mtprotoworker\";\r\nimport apiManager from '../mtproto/mtprotoworker';\r\nimport { RichTextProcessor } from \"../richtextprocessor\";\r\nimport rootScope from \"../rootScope\";\r\nimport apiUpdatesManager from \"./apiUpdatesManager\";\r\nimport appPeersManager from \"./appPeersManager\";\r\nimport appStateManager from \"./appStateManager\";\r\nimport appUsersManager from \"./appUsersManager\";\r\n\r\nexport type Channel = Chat.channel;\r\n\r\nexport type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags'] | 'change_type' | 'change_permissions' | 'delete_chat' | 'view_participants';\r\n\r\nexport class AppChatsManager {\r\n private storage = appStateManager.storages.chats;\r\n \r\n private chats: {[id: number]: Chat.channel | Chat.chat | any};\r\n //private usernames: any;\r\n //private channelAccess: any;\r\n //private megagroups: {[id: number]: true};\r\n\r\n constructor() {\r\n this.clear(true);\r\n\r\n rootScope.addMultipleEventsListeners({\r\n /* updateChannel: (update) => {\r\n const channelId = update.channel_id;\r\n //console.log('updateChannel:', update);\r\n rootScope.broadcast('channel_settings', {channelId});\r\n }, */\r\n\r\n updateChannelParticipant: (update) => {\r\n apiManagerProxy.clearCache('channels.getParticipants', (params) => {\r\n return (params.channel as InputChannel.inputChannel).channel_id === update.channel_id;\r\n });\r\n },\r\n\r\n updateChatDefaultBannedRights: (update) => {\r\n const chatId = -appPeersManager.getPeerId(update.peer);\r\n const chat: Chat.chat = this.chats[chatId];\r\n if(chat) {\r\n chat.default_banned_rights = update.default_banned_rights;\r\n rootScope.dispatchEvent('chat_update', chatId);\r\n }\r\n }\r\n });\r\n\r\n appStateManager.getState().then((state) => {\r\n const chats = appStateManager.storagesResults.chats;\r\n if(chats.length) {\r\n for(let i = 0, length = chats.length; i < length; ++i) {\r\n const chat = chats[i];\r\n if(chat) {\r\n this.chats[chat.id] = chat;\r\n }\r\n }\r\n }\r\n\r\n appStateManager.addEventListener('peerNeeded', (peerId: number) => {\r\n if(peerId > 0 || this.storage.getFromCache(-peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.set({\r\n [-peerId]: this.getChat(-peerId)\r\n });\r\n });\r\n\r\n appStateManager.addEventListener('peerUnneeded', (peerId: number) => {\r\n if(peerId > 0 || !this.storage.getFromCache(-peerId)) {\r\n return;\r\n }\r\n\r\n this.storage.delete(-peerId);\r\n });\r\n });\r\n }\r\n\r\n public clear(init = false) {\r\n if(!init) {\r\n const chats = appStateManager.storagesResults.chats;\r\n for(const _chatId in this.chats) {\r\n const chatId = +_chatId;\r\n if(!chatId) continue;\r\n if(!appStateManager.isPeerNeeded(-chatId)) {\r\n /* const chat = this.chats[chatId];\r\n if(chat.username) {\r\n delete this.usernames[cleanUsername(chat.username)];\r\n } */\r\n \r\n chats.findAndSplice((chat) => chat.id === chatId);\r\n this.storage.delete(chatId);\r\n delete this.chats[chatId];\r\n }\r\n }\r\n } else {\r\n this.chats = {};\r\n }\r\n }\r\n\r\n public saveApiChats(apiChats: any[], override?: boolean) {\r\n apiChats.forEach(chat => this.saveApiChat(chat, override));\r\n }\r\n\r\n public saveApiChat(chat: Chat, override?: boolean) {\r\n if(chat._ === 'chatEmpty') return;\r\n /* if(chat._ !== 'chat' && chat._ !== 'channel') {\r\n return;\r\n } */\r\n \r\n // * exclude from state\r\n // defineNotNumerableProperties(chat, ['rTitle', 'initials']);\r\n\r\n const oldChat: Exclude<Chat, Chat.chatEmpty> = this.chats[chat.id];\r\n\r\n /* if(oldChat && !override) {\r\n return;\r\n } */\r\n\r\n if((chat as Chat.chat).pFlags === undefined) {\r\n (chat as Chat.chat).pFlags = {};\r\n }\r\n\r\n if((chat as Chat.channel).pFlags.min && oldChat !== undefined) {\r\n return;\r\n }\r\n\r\n chat.initials = RichTextProcessor.getAbbreviation(chat.title);\r\n\r\n if(chat._ === 'channel' &&\r\n chat.participants_count === undefined &&\r\n oldChat !== undefined &&\r\n (oldChat as Chat.channel).participants_count) {\r\n chat.participants_count = (oldChat as Chat.channel).participants_count;\r\n }\r\n\r\n /* if(chat.username) {\r\n let searchUsername = searchIndexManager.cleanUsername(chat.username);\r\n this.usernames[searchUsername] = chat.id;\r\n } */\r\n\r\n let changedPhoto = false, changedTitle = false;\r\n if(oldChat === undefined) {\r\n this.chats[chat.id] = chat;\r\n } else {\r\n const oldPhotoId = ((oldChat as Chat.chat).photo as ChatPhoto.chatPhoto)?.photo_id;\r\n const newPhotoId = ((chat as Chat.chat).photo as ChatPhoto.chatPhoto)?.photo_id;\r\n if(oldPhotoId !== newPhotoId) {\r\n changedPhoto = true;\r\n }\r\n\r\n if(oldChat.title !== chat.title) {\r\n changedTitle = true;\r\n }\r\n\r\n safeReplaceObject(oldChat, chat);\r\n rootScope.dispatchEvent('chat_update', chat.id);\r\n }\r\n\r\n if(changedPhoto) {\r\n rootScope.dispatchEvent('avatar_update', -chat.id);\r\n }\r\n\r\n if(changedTitle) {\r\n rootScope.dispatchEvent('peer_title_edit', -chat.id);\r\n }\r\n\r\n if(appStateManager.isPeerNeeded(-chat.id)) {\r\n this.storage.set({\r\n [chat.id]: chat\r\n });\r\n }\r\n }\r\n\r\n public getChat(id: number) {\r\n if(id < 0) id = -id;\r\n return this.chats[id] || {_: 'chatEmpty', id, deleted: true, access_hash: '', pFlags: {}/* this.channelAccess[id] */};\r\n }\r\n\r\n public combineParticipantBannedRights(id: number, rights: ChatBannedRights) {\r\n const chat: Chat.channel = this.getChat(id);\r\n\r\n if(chat.default_banned_rights) {\r\n rights = copy(rights);\r\n const defaultRights = chat.default_banned_rights.pFlags;\r\n for(let i in defaultRights) {\r\n // @ts-ignore\r\n rights.pFlags[i] = defaultRights[i];\r\n }\r\n }\r\n\r\n return rights;\r\n }\r\n\r\n public hasRights(id: number, action: ChatRights, rights?: ChatAdminRights | ChatBannedRights, isThread?: boolean) {\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'chatEmpty') return false;\r\n\r\n if(chat._ === 'chatForbidden' ||\r\n chat._ === 'channelForbidden' ||\r\n (chat as Chat.chat).pFlags.kicked ||\r\n (chat.pFlags.left && !(chat as Chat.channel).pFlags.megagroup)) {\r\n return false;\r\n }\r\n\r\n if((chat as Chat.chat).pFlags.deactivated && action !== 'view_messages') {\r\n return false;\r\n }\r\n\r\n if(chat.pFlags.creator && rights === undefined) {\r\n return true;\r\n }\r\n\r\n if(!rights) {\r\n rights = chat.admin_rights || (chat as Chat.channel).banned_rights || chat.default_banned_rights;\r\n\r\n if(!rights) {\r\n return false;\r\n }\r\n }\r\n\r\n let myFlags: Partial<{[flag in keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags']]: true}> = {};\r\n if(rights) {\r\n myFlags = rights.pFlags as any;\r\n }\r\n\r\n switch(action) {\r\n case 'embed_links':\r\n case 'send_games':\r\n case 'send_gifs':\r\n case 'send_inline':\r\n case 'send_media':\r\n case 'send_messages':\r\n case 'send_polls':\r\n case 'send_stickers': {\r\n if(!isThread && chat.pFlags.left) {\r\n return false;\r\n }\r\n\r\n if(rights._ === 'chatBannedRights' && myFlags[action]) {\r\n return false;\r\n }\r\n\r\n if(chat._ === 'channel') {\r\n if(!chat.pFlags.megagroup && !myFlags.post_messages) {\r\n return false;\r\n }\r\n }\r\n\r\n break;\r\n }\r\n\r\n // * revoke foreign messages\r\n case 'delete_messages': {\r\n return !!myFlags.delete_messages;\r\n }\r\n\r\n case 'pin_messages': {\r\n return rights._ === 'chatAdminRights' ? myFlags[action] || !!myFlags.post_messages : !myFlags[action];\r\n }\r\n\r\n case 'invite_users':\r\n case 'change_info': {\r\n return rights._ === 'chatAdminRights' ? myFlags[action] : !myFlags[action];\r\n }\r\n\r\n // * only creator can do that\r\n case 'change_type':\r\n case 'delete_chat': {\r\n return false;\r\n }\r\n\r\n case 'change_permissions': {\r\n return rights._ === 'chatAdminRights' && myFlags['ban_users'];\r\n }\r\n\r\n case 'view_participants': {\r\n return !!(chat._ === 'chat' || !chat.pFlags.broadcast || chat.pFlags.creator || chat.admin_rights);\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n public editChatDefaultBannedRights(id: number, banned_rights: ChatBannedRights) {\r\n const chat: Chat.chat = this.getChat(id);\r\n if(chat.default_banned_rights) {\r\n if(chat.default_banned_rights.until_date === banned_rights.until_date && deepEqual(chat.default_banned_rights.pFlags, banned_rights.pFlags)) {\r\n return Promise.resolve();\r\n }\r\n }\r\n \r\n return apiManager.invokeApi('messages.editChatDefaultBannedRights', {\r\n peer: appPeersManager.getInputPeerById(-id),\r\n banned_rights\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n /* public resolveUsername(username: string) {\r\n return this.usernames[username] || 0;\r\n } */\r\n\r\n /* public saveChannelAccess(id: number, accessHash: string) {\r\n this.channelAccess[id] = accessHash;\r\n } */\r\n\r\n /* public saveIsMegagroup(id: number) {\r\n this.megagroups[id] = true;\r\n } */\r\n\r\n public isChannel(id: number) {\r\n const chat = this.chats[id];\r\n return chat && (chat._ === 'channel' || chat._ === 'channelForbidden')/* || this.channelAccess[id] */;\r\n }\r\n\r\n public isMegagroup(id: number) {\r\n /* if(this.megagroups[id]) {\r\n return true;\r\n } */\r\n\r\n const chat = this.chats[id];\r\n return chat && chat._ === 'channel' && chat.pFlags.megagroup;\r\n }\r\n\r\n public isBroadcast(id: number) {\r\n return this.isChannel(id) && !this.isMegagroup(id);\r\n }\r\n\r\n public isInChat(id: number) {\r\n let good = true;\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'channelForbidden' \r\n || chat._ === 'chatForbidden' \r\n || chat._ === 'chatEmpty' \r\n || (chat as Chat.chat).pFlags.left \r\n || (chat as Chat.chat).pFlags.kicked \r\n || (chat as Chat.chat).pFlags.deactivated) {\r\n good = false;\r\n }\r\n\r\n return good;\r\n }\r\n\r\n public getChannelInput(id: number): InputChannel {\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'chatEmpty' || !(chat as Chat.channel).access_hash) {\r\n return {\r\n _: 'inputChannelEmpty'\r\n };\r\n } else {\r\n return {\r\n _: 'inputChannel',\r\n channel_id: id,\r\n access_hash: (chat as Chat.channel).access_hash/* || this.channelAccess[id] */ || '0'\r\n };\r\n }\r\n }\r\n\r\n public getChatInputPeer(id: number): InputPeer.inputPeerChat {\r\n return {\r\n _: 'inputPeerChat',\r\n chat_id: id\r\n };\r\n }\r\n\r\n public getChannelInputPeer(id: number): InputPeer.inputPeerChannel {\r\n return {\r\n _: 'inputPeerChannel',\r\n channel_id: id,\r\n access_hash: this.getChat(id).access_hash/* || this.channelAccess[id] */ || 0\r\n };\r\n }\r\n\r\n public hasChat(id: number, allowMin?: true) {\r\n const chat = this.chats[id]\r\n return isObject(chat) && (allowMin || !chat.pFlags.min);\r\n }\r\n\r\n public getChatPhoto(id: number) {\r\n const chat: Chat.chat = this.getChat(id);\r\n\r\n return chat && chat.photo || {\r\n _: 'chatPhotoEmpty'\r\n };\r\n }\r\n\r\n public getChatString(id: number) {\r\n const chat = this.getChat(id);\r\n if(this.isChannel(id)) {\r\n return (this.isMegagroup(id) ? 's' : 'c') + id + '_' + chat.access_hash;\r\n }\r\n return 'g' + id;\r\n }\r\n\r\n /* public wrapForFull(id: number, fullChat: any) {\r\n const chatFull = copy(fullChat);\r\n const chat = this.getChat(id);\r\n\r\n if(!chatFull.participants_count) {\r\n chatFull.participants_count = chat.participants_count;\r\n }\r\n\r\n if(chatFull.participants &&\r\n chatFull.participants._ === 'chatParticipants') {\r\n chatFull.participants.participants = this.wrapParticipants(id, chatFull.participants.participants);\r\n }\r\n\r\n if(chatFull.about) {\r\n chatFull.rAbout = RichTextProcessor.wrapRichText(chatFull.about, {noLinebreaks: true});\r\n }\r\n\r\n //chatFull.peerString = this.getChatString(id);\r\n chatFull.chat = chat;\r\n\r\n return chatFull;\r\n }\r\n\r\n public wrapParticipants(id: number, participants: any[]) {\r\n const chat = this.getChat(id);\r\n const myId = appUsersManager.getSelf().id;\r\n if(this.isChannel(id)) {\r\n const isAdmin = chat.pFlags.creator;\r\n participants.forEach((participant) => {\r\n participant.canLeave = myId === participant.user_id;\r\n participant.canKick = isAdmin && participant._ === 'channelParticipant';\r\n\r\n // just for order by last seen\r\n participant.user = appUsersManager.getUser(participant.user_id);\r\n });\r\n } else {\r\n const isAdmin = chat.pFlags.creator || chat.pFlags.admins_enabled && chat.pFlags.admin;\r\n participants.forEach((participant) => {\r\n participant.canLeave = myId === participant.user_id;\r\n participant.canKick = !participant.canLeave && (\r\n chat.pFlags.creator ||\r\n participant._ === 'chatParticipant' && (isAdmin || myId === participant.inviter_id)\r\n );\r\n\r\n // just for order by last seen\r\n participant.user = appUsersManager.getUser(participant.user_id);\r\n });\r\n }\r\n\r\n return participants;\r\n } */\r\n\r\n public createChannel(title: string, about: string): Promise<number> {\r\n return apiManager.invokeApi('channels.createChannel', {\r\n broadcast: true,\r\n title,\r\n about\r\n }).then((updates) => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n\r\n const channelId = (updates as any).chats[0].id;\r\n rootScope.dispatchEvent('history_focus', {peerId: -channelId});\r\n\r\n return channelId;\r\n });\r\n }\r\n\r\n public inviteToChannel(id: number, userIds: number[]) {\r\n const input = this.getChannelInput(id);\r\n const usersInputs = userIds.map(u => appUsersManager.getUserInput(u));\r\n\r\n return apiManager.invokeApi('channels.inviteToChannel', {\r\n channel: input,\r\n users: usersInputs\r\n }).then(updates => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n });\r\n }\r\n\r\n public createChat(title: string, userIds: number[]): Promise<number> {\r\n return apiManager.invokeApi('messages.createChat', {\r\n users: userIds.map(u => appUsersManager.getUserInput(u)),\r\n title\r\n }).then(updates => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n\r\n const chatId = (updates as any as Updates.updates).chats[0].id;\r\n rootScope.dispatchEvent('history_focus', {peerId: -chatId});\r\n\r\n return chatId;\r\n });\r\n }\r\n\r\n private onChatUpdated = (chatId: number, updates: any) => {\r\n //console.log('onChatUpdated', chatId, updates);\r\n\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n if(updates &&\r\n /* updates.updates &&\r\n updates.updates.length && */\r\n this.isChannel(chatId)) {\r\n rootScope.dispatchEvent('invalidate_participants', chatId);\r\n }\r\n };\r\n\r\n public leaveChannel(id: number) {\r\n return apiManager.invokeApi('channels.leaveChannel', {\r\n channel: this.getChannelInput(id)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public joinChannel(id: number) {\r\n return apiManager.invokeApi('channels.joinChannel', {\r\n channel: this.getChannelInput(id)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public addChatUser(id: number, userId: number, fwdLimit = 100) {\r\n return apiManager.invokeApi('messages.addChatUser', {\r\n chat_id: id,\r\n user_id: appUsersManager.getUserInput(userId),\r\n fwd_limit: fwdLimit\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public deleteChatUser(id: number, userId: number) {\r\n return apiManager.invokeApi('messages.deleteChatUser', {\r\n chat_id: id,\r\n user_id: appUsersManager.getUserInput(userId)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public leaveChat(id: number) {\r\n return this.deleteChatUser(id, appUsersManager.getSelf().id);\r\n }\r\n\r\n public leave(id: number) {\r\n return this.isChannel(id) ? this.leaveChannel(id) : this.leaveChat(id);\r\n }\r\n\r\n public delete(id: number) {\r\n return this.isChannel(id) ? this.deleteChannel(id) : this.deleteChat(id);\r\n }\r\n\r\n public deleteChannel(id: number) {\r\n return apiManager.invokeApi('channels.deleteChannel', {\r\n channel: this.getChannelInput(id)\r\n }).then(this.onChatUpdated.bind(this, id));\r\n }\r\n\r\n public deleteChat(id: number) {\r\n //return this.leaveChat(id).then(() => {\r\n return apiManager.invokeApi('messages.deleteChat', {\r\n chat_id: id\r\n });\r\n //});\r\n }\r\n\r\n public migrateChat(id: number): Promise<number> {\r\n const chat: Chat = this.getChat(id);\r\n if(chat._ === 'channel') return Promise.resolve(chat.id);\r\n return apiManager.invokeApi('messages.migrateChat', {\r\n chat_id: id\r\n }).then((updates) => {\r\n this.onChatUpdated(id, updates);\r\n const update: Update.updateChannel = (updates as Updates.updates).updates.find(u => u._ === 'updateChannel') as any;\r\n return update.channel_id;\r\n });\r\n }\r\n\r\n public updateUsername(id: number, username: string) {\r\n return apiManager.invokeApi('channels.updateUsername', {\r\n channel: this.getChannelInput(id),\r\n username\r\n }).then((bool) => {\r\n if(bool) {\r\n const chat: Chat.channel = this.getChat(id);\r\n chat.username = username;\r\n }\r\n\r\n return bool;\r\n });\r\n }\r\n\r\n public editPhoto(id: number, inputFile: InputFile) {\r\n const inputChatPhoto: InputChatPhoto = {\r\n _: 'inputChatUploadedPhoto',\r\n file: inputFile\r\n };\r\n\r\n let promise: any;\r\n if(this.isChannel(id)) {\r\n promise = apiManager.invokeApi('channels.editPhoto', {\r\n channel: this.getChannelInput(id),\r\n photo: inputChatPhoto\r\n });\r\n } else {\r\n promise = apiManager.invokeApi('messages.editChatPhoto', {\r\n chat_id: id,\r\n photo: inputChatPhoto\r\n });\r\n }\r\n\r\n return promise.then((updates: any) => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n });\r\n }\r\n\r\n public editTitle(id: number, title: string) {\r\n let promise: any;\r\n\r\n if(this.isChannel(id)) {\r\n promise = apiManager.invokeApi('channels.editTitle', {\r\n channel: this.getChannelInput(id),\r\n title\r\n });\r\n } else {\r\n promise = apiManager.invokeApi('messages.editChatTitle', {\r\n chat_id: id,\r\n title\r\n });\r\n }\r\n\r\n return promise.then((updates: any) => {\r\n apiUpdatesManager.processUpdateMessage(updates);\r\n });\r\n }\r\n\r\n public editAbout(id: number, about: string) {\r\n return apiManager.invokeApi('messages.editChatAbout', {\r\n peer: appPeersManager.getInputPeerById(-id),\r\n about\r\n }).then(bool => {\r\n //apiUpdatesManager.processUpdateMessage(updates);\r\n rootScope.dispatchEvent('peer_bio_edit', -id);\r\n });\r\n }\r\n\r\n public getParticipantPeerId(participant: ChannelParticipant | ChatParticipant) {\r\n const peerId = (participant as ChannelParticipant.channelParticipantBanned).peer ? \r\n appPeersManager.getPeerId((participant as ChannelParticipant.channelParticipantBanned).peer) : \r\n (participant as ChatParticipant.chatParticipant).user_id;\r\n return peerId;\r\n }\r\n\r\n public editBanned(id: number, participant: number | ChannelParticipant, banned_rights: ChatBannedRights) {\r\n const peerId = typeof(participant) === 'number' ? participant : this.getParticipantPeerId(participant);\r\n return apiManager.invokeApi('channels.editBanned', {\r\n channel: this.getChannelInput(id),\r\n participant: appPeersManager.getInputPeerById(peerId),\r\n banned_rights\r\n }).then((updates) => {\r\n this.onChatUpdated(id, updates);\r\n\r\n if(typeof(participant) !== 'number') {\r\n const timestamp = Date.now() / 1000 | 0;\r\n apiUpdatesManager.processLocalUpdate({\r\n _: 'updateChannelParticipant',\r\n channel_id: id,\r\n date: timestamp,\r\n actor_id: undefined,\r\n qts: undefined,\r\n user_id: peerId,\r\n prev_participant: participant,\r\n new_participant: Object.keys(banned_rights.pFlags).length ? {\r\n _: 'channelParticipantBanned',\r\n date: timestamp,\r\n banned_rights,\r\n kicked_by: appUsersManager.getSelf().id,\r\n peer: appPeersManager.getOutputPeer(peerId),\r\n pFlags: {}\r\n } : undefined\r\n });\r\n }\r\n });\r\n }\r\n\r\n public clearChannelParticipantBannedRights(id: number, participant: number | ChannelParticipant) {\r\n return this.editBanned(id, participant, {\r\n _: 'chatBannedRights',\r\n until_date: 0,\r\n pFlags: {}\r\n });\r\n }\r\n \r\n public kickFromChannel(id: number, participant: number | ChannelParticipant) {\r\n return this.editBanned(id, participant, {\r\n _: 'chatBannedRights',\r\n until_date: 0,\r\n pFlags: {\r\n view_messages: true\r\n }\r\n });\r\n }\r\n}\r\n\r\nconst appChatsManager = new AppChatsManager();\r\nMOUNT_CLASS_TO.appChatsManager = appChatsManager;\r\nexport default appChatsManager;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport type { ChatPhoto, DialogPeer, InputDialogPeer, InputNotifyPeer, InputPeer, Peer, Update, UserProfilePhoto } from \"../../layer\";\r\nimport type { LangPackKey } from \"../langPack\";\r\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\r\nimport { isObject } from \"../../helpers/object\";\r\nimport { RichTextProcessor } from \"../richtextprocessor\";\r\nimport rootScope from \"../rootScope\";\r\nimport appChatsManager from \"./appChatsManager\";\r\nimport appUsersManager from \"./appUsersManager\";\r\nimport I18n from '../langPack';\r\n\r\n// https://github.com/eelcohn/Telegram-API/wiki/Calculating-color-for-a-Telegram-user-on-IRC\r\n/*\r\n HTML-color IRC-color Description\r\n #c03d33 4 red\r\n #4fad2d 3 green\r\n #d09306 7 yellow\r\n #168acd 10 blue\r\n #8544d6 6 purple\r\n #cd4073 13 pink\r\n #2996ad 11 sea\r\n #ce671b 5 orange\r\n */\r\nconst DialogColorsFg = ['#fc5c51', '#0fb297', '#d09306', '#3d72ed', '#895dd5', '#cd4073', '#00c1a6', '#fa790f'];\r\nconst DialogColors = ['red', 'green', 'yellow', 'blue', 'violet', 'pink', 'cyan', 'orange'];\r\nconst DialogColorsMap = [0, 7, 4, 1, 6, 3, 5];\r\n\r\nexport type PeerType = 'channel' | 'chat' | 'megagroup' | 'group' | 'saved';\r\nexport class AppPeersManager {\r\n constructor() {\r\n rootScope.addMultipleEventsListeners({\r\n updatePeerBlocked: (update) => {\r\n rootScope.dispatchEvent('peer_block', {peerId: this.getPeerId(update.peer_id), blocked: update.blocked});\r\n }\r\n });\r\n }\r\n /* public savePeerInstance(peerId: number, instance: any) {\r\n if(peerId < 0) appChatsManager.saveApiChat(instance);\r\n else appUsersManager.saveApiUser(instance);\r\n } */\r\n\r\n public canPinMessage(peerId: number) {\r\n return peerId > 0 || appChatsManager.hasRights(-peerId, 'pin_messages');\r\n }\r\n\r\n public getPeerPhoto(peerId: number): UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto {\r\n const photo = peerId > 0\r\n ? appUsersManager.getUserPhoto(peerId)\r\n : appChatsManager.getChatPhoto(-peerId);\r\n\r\n return photo._ !== 'chatPhotoEmpty' && photo._ !== 'userProfilePhotoEmpty' ? photo : null;\r\n }\r\n\r\n public getPeerMigratedTo(peerId: number) {\r\n if(peerId >= 0) {\r\n return false;\r\n }\r\n\r\n let chat = appChatsManager.getChat(-peerId);\r\n if(chat && chat.migrated_to && chat.pFlags.deactivated) {\r\n return this.getPeerId(chat.migrated_to);\r\n }\r\n \r\n return false;\r\n }\r\n\r\n public getPeerTitle(peerId: number | any, plainText = false, onlyFirstName = false) {\r\n if(!peerId) {\r\n peerId = rootScope.myId;\r\n }\r\n \r\n let peer: any = {}; \r\n if(!isObject(peerId)) {\r\n peer = this.getPeer(peerId);\r\n } else peer = peerId;\r\n\r\n let title = '';\r\n if(peerId > 0) {\r\n if(peer.first_name) title += peer.first_name;\r\n if(peer.last_name) title += ' ' + peer.last_name;\r\n \r\n if(!title) title = peer.pFlags.deleted ? I18n.format('HiddenName', true) : peer.username;\r\n else title = title.trim();\r\n } else {\r\n title = peer.title;\r\n }\r\n\r\n if(onlyFirstName) {\r\n title = title.split(' ')[0];\r\n }\r\n \r\n return plainText ? title : RichTextProcessor.wrapEmojiText(title);\r\n }\r\n \r\n public getOutputPeer(peerId: number): Peer {\r\n if(peerId > 0) {\r\n return {_: 'peerUser', user_id: peerId};\r\n }\r\n\r\n let chatId = -peerId;\r\n if(appChatsManager.isChannel(chatId)) {\r\n return {_: 'peerChannel', channel_id: chatId};\r\n }\r\n\r\n return {_: 'peerChat', chat_id: chatId};\r\n }\r\n\r\n public getPeerString(peerId: number) {\r\n if(peerId > 0) {\r\n return appUsersManager.getUserString(peerId);\r\n }\r\n return appChatsManager.getChatString(-peerId);\r\n }\r\n\r\n public getPeerUsername(peerId: number): string {\r\n if(peerId > 0) {\r\n return appUsersManager.getUser(peerId).username || '';\r\n }\r\n return appChatsManager.getChat(-peerId).username || '';\r\n }\r\n\r\n public getPeer(peerId: number) {\r\n return peerId > 0\r\n ? appUsersManager.getUser(peerId)\r\n : appChatsManager.getChat(-peerId)\r\n }\r\n\r\n public getPeerId(peerId: Peer | InputPeer | number | string): number {\r\n if(typeof(peerId) === 'number') return peerId;\r\n else if(isObject(peerId)) return (peerId as Peer.peerUser).user_id || -((peerId as Peer.peerChannel).channel_id || (peerId as Peer.peerChat).chat_id);\r\n else if(!peerId) return 0;\r\n \r\n const isUser = (peerId as string).charAt(0) === 'u';\r\n const peerParams = (peerId as string).substr(1).split('_');\r\n\r\n return isUser ? +peerParams[0] : -peerParams[0] || 0;\r\n }\r\n\r\n public getDialogPeer(peerId: number): DialogPeer {\r\n return {\r\n _: 'dialogPeer',\r\n peer: this.getOutputPeer(peerId)\r\n };\r\n }\r\n\r\n public isChannel(peerId: number): boolean {\r\n return (peerId < 0) && appChatsManager.isChannel(-peerId);\r\n }\r\n\r\n public isMegagroup(peerId: number) {\r\n return (peerId < 0) && appChatsManager.isMegagroup(-peerId);\r\n }\r\n\r\n public isAnyGroup(peerId: number): boolean {\r\n return (peerId < 0) && !appChatsManager.isBroadcast(-peerId);\r\n }\r\n\r\n public isBroadcast(peerId: number): boolean {\r\n return this.isChannel(peerId) && !this.isMegagroup(peerId);\r\n }\r\n\r\n public isBot(peerId: number): boolean {\r\n return (peerId > 0) && appUsersManager.isBot(peerId);\r\n }\r\n\r\n /* public getInputPeer(peerString: string): InputPeer {\r\n var firstChar = peerString.charAt(0);\r\n var peerParams = peerString.substr(1).split('_');\r\n let id = +peerParams[0];\r\n\r\n if(firstChar === 'u') {\r\n //appUsersManager.saveUserAccess(id, peerParams[1]);\r\n\r\n return {\r\n _: 'inputPeerUser',\r\n user_id: id,\r\n access_hash: peerParams[1]\r\n };\r\n } else if(firstChar === 'c' || firstChar === 's') {\r\n //appChatsManager.saveChannelAccess(id, peerParams[1]);\r\n if(firstChar === 's') {\r\n appChatsManager.saveIsMegagroup(id);\r\n }\r\n\r\n return {\r\n _: 'inputPeerChannel',\r\n channel_id: id,\r\n access_hash: peerParams[1] || '0'\r\n };\r\n } else {\r\n return {\r\n _: 'inputPeerChat',\r\n chat_id: id\r\n };\r\n }\r\n } */\r\n\r\n public getInputNotifyPeerById(peerId: number, ignorePeerId: true): Exclude<InputNotifyPeer, InputNotifyPeer.inputNotifyPeer>;\r\n public getInputNotifyPeerById(peerId: number, ignorePeerId?: false): InputNotifyPeer.inputNotifyPeer;\r\n public getInputNotifyPeerById(peerId: number, ignorePeerId?: boolean): InputNotifyPeer {\r\n if(ignorePeerId) {\r\n if(peerId > 0) {\r\n return {_: 'inputNotifyUsers'};\r\n } else {\r\n if(appPeersManager.isBroadcast(peerId)) {\r\n return {_: 'inputNotifyBroadcasts'};\r\n } else {\r\n return {_: 'inputNotifyChats'};\r\n }\r\n }\r\n } else {\r\n return {\r\n _: 'inputNotifyPeer', \r\n peer: this.getInputPeerById(peerId)\r\n };\r\n }\r\n }\r\n\r\n public getInputPeerById(peerId: number): InputPeer {\r\n if(!peerId) {\r\n return {_: 'inputPeerEmpty'};\r\n }\r\n\r\n if(peerId < 0) {\r\n const chatId = -peerId;\r\n if(!appChatsManager.isChannel(chatId)) {\r\n return appChatsManager.getChatInputPeer(chatId);\r\n } else {\r\n return appChatsManager.getChannelInputPeer(chatId);\r\n }\r\n }\r\n\r\n return {\r\n _: 'inputPeerUser',\r\n user_id: peerId,\r\n access_hash: appUsersManager.getUser(peerId).access_hash\r\n };\r\n }\r\n\r\n public getInputDialogPeerById(peerId: number): InputDialogPeer {\r\n return {\r\n _: 'inputDialogPeer',\r\n peer: this.getInputPeerById(peerId)\r\n }\r\n }\r\n\r\n public getPeerColorById(peerId: number, pic = true) {\r\n if(!peerId) return '';\r\n\r\n const idx = DialogColorsMap[(peerId < 0 ? -peerId : peerId) % 7];\r\n const color = (pic ? DialogColors : DialogColorsFg)[idx];\r\n return color;\r\n }\r\n\r\n public getPeerSearchText(peerId: number) {\r\n let text;\r\n if(peerId > 0) {\r\n text = '%pu ' + appUsersManager.getUserSearchText(peerId);\r\n } else if(peerId < 0) {\r\n const chat = appChatsManager.getChat(-peerId);\r\n text = '%pg ' + (chat.title || '');\r\n }\r\n return text;\r\n }\r\n\r\n public getDialogType(peerId: number): PeerType {\r\n if(appPeersManager.isMegagroup(peerId)) {\r\n return 'megagroup';\r\n } else if(appPeersManager.isChannel(peerId)) {\r\n return 'channel';\r\n } else if(peerId < 0) {\r\n return 'group';\r\n } else {\r\n return peerId === rootScope.myId ? 'saved' : 'chat';\r\n }\r\n }\r\n\r\n public getDeleteButtonText(peerId: number): LangPackKey {\r\n switch(this.getDialogType(peerId)) {\r\n case 'channel':\r\n return 'ChatList.Context.LeaveChannel';\r\n\r\n case 'megagroup':\r\n return 'ChatList.Context.LeaveGroup';\r\n\r\n case 'group':\r\n return 'ChatList.Context.DeleteAndExit';\r\n \r\n default:\r\n return 'ChatList.Context.DeleteChat';\r\n }\r\n }\r\n}\r\n\r\nconst appPeersManager = new AppPeersManager();\r\nMOUNT_CLASS_TO.appPeersManager = appPeersManager;\r\nexport default appPeersManager;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\r\nimport { MessageEntity } from \"../../layer\";\r\nimport RichTextProcessor from \"../../lib/richtextprocessor\";\r\nimport getRichElementValue from \"./getRichElementValue\";\r\n\r\nexport default function getRichValue(field: HTMLElement, withEntities = true) {\r\n const lines: string[] = [];\r\n const line: string[] = [];\r\n\r\n const entities: MessageEntity[] = withEntities ? [] : undefined;\r\n getRichElementValue(field, lines, line, undefined, undefined, entities);\r\n if(line.length) {\r\n lines.push(line.join(''));\r\n }\r\n\r\n let value = lines.join('\\n');\r\n value = value.replace(/\\u00A0/g, ' ');\r\n\r\n if(entities) {\r\n RichTextProcessor.combineSameEntities(entities);\r\n }\r\n\r\n //console.log('getRichValue:', value, entities);\r\n\r\n return {value, entities};\r\n}\r\n\r\nMOUNT_CLASS_TO.getRichValue = getRichValue;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nexport default function toggleDisability(elements: HTMLElement[], disable: boolean) {\r\n if(disable) {\r\n elements.forEach(el => el.setAttribute('disabled', 'true'));\r\n } else {\r\n elements.forEach(el => el.removeAttribute('disabled'));\r\n }\r\n\r\n return () => toggleDisability(elements, !disable);\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport type { ApplyServerTimeOffsetTask } from './timeManager';\r\nimport { MOUNT_CLASS_TO } from '../../config/debug';\r\n// import { tsNow } from '../../helpers/date';\r\nimport sessionStorage from '../sessionStorage';\r\nimport apiManager from './mtprotoworker';\r\n\r\nexport class ServerTimeManager {\r\n /* private midnightNoOffset: number;\r\n private midnightOffseted: Date;\r\n\r\n private midnightOffset: number; */\r\n\r\n public serverTimeOffset: number; // in seconds\r\n /* private timeParams: {\r\n midnightOffset: number,\r\n serverTimeOffset: number\r\n }; */\r\n\r\n constructor() {\r\n /* const timestampNow = tsNow(true);\r\n this.midnightNoOffset = timestampNow - (timestampNow % 86400);\r\n this.midnightOffseted = new Date();\r\n this.midnightOffseted.setHours(0, 0, 0, 0);\r\n \r\n this.midnightOffset = this.midnightNoOffset - (Math.floor(+this.midnightOffseted / 1000)); */\r\n\r\n this.serverTimeOffset = 0;\r\n /* this.timeParams = {\r\n midnightOffset: this.midnightOffset,\r\n serverTimeOffset: this.serverTimeOffset\r\n }; */\r\n\r\n sessionStorage.get('server_time_offset').then((to) => {\r\n if(to) {\r\n this.serverTimeOffset = to;\r\n // this.timeParams.serverTimeOffset = to;\r\n }\r\n });\r\n\r\n apiManager.addTaskListener('applyServerTimeOffset', (task: ApplyServerTimeOffsetTask) => {\r\n this.serverTimeOffset = task.payload;\r\n });\r\n }\r\n}\r\n\r\nconst serverTimeManager = new ServerTimeManager();\r\nMOUNT_CLASS_TO && (MOUNT_CLASS_TO.serverTimeManager = serverTimeManager);\r\nexport default serverTimeManager;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\n/* import { copy } from \"./object\";\r\n\r\nexport function listMergeSorted(list1: any[] = [], list2: any[] = []) {\r\n const result = copy(list1);\r\n\r\n const minId = list1.length ? list1[list1.length - 1] : 0xFFFFFFFF;\r\n for(let i = 0; i < list2.length; i++) {\r\n if(list2[i] < minId) {\r\n result.push(list2[i]);\r\n }\r\n }\r\n\r\n return result;\r\n} */\r\n\r\nexport const accumulate = (arr: number[], initialValue: number) => arr.reduce((acc, value) => acc + value, initialValue);\r\n\r\nexport function findAndSpliceAll<T>(array: Array<T>, verify: (value: T, index: number, arr: typeof array) => boolean) {\r\n const out: typeof array = [];\r\n let idx = -1;\r\n while((idx = array.findIndex(verify)) !== -1) {\r\n out.push(array.splice(idx, 1)[0]);\r\n }\r\n\r\n return out;\r\n}\r\n\r\nexport function forEachReverse<T>(array: Array<T>, callback: (value: T, index?: number, array?: Array<T>) => void) {\r\n for(let length = array.length, i = length - 1; i >= 0; --i) {\r\n callback(array[i], i, array);\r\n }\r\n};\r\n\r\nexport function insertInDescendSortedArray<T extends {[smth in K]?: number}, K extends keyof T>(array: Array<T>, element: T, property: K, pos?: number) {\r\n if(pos === undefined) {\r\n pos = array.indexOf(element);\r\n if(pos !== -1) {\r\n array.splice(pos, 1);\r\n }\r\n }\r\n\r\n const sortProperty: number = element[property];\r\n const len = array.length;\r\n if(!len || sortProperty <= array[len - 1][property]) {\r\n return array.push(element) - 1;\r\n } else if(sortProperty >= array[0][property]) {\r\n array.unshift(element);\r\n return 0;\r\n } else {\r\n for(let i = 0; i < len; i++) {\r\n if(sortProperty > array[i][property]) {\r\n array.splice(i, 0, element);\r\n return i;\r\n }\r\n }\r\n }\r\n\r\n console.error('wtf', array, element);\r\n return array.indexOf(element);\r\n}\r\n\r\nexport function filterUnique<T extends Array<any>>(arr: T): T {\r\n return [...new Set(arr)] as T;\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\n//import apiManager from '../mtproto/apiManager';\r\nimport DEBUG, { MOUNT_CLASS_TO } from '../../config/debug';\r\nimport { Message, MessageFwdHeader, Peer, Update, Updates } from '../../layer';\r\nimport { logger, LogTypes } from '../logger';\r\nimport apiManager from '../mtproto/mtprotoworker';\r\nimport rootScope from '../rootScope';\r\n//import networkerFactory from '../mtproto/networkerFactory';\r\nimport appUsersManager from \"./appUsersManager\";\r\nimport appChatsManager from \"./appChatsManager\";\r\nimport appPeersManager from \"./appPeersManager\";\r\nimport appStateManager from './appStateManager';\r\nimport serverTimeManager from '../mtproto/serverTimeManager';\r\n\r\ntype UpdatesState = {\r\n pendingPtsUpdates: (Update & {pts: number, pts_count: number})[],\r\n pendingSeqUpdates?: {[seq: number]: {seq: number, date: number, updates: any[]}},\r\n syncPending: {\r\n seqAwaiting?: number,\r\n ptsAwaiting?: true,\r\n timeout: number\r\n },\r\n syncLoading: Promise<void>,\r\n\r\n seq?: number,\r\n pts?: number,\r\n date?: number,\r\n lastPtsUpdateTime?: number\r\n};\r\n\r\nconst SYNC_DELAY = 6;\r\n\r\nexport class ApiUpdatesManager {\r\n public updatesState: UpdatesState = {\r\n pendingPtsUpdates: [],\r\n pendingSeqUpdates: {},\r\n syncPending: null,\r\n syncLoading: null\r\n };\r\n\r\n private channelStates: {[channelId: number]: UpdatesState} = {};\r\n private attached = false;\r\n\r\n private log = logger('UPDATES', LogTypes.Error | LogTypes.Warn | LogTypes.Log/* | LogTypes.Debug */);\r\n private debug = DEBUG;\r\n\r\n private setProxy() {\r\n const self = this;\r\n this.updatesState = new Proxy(this.updatesState, {\r\n set: function(target: ApiUpdatesManager['updatesState'], key: keyof ApiUpdatesManager['updatesState'], value: ApiUpdatesManager['updatesState'][typeof key]) {\r\n // @ts-ignore\r\n target[key] = value;\r\n self.saveUpdatesState();\r\n return true;\r\n }\r\n });\r\n }\r\n\r\n public saveUpdatesState() {\r\n const us = this.updatesState;\r\n appStateManager.pushToState('updates', {\r\n seq: us.seq,\r\n pts: us.pts,\r\n date: us.date\r\n });\r\n }\r\n\r\n private popPendingSeqUpdate() {\r\n const state = this.updatesState;\r\n const nextSeq = state.seq + 1;\r\n const pendingUpdatesData = state.pendingSeqUpdates[nextSeq];\r\n if(!pendingUpdatesData) {\r\n return false;\r\n }\r\n\r\n const updates = pendingUpdatesData.updates;\r\n for(let i = 0, length = updates.length; i < length; ++i) {\r\n this.saveUpdate(updates[i]);\r\n }\r\n\r\n state.seq = pendingUpdatesData.seq;\r\n if(pendingUpdatesData.date && state.date < pendingUpdatesData.date) {\r\n state.date = pendingUpdatesData.date;\r\n }\r\n delete state.pendingSeqUpdates[nextSeq];\r\n \r\n if(!this.popPendingSeqUpdate() &&\r\n state.syncPending &&\r\n state.syncPending.seqAwaiting &&\r\n state.seq >= state.syncPending.seqAwaiting) {\r\n if(!state.syncPending.ptsAwaiting) {\r\n clearTimeout(state.syncPending.timeout);\r\n state.syncPending = null;\r\n } else {\r\n delete state.syncPending.seqAwaiting;\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n private popPendingPtsUpdate(channelId: number) {\r\n const curState = channelId ? this.getChannelState(channelId) : this.updatesState;\r\n if(!curState.pendingPtsUpdates.length) {\r\n return false;\r\n }\r\n\r\n curState.pendingPtsUpdates.sort((a, b) => {\r\n return a.pts - b.pts;\r\n });\r\n // this.log('pop update', channelId, curState.pendingPtsUpdates)\r\n \r\n let curPts = curState.pts;\r\n let goodPts = 0;\r\n let goodIndex = 0;\r\n for(let i = 0, length = curState.pendingPtsUpdates.length; i < length; ++i) {\r\n const update = curState.pendingPtsUpdates[i];\r\n curPts += update.pts_count;\r\n if(curPts >= update.pts) {\r\n goodPts = update.pts;\r\n goodIndex = i;\r\n }\r\n }\r\n \r\n if(!goodPts) {\r\n return false;\r\n }\r\n \r\n this.debug && this.log.debug('pop pending pts updates', goodPts, curState.pendingPtsUpdates.slice(0, goodIndex + 1));\r\n \r\n curState.pts = goodPts;\r\n for(let i = 0; i <= goodIndex; ++i) {\r\n const update = curState.pendingPtsUpdates[i];\r\n\r\n // @ts-ignore\r\n this.saveUpdate(update);\r\n }\r\n curState.pendingPtsUpdates.splice(0, goodIndex + 1);\r\n \r\n if(!curState.pendingPtsUpdates.length && curState.syncPending) {\r\n if(!curState.syncPending.seqAwaiting) {\r\n clearTimeout(curState.syncPending.timeout);\r\n curState.syncPending = null;\r\n } else {\r\n delete curState.syncPending.ptsAwaiting;\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n public forceGetDifference() {\r\n if(!this.updatesState.syncLoading) {\r\n this.getDifference();\r\n }\r\n }\r\n\r\n public processLocalUpdate(update: Update) {\r\n this.processUpdateMessage({\r\n _: 'updateShort',\r\n update\r\n } as Updates);\r\n }\r\n\r\n public processUpdateMessage = (updateMessage: any, options: Partial<{\r\n override: boolean\r\n }> = {}) => {\r\n // return forceGetDifference()\r\n const processOpts = {\r\n date: updateMessage.date,\r\n seq: updateMessage.seq,\r\n seqStart: updateMessage.seq_start,\r\n //ignoreSyncLoading: options.ignoreSyncLoading\r\n };\r\n\r\n this.debug && this.log.debug('processUpdateMessage', updateMessage);\r\n \r\n switch(updateMessage._) {\r\n case 'updatesTooLong':\r\n case 'new_session_created':\r\n this.forceGetDifference();\r\n break;\r\n \r\n case 'updateShort':\r\n this.processUpdate(updateMessage.update, processOpts);\r\n break;\r\n \r\n case 'updateShortMessage':\r\n case 'updateShortChatMessage': {\r\n this.debug && this.log.debug('updateShortMessage | updateShortChatMessage', {...updateMessage});\r\n const isOut = updateMessage.pFlags.out;\r\n const fromId = updateMessage.from_id || (isOut ? rootScope.myId : updateMessage.user_id);\r\n const toId = updateMessage.chat_id\r\n ? -updateMessage.chat_id\r\n : (updateMessage.user_id || rootScope.myId);\r\n \r\n this.processUpdate({\r\n _: 'updateNewMessage',\r\n message: {\r\n _: 'message',\r\n pFlags: updateMessage.pFlags,\r\n id: updateMessage.id,\r\n from_id: appPeersManager.getOutputPeer(fromId),\r\n peer_id: appPeersManager.getOutputPeer(toId),\r\n date: updateMessage.date,\r\n message: updateMessage.message,\r\n fwd_from: updateMessage.fwd_from,\r\n reply_to: updateMessage.reply_to,\r\n entities: updateMessage.entities\r\n },\r\n pts: updateMessage.pts,\r\n pts_count: updateMessage.pts_count\r\n }, processOpts);\r\n break;\r\n }\r\n \r\n case 'updatesCombined':\r\n case 'updates':\r\n appUsersManager.saveApiUsers(updateMessage.users, options.override);\r\n appChatsManager.saveApiChats(updateMessage.chats, options.override);\r\n \r\n updateMessage.updates.forEach((update: Update) => {\r\n this.processUpdate(update, processOpts);\r\n });\r\n break;\r\n \r\n default:\r\n this.log.warn('Unknown update message', updateMessage);\r\n }\r\n };\r\n \r\n private getDifference(first = false): Promise<void> {\r\n // this.trace('Get full diff')\r\n const updatesState = this.updatesState;\r\n let wasSyncing = updatesState.syncLoading;\r\n if(!wasSyncing) {\r\n updatesState.pendingSeqUpdates = {};\r\n updatesState.pendingPtsUpdates = [];\r\n }\r\n \r\n if(updatesState.syncPending) {\r\n clearTimeout(updatesState.syncPending.timeout);\r\n updatesState.syncPending = null;\r\n }\r\n\r\n const promise = apiManager.invokeApi('updates.getDifference', {\r\n pts: updatesState.pts, \r\n pts_total_limit: first /* && false */? /* 50 */1200 : undefined,\r\n date: updatesState.date, \r\n qts: -1\r\n }, {\r\n timeout: 0x7fffffff\r\n }).then((differenceResult) => {\r\n this.debug && this.log.debug('Get diff result', differenceResult);\r\n\r\n if(differenceResult._ === 'updates.differenceEmpty') {\r\n this.debug && this.log.debug('apply empty diff', differenceResult.seq);\r\n updatesState.date = differenceResult.date;\r\n updatesState.seq = differenceResult.seq;\r\n return;\r\n }\r\n\r\n // ! SORRY I'M SORRY I'M SORRY\r\n if(first) {\r\n rootScope.dispatchEvent('state_synchronizing');\r\n }\r\n\r\n if(differenceResult._ !== 'updates.differenceTooLong') {\r\n appUsersManager.saveApiUsers(differenceResult.users);\r\n appChatsManager.saveApiChats(differenceResult.chats);\r\n\r\n // Should be first because of updateMessageID\r\n // this.log('applying', differenceResult.other_updates.length, 'other updates')\r\n \r\n differenceResult.other_updates.forEach((update) => {\r\n switch(update._) {\r\n case 'updateChannelTooLong':\r\n case 'updateNewChannelMessage':\r\n case 'updateEditChannelMessage':\r\n this.processUpdate(update);\r\n return;\r\n }\r\n \r\n this.saveUpdate(update);\r\n });\r\n\r\n // this.log('applying', differenceResult.new_messages.length, 'new messages')\r\n differenceResult.new_messages.forEach((apiMessage) => {\r\n this.saveUpdate({\r\n _: 'updateNewMessage',\r\n message: apiMessage,\r\n pts: updatesState.pts,\r\n pts_count: 0\r\n });\r\n });\r\n\r\n const nextState = differenceResult._ === 'updates.difference' ? differenceResult.state : differenceResult.intermediate_state;\r\n updatesState.seq = nextState.seq;\r\n updatesState.pts = nextState.pts;\r\n updatesState.date = nextState.date;\r\n } else {\r\n updatesState.pts = differenceResult.pts;\r\n updatesState.date = (Date.now() / 1000 | 0) + serverTimeManager.serverTimeOffset;\r\n delete updatesState.seq;\r\n \r\n this.channelStates = {};\r\n \r\n this.log.warn('getDifference:', differenceResult._);\r\n rootScope.dispatchEvent('state_cleared');\r\n }\r\n \r\n // this.log('apply diff', updatesState.seq, updatesState.pts)\r\n \r\n if(differenceResult._ === 'updates.differenceSlice') {\r\n return this.getDifference();\r\n } else {\r\n this.debug && this.log.debug('finished get diff');\r\n }\r\n });\r\n\r\n if(!wasSyncing) {\r\n this.justAName(updatesState, promise);\r\n }\r\n \r\n return promise;\r\n }\r\n\r\n private getChannelDifference(channelId: number): Promise<void> {\r\n const channelState = this.getChannelState(channelId);\r\n const wasSyncing = channelState.syncLoading;\r\n if(!wasSyncing) {\r\n channelState.pendingPtsUpdates = [];\r\n }\r\n\r\n if(channelState.syncPending) {\r\n clearTimeout(channelState.syncPending.timeout);\r\n channelState.syncPending = null;\r\n }\r\n\r\n //this.log.trace('Get channel diff', appChatsManager.getChat(channelId), channelState.pts);\r\n const promise = apiManager.invokeApi('updates.getChannelDifference', {\r\n channel: appChatsManager.getChannelInput(channelId),\r\n filter: {_: 'channelMessagesFilterEmpty'},\r\n pts: channelState.pts,\r\n limit: 30\r\n }, {timeout: 0x7fffffff}).then((differenceResult) => {\r\n this.debug && this.log.debug('Get channel diff result', differenceResult)\r\n channelState.pts = 'pts' in differenceResult ? differenceResult.pts : undefined;\r\n \r\n if(differenceResult._ === 'updates.channelDifferenceEmpty') {\r\n this.debug && this.log.debug('apply channel empty diff', differenceResult);\r\n return;\r\n }\r\n \r\n if(differenceResult._ === 'updates.channelDifferenceTooLong') {\r\n this.debug && this.log.debug('channel diff too long', differenceResult);\r\n delete this.channelStates[channelId];\r\n\r\n this.saveUpdate({_: 'updateChannelReload', channel_id: channelId});\r\n return;\r\n }\r\n \r\n appUsersManager.saveApiUsers(differenceResult.users);\r\n appChatsManager.saveApiChats(differenceResult.chats);\r\n \r\n // Should be first because of updateMessageID\r\n this.debug && this.log.debug('applying', differenceResult.other_updates.length, 'channel other updates');\r\n differenceResult.other_updates.forEach((update) => {\r\n this.saveUpdate(update);\r\n });\r\n \r\n this.debug && this.log.debug('applying', differenceResult.new_messages.length, 'channel new messages');\r\n differenceResult.new_messages.forEach((apiMessage) => {\r\n this.saveUpdate({\r\n _: 'updateNewChannelMessage',\r\n message: apiMessage,\r\n pts: channelState.pts,\r\n pts_count: 0\r\n });\r\n });\r\n \r\n this.debug && this.log.debug('apply channel diff', channelState.pts);\r\n \r\n if(differenceResult._ === 'updates.channelDifference' &&\r\n !differenceResult.pFlags['final']) {\r\n return this.getChannelDifference(channelId);\r\n } else {\r\n this.debug && this.log.debug('finished channel get diff');\r\n }\r\n });\r\n\r\n if(!wasSyncing) {\r\n this.justAName(channelState, promise, channelId);\r\n }\r\n\r\n return promise;\r\n }\r\n\r\n private justAName(state: UpdatesState, promise: UpdatesState['syncLoading'], channelId?: number) {\r\n state.syncLoading = promise;\r\n rootScope.dispatchEvent('state_synchronizing', channelId);\r\n\r\n promise.then(() => {\r\n state.syncLoading = null;\r\n rootScope.dispatchEvent('state_synchronized', channelId);\r\n }, () => {\r\n state.syncLoading = null;\r\n });\r\n }\r\n \r\n public addChannelState(channelId: number, pts: number) {\r\n if(!pts) {\r\n throw new Error('Add channel state without pts ' + channelId);\r\n }\r\n\r\n if(!(channelId in this.channelStates)) {\r\n this.channelStates[channelId] = {\r\n pts,\r\n pendingPtsUpdates: [],\r\n syncPending: null,\r\n syncLoading: null\r\n };\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n public getChannelState(channelId: number, pts?: number) {\r\n if(this.channelStates[channelId] === undefined) {\r\n this.addChannelState(channelId, pts);\r\n }\r\n\r\n return this.channelStates[channelId];\r\n }\r\n\r\n private processUpdate(update: Update, options: Partial<{\r\n date: number,\r\n seq: number,\r\n seqStart: number/* ,\r\n ignoreSyncLoading: boolean */\r\n }> = {}) {\r\n let channelId = 0;\r\n switch(update._) {\r\n case 'updateNewChannelMessage':\r\n case 'updateEditChannelMessage':\r\n channelId = -appPeersManager.getPeerId(update.message.peer_id);\r\n break;\r\n /* case 'updateDeleteChannelMessages':\r\n channelId = update.channel_id;\r\n break; */\r\n case 'updateChannelTooLong':\r\n channelId = update.channel_id;\r\n if(!(channelId in this.channelStates)) {\r\n return false;\r\n }\r\n break;\r\n default:\r\n if('channel_id' in update) {\r\n channelId = update.channel_id;\r\n }\r\n break;\r\n }\r\n \r\n const {pts, pts_count} = update as Update.updateNewMessage;\r\n const curState = channelId ? this.getChannelState(channelId, pts) : this.updatesState;\r\n \r\n // this.log.log('process', channelId, curState.pts, update)\r\n \r\n if(curState.syncLoading/* && !options.ignoreSyncLoading */) {\r\n return false;\r\n }\r\n \r\n if(update._ === 'updateChannelTooLong') {\r\n if(!curState.lastPtsUpdateTime ||\r\n curState.lastPtsUpdateTime < (Date.now() - SYNC_DELAY)) {\r\n // this.log.trace('channel too long, get diff', channelId, update)\r\n this.getChannelDifference(channelId);\r\n }\r\n return false;\r\n }\r\n \r\n if(update._ === 'updateNewMessage' ||\r\n update._ === 'updateEditMessage' ||\r\n update._ === 'updateNewChannelMessage' ||\r\n update._ === 'updateEditChannelMessage') {\r\n const message = update.message as Message.message;\r\n const toPeerId = appPeersManager.getPeerId(message.peer_id);\r\n const fwdHeader: MessageFwdHeader.messageFwdHeader = message.fwd_from || {} as any;\r\n let reason: string;\r\n if(message.from_id && !appUsersManager.hasUser(appPeersManager.getPeerId(message.from_id), message.pFlags.post/* || channelId*/) && (reason = 'author') ||\r\n fwdHeader.from_id && !appUsersManager.hasUser(appPeersManager.getPeerId(fwdHeader.from_id), !!(fwdHeader.from_id as Peer.peerChannel).channel_id) && (reason = 'fwdAuthor') ||\r\n (fwdHeader.from_id as Peer.peerChannel)?.channel_id && !appChatsManager.hasChat((fwdHeader.from_id as Peer.peerChannel).channel_id, true) && (reason = 'fwdChannel') ||\r\n toPeerId > 0 && !appUsersManager.hasUser(toPeerId) && (reason = 'toPeer User') ||\r\n toPeerId < 0 && !appChatsManager.hasChat(-toPeerId) && (reason = 'toPeer Chat')) {\r\n this.log.warn('Not enough data for message update', toPeerId, reason, message);\r\n if(channelId && appChatsManager.hasChat(channelId)) {\r\n this.getChannelDifference(channelId);\r\n } else {\r\n this.forceGetDifference();\r\n }\r\n return false;\r\n }\r\n } else if(channelId && !appChatsManager.hasChat(channelId)) {\r\n // this.log.log('skip update, missing channel', channelId, update)\r\n return false;\r\n }\r\n \r\n let popPts: boolean;\r\n let popSeq: boolean;\r\n \r\n if(pts) {\r\n const newPts = curState.pts + (pts_count || 0);\r\n if(newPts < pts) {\r\n this.debug && this.log.warn('Pts hole', curState, update, channelId && appChatsManager.getChat(channelId));\r\n curState.pendingPtsUpdates.push(update as Update.updateNewMessage);\r\n if(!curState.syncPending && !curState.syncLoading) {\r\n curState.syncPending = {\r\n timeout: window.setTimeout(() => {\r\n curState.syncPending = null;\r\n\r\n if(curState.syncLoading) {\r\n return;\r\n }\r\n\r\n if(channelId) {\r\n this.getChannelDifference(channelId);\r\n } else {\r\n this.getDifference();\r\n }\r\n }, SYNC_DELAY)\r\n };\r\n }\r\n\r\n curState.syncPending.ptsAwaiting = true;\r\n return false;\r\n }\r\n\r\n if(pts > curState.pts) {\r\n curState.pts = pts;\r\n popPts = true;\r\n \r\n curState.lastPtsUpdateTime = Date.now();\r\n } else if(pts_count) {\r\n // this.log.warn('Duplicate update', update)\r\n return false;\r\n }\r\n\r\n if(channelId && options.date && this.updatesState.date < options.date) {\r\n this.updatesState.date = options.date;\r\n }\r\n } else if(!channelId && options.seq > 0) {\r\n const seq = options.seq;\r\n const seqStart = options.seqStart || seq;\r\n \r\n if(seqStart !== curState.seq + 1) {\r\n if(seqStart > curState.seq) {\r\n this.debug && this.log.warn('Seq hole', curState, curState.syncPending && curState.syncPending.seqAwaiting);\r\n \r\n if(curState.pendingSeqUpdates[seqStart] === undefined) {\r\n curState.pendingSeqUpdates[seqStart] = {seq, date: options.date, updates: []};\r\n }\r\n curState.pendingSeqUpdates[seqStart].updates.push(update);\r\n \r\n if(!curState.syncPending) {\r\n curState.syncPending = {\r\n timeout: window.setTimeout(() => {\r\n curState.syncPending = null;\r\n\r\n if(curState.syncLoading) {\r\n return;\r\n }\r\n\r\n this.getDifference();\r\n }, SYNC_DELAY)\r\n };\r\n }\r\n\r\n if(!curState.syncPending.seqAwaiting ||\r\n curState.syncPending.seqAwaiting < seqStart) {\r\n curState.syncPending.seqAwaiting = seqStart;\r\n }\r\n return false;\r\n }\r\n }\r\n \r\n if(curState.seq !== seq) {\r\n curState.seq = seq;\r\n if(options.date && curState.date < options.date) {\r\n curState.date = options.date;\r\n }\r\n\r\n popSeq = true;\r\n }\r\n }\r\n \r\n this.saveUpdate(update);\r\n \r\n if(popPts) {\r\n this.popPendingPtsUpdate(channelId);\r\n } else if(popSeq) {\r\n this.popPendingSeqUpdate();\r\n }\r\n }\r\n\r\n public saveUpdate(update: Update) {\r\n //this.debug && this.log('saveUpdate', update);\r\n rootScope.dispatchEvent(update._, update as any);\r\n }\r\n \r\n public attach() {\r\n if(this.attached) return;\r\n\r\n //return;\r\n\r\n this.log('attach');\r\n \r\n this.attached = true;\r\n\r\n appStateManager.getState().then(_state => {\r\n const state = _state.updates;\r\n\r\n //rootScope.broadcast('state_synchronizing');\r\n if(!state || !state.pts || !state.date || !state.seq) {\r\n this.log('will get new state');\r\n\r\n this.updatesState.syncLoading = new Promise((resolve) => {\r\n apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult) => {\r\n this.updatesState.seq = stateResult.seq;\r\n this.updatesState.pts = stateResult.pts;\r\n this.updatesState.date = stateResult.date;\r\n this.saveUpdatesState();\r\n //setTimeout(() => {\r\n this.updatesState.syncLoading = null;\r\n resolve();\r\n //rootScope.broadcast('state_synchronized');\r\n //}, 1000);\r\n \r\n // ! for testing\r\n // updatesState.seq = 1\r\n // updatesState.pts = stateResult.pts - 5000\r\n // updatesState.date = 1\r\n // getDifference()\r\n });\r\n });\r\n } else {\r\n // ! for testing\r\n /* state.seq = 1;\r\n state.pts = state.pts - 15;\r\n state.date = 1; */\r\n // state.pts -= 100;\r\n\r\n Object.assign(this.updatesState, state);\r\n \r\n this.log('will get difference', Object.assign({}, state));\r\n \r\n this.getDifference(true)/* .finally(() => {\r\n if(this.updatesState.syncLoading) {\r\n rootScope.broadcast('state_synchronizing');\r\n }\r\n }) */;\r\n }\r\n\r\n apiManager.setUpdatesProcessor(this.processUpdateMessage);\r\n\r\n // this.updatesState.syncLoading.then(() => {\r\n this.setProxy();\r\n // });\r\n });\r\n }\r\n}\r\n\r\nconst apiUpdatesManager = new ApiUpdatesManager();\r\nMOUNT_CLASS_TO.apiUpdatesManager = apiUpdatesManager;\r\nexport default apiUpdatesManager\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport { MessageEntity } from \"../../layer\";\r\n\r\nexport type MarkdownType = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'monospace' | 'link' | 'mentionName';\r\nexport type MarkdownTag = {\r\n match: string,\r\n entityName: 'messageEntityBold' | 'messageEntityUnderline' | 'messageEntityItalic' | 'messageEntityPre' | 'messageEntityStrike' | 'messageEntityTextUrl' | 'messageEntityMentionName';\r\n};\r\nexport const markdownTags: {[type in MarkdownType]: MarkdownTag} = {\r\n bold: {\r\n match: '[style*=\"font-weight\"], b',\r\n entityName: 'messageEntityBold'\r\n },\r\n underline: {\r\n match: '[style*=\"underline\"], u',\r\n entityName: 'messageEntityUnderline'\r\n },\r\n italic: {\r\n match: '[style*=\"italic\"], i',\r\n entityName: 'messageEntityItalic'\r\n },\r\n monospace: {\r\n match: '[style*=\"monospace\"], [face=\"monospace\"]',\r\n entityName: 'messageEntityPre'\r\n },\r\n strikethrough: {\r\n match: '[style*=\"line-through\"], strike',\r\n entityName: 'messageEntityStrike'\r\n },\r\n link: {\r\n match: 'A:not(.follow)',\r\n entityName: 'messageEntityTextUrl'\r\n },\r\n mentionName: {\r\n match: 'A.follow',\r\n entityName: 'messageEntityMentionName'\r\n }\r\n};\r\n\r\nexport default function getRichElementValue(node: HTMLElement, lines: string[], line: string[], selNode?: Node, selOffset?: number, entities?: MessageEntity[], offset = {offset: 0}) {\r\n if(node.nodeType === 3) { // TEXT\r\n const nodeValue = node.nodeValue;\r\n\r\n if(selNode === node) {\r\n line.push(nodeValue.substr(0, selOffset) + '\\x01' + nodeValue.substr(selOffset));\r\n } else {\r\n line.push(nodeValue);\r\n }\r\n\r\n if(entities && nodeValue.trim()) {\r\n if(node.parentNode) {\r\n const parentElement = node.parentElement;\r\n \r\n for(const type in markdownTags) {\r\n const tag = markdownTags[type as MarkdownType];\r\n const closest = parentElement.closest(tag.match + ', [contenteditable]');\r\n if(closest && closest.getAttribute('contenteditable') === null) {\r\n if(tag.entityName === 'messageEntityTextUrl') {\r\n entities.push({\r\n _: tag.entityName,\r\n url: (parentElement as HTMLAnchorElement).href,\r\n offset: offset.offset,\r\n length: nodeValue.length\r\n });\r\n } else if(tag.entityName === 'messageEntityMentionName') {\r\n entities.push({\r\n _: tag.entityName,\r\n offset: offset.offset,\r\n length: nodeValue.length,\r\n user_id: +parentElement.dataset.follow\r\n });\r\n } else {\r\n entities.push({\r\n _: tag.entityName as any,\r\n offset: offset.offset,\r\n length: nodeValue.length\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n offset.offset += nodeValue.length;\r\n\r\n return;\r\n }\r\n\r\n if(node.nodeType !== 1) { // NON-ELEMENT\r\n return;\r\n }\r\n\r\n const isSelected = (selNode === node);\r\n const isBlock = node.tagName === 'DIV' || node.tagName === 'P';\r\n if(isBlock && line.length || node.tagName === 'BR') {\r\n lines.push(line.join(''));\r\n line.splice(0, line.length);\r\n } else if(node.tagName === 'IMG') {\r\n const alt = (node as HTMLImageElement).alt;\r\n if(alt) {\r\n line.push(alt);\r\n offset.offset += alt.length;\r\n }\r\n }\r\n\r\n if(isSelected && !selOffset) {\r\n line.push('\\x01');\r\n }\r\n\r\n let curChild = node.firstChild as HTMLElement;\r\n while(curChild) {\r\n getRichElementValue(curChild, lines, line, selNode, selOffset, entities, offset);\r\n curChild = curChild.nextSibling as any;\r\n }\r\n\r\n if(isSelected && selOffset) {\r\n line.push('\\x01');\r\n }\r\n\r\n if(isBlock && line.length) {\r\n lines.push(line.join(''));\r\n line.splice(0, line.length);\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nexport default function findUpAttribute(el: any, attribute: string): HTMLElement {\r\n return el.closest(`[${attribute}]`);\r\n /* if(el.getAttribute(attribute) !== null) return el; // 03.02.2020\r\n\r\n while(el.parentElement) {\r\n el = el.parentElement;\r\n if(el.getAttribute(attribute) !== null) \r\n return el;\r\n }\r\n return null; */\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport getRichValue from \"./getRichValue\";\r\n\r\nexport default function isInputEmpty(element: HTMLElement) {\r\n if(element.hasAttribute('contenteditable') || element.tagName !== 'INPUT') {\r\n /* const value = element.innerText;\r\n\r\n return !value.trim() && !serializeNodes(Array.from(element.childNodes)).trim(); */\r\n return !getRichValue(element, false).value.trim();\r\n } else {\r\n return !(element as HTMLInputElement).value.trim();\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport type { AccountPassword, AccountUpdatePasswordSettings, InputCheckPasswordSRP, PasswordKdfAlgo } from '../../layer';\r\nimport { MOUNT_CLASS_TO } from '../../config/debug';\r\nimport appUsersManager from '../appManagers/appUsersManager';\r\nimport apiManager from './mtprotoworker';\r\n\r\nexport class PasswordManager {\r\n public getState(): Promise<AccountPassword> {\r\n return apiManager.invokeApi('account.getPassword').then((result) => {\r\n return result;\r\n });\r\n }\r\n\r\n public updateSettings(settings: {\r\n hint?: string,\r\n email?: string,\r\n newPassword?: string,\r\n currentPassword?: string\r\n } = {}) {\r\n //state = Object.assign({}, state);\r\n //state.new_algo = Object.assign({}, state.new_algo);\r\n\r\n return this.getState().then(state => {\r\n let currentHashPromise: Promise<InputCheckPasswordSRP>;\r\n let newHashPromise: Promise<Uint8Array>;\r\n const params: AccountUpdatePasswordSettings = {\r\n password: null,\r\n new_settings: {\r\n _: 'account.passwordInputSettings',\r\n hint: settings.hint,\r\n email: settings.email\r\n }\r\n };\r\n \r\n if(settings.currentPassword) {\r\n currentHashPromise = apiManager.invokeCrypto('computeSRP', settings.currentPassword, state, false) as any;\r\n } else {\r\n currentHashPromise = Promise.resolve({\r\n _: 'inputCheckPasswordEmpty'\r\n });\r\n }\r\n \r\n // * https://core.telegram.org/api/srp#setting-a-new-2fa-password, but still there is a mistake, TDesktop passes 'new_algo' everytime\r\n const newAlgo = state.new_algo as PasswordKdfAlgo.passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow;\r\n const salt1 = new Uint8Array(newAlgo.salt1.length + 32);\r\n salt1.randomize();\r\n salt1.set(newAlgo.salt1, 0);\r\n newAlgo.salt1 = salt1;\r\n \r\n if(settings.newPassword) {\r\n newHashPromise = apiManager.invokeCrypto('computeSRP', settings.newPassword, state, true) as any;\r\n } else {\r\n newHashPromise = Promise.resolve(new Uint8Array());\r\n }\r\n \r\n return Promise.all([currentHashPromise, newHashPromise]).then((hashes) => {\r\n params.password = hashes[0];\r\n params.new_settings.new_algo = newAlgo;\r\n params.new_settings.new_password_hash = hashes[1];\r\n \r\n return apiManager.invokeApi('account.updatePasswordSettings', params);\r\n });\r\n });\r\n }\r\n\r\n public check(password: string, state: AccountPassword, options: any = {}) {\r\n return apiManager.invokeCrypto('computeSRP', password, state, false).then((inputCheckPassword) => {\r\n //console.log('SRP', inputCheckPassword);\r\n return apiManager.invokeApi('auth.checkPassword', {\r\n password: inputCheckPassword as InputCheckPasswordSRP.inputCheckPasswordSRP\r\n }, options).then(auth => {\r\n if(auth._ === 'auth.authorization') {\r\n appUsersManager.saveApiUser(auth.user);\r\n apiManager.setUserAuth(auth.user.id);\r\n }\r\n\r\n return auth;\r\n });\r\n });\r\n }\r\n\r\n public confirmPasswordEmail(code: string) {\r\n return apiManager.invokeApi('account.confirmPasswordEmail', {code});\r\n }\r\n\r\n public resendPasswordEmail() {\r\n return apiManager.invokeApi('account.resendPasswordEmail');\r\n }\r\n\r\n public cancelPasswordEmail() {\r\n return apiManager.invokeApi('account.cancelPasswordEmail');\r\n }\r\n\r\n /* public requestRecovery(options: any = {}) {\r\n return apiManager.invokeApi('auth.requestPasswordRecovery', {}, options);\r\n }\r\n\r\n public recover(code: any, options: any = {}) {\r\n return apiManager.invokeApi('auth.recoverPassword', {\r\n code\r\n }, options);\r\n } */\r\n}\r\n\r\nconst passwordManager = new PasswordManager();\r\nMOUNT_CLASS_TO.passwordManager = passwordManager;\r\nexport default passwordManager;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { LangPackKey, i18n } from \"../lib/langPack\";\r\n\r\nexport default class LoginPage {\r\n public element: HTMLElement;\r\n public container: HTMLElement;\r\n public imageDiv: HTMLElement;\r\n public inputWrapper: HTMLElement;\r\n public title: HTMLElement;\r\n public subtitle: HTMLParagraphElement;\r\n\r\n constructor(options: {\r\n className: string,\r\n withInputWrapper?: boolean,\r\n titleLangKey?: LangPackKey,\r\n subtitleLangKey?: LangPackKey,\r\n }) {\r\n this.element = document.body.querySelector('.' + options.className) as HTMLDivElement;\r\n //this.element = document.createElement('div');\r\n //this.element.className = 'page-' + options.className;\r\n\r\n this.container = document.createElement('div');\r\n this.container.className = 'container center-align';\r\n\r\n this.imageDiv = document.createElement('div');\r\n this.imageDiv.className = 'auth-image';\r\n\r\n this.title = document.createElement('h4');\r\n if(options.titleLangKey) {\r\n this.title.append(i18n(options.titleLangKey));\r\n }\r\n\r\n this.subtitle = document.createElement('p');\r\n this.subtitle.className = 'subtitle';\r\n if(options.subtitleLangKey) {\r\n this.subtitle.append(i18n(options.subtitleLangKey));\r\n }\r\n \r\n this.container.append(this.imageDiv, this.title, this.subtitle);\r\n\r\n if(options.withInputWrapper) {\r\n this.inputWrapper = document.createElement('div');\r\n this.inputWrapper.className = 'input-wrapper';\r\n this.container.append(this.inputWrapper);\r\n }\r\n\r\n this.element.append(this.container);\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { cancelEvent } from \"../helpers/dom/cancelEvent\";\r\nimport InputField, { InputFieldOptions } from \"./inputField\";\r\n\r\nexport default class PasswordInputField extends InputField {\r\n public passwordVisible = false;\r\n public toggleVisible: HTMLElement;\r\n public onVisibilityClickAdditional: () => void;\r\n\r\n constructor(options: InputFieldOptions = {}) {\r\n super({\r\n plainText: true,\r\n ...options\r\n });\r\n\r\n const input = this.input as HTMLInputElement;\r\n input.type = 'password';\r\n input.setAttribute('required', '');\r\n input.autocomplete = 'off';\r\n /* input.readOnly = true;\r\n\r\n input.addEventListener('focus', () => {\r\n input.removeAttribute('readonly');\r\n }, {once: true}); */\r\n\r\n // * https://stackoverflow.com/a/35949954/6758968\r\n const stealthy = document.createElement('input');\r\n stealthy.classList.add('stealthy');\r\n stealthy.tabIndex = -1;\r\n stealthy.type = 'password';\r\n input.parentElement.prepend(stealthy);\r\n input.parentElement.insertBefore(stealthy.cloneNode(), input.nextSibling);\r\n\r\n const toggleVisible = this.toggleVisible = document.createElement('span');\r\n toggleVisible.classList.add('toggle-visible', 'tgico');\r\n\r\n this.container.classList.add('input-field-password');\r\n this.container.append(toggleVisible);\r\n\r\n toggleVisible.addEventListener('click', this.onVisibilityClick);\r\n toggleVisible.addEventListener('touchend', this.onVisibilityClick);\r\n }\r\n\r\n public onVisibilityClick = (e: Event) => {\r\n cancelEvent(e);\r\n this.passwordVisible = !this.passwordVisible;\r\n\r\n this.toggleVisible.classList.toggle('eye-hidden', this.passwordVisible);\r\n (this.input as HTMLInputElement).type = this.passwordVisible ? 'text' : 'password';\r\n this.onVisibilityClickAdditional && this.onVisibilityClickAdditional();\r\n };\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport cleanSearchText from '../helpers/cleanSearchText';\r\n\r\nexport default class SearchIndex<SearchWhat> {\r\n private fullTexts: Map<SearchWhat, string> = new Map();\r\n\r\n // minChars can be 0 because it requires at least one word (one symbol) to be found\r\n constructor(private cleanText = true, private latinize = true, private minChars: number = 0) {\r\n\r\n }\r\n\r\n public indexObject(id: SearchWhat, searchText: string) {\r\n /* if(searchIndex.fullTexts.hasOwnProperty(id)) {\r\n return false;\r\n } */\r\n\r\n if(searchText.trim() && this.cleanText) {\r\n searchText = cleanSearchText(searchText, this.latinize);\r\n }\r\n\r\n if(!searchText) {\r\n this.fullTexts.delete(id);\r\n return false;\r\n }\r\n\r\n this.fullTexts.set(id, searchText);\r\n \r\n /* const shortIndexes = searchIndex.shortIndexes;\r\n searchText.split(' ').forEach((searchWord) => {\r\n let len = Math.min(searchWord.length, 3),\r\n wordPart, i;\r\n for(i = 1; i <= len; i++) {\r\n wordPart = searchWord.substr(0, i);\r\n if(shortIndexes[wordPart] === undefined) {\r\n shortIndexes[wordPart] = [id];\r\n } else {\r\n shortIndexes[wordPart].push(id);\r\n }\r\n }\r\n }); */\r\n }\r\n\r\n public search(query: string) {\r\n const fullTexts = this.fullTexts;\r\n //const shortIndexes = searchIndex.shortIndexes;\r\n\r\n if(this.cleanText) {\r\n query = cleanSearchText(query, this.latinize);\r\n }\r\n\r\n const newFoundObjs: Array<{fullText: string, fullTextLength: number, what: SearchWhat, foundChars: number}> = [];\r\n const queryWords = query.split(' ');\r\n const queryWordsLength = queryWords.length;\r\n fullTexts.forEach((fullText, what) => {\r\n let found = true;\r\n let foundChars = 0;\r\n for(let i = 0; i < queryWordsLength; ++i) { // * verify that all words are found\r\n const word = queryWords[i];\r\n const idx = fullText.indexOf(word);\r\n if(idx === -1 || (idx !== 0 && fullText[idx - 1] !== ' ')) { // * search only from word beginning\r\n found = false;\r\n break;\r\n }\r\n\r\n foundChars += word.length;\r\n }\r\n\r\n if(found) {\r\n foundChars += queryWordsLength - 1;\r\n const fullTextLength = fullText.length;\r\n if(this.minChars <= foundChars || fullTextLength <= foundChars) {\r\n newFoundObjs.push({fullText, fullTextLength, what, foundChars});\r\n }\r\n }\r\n });\r\n\r\n newFoundObjs.sort((a, b) => a.fullTextLength - b.fullTextLength || b.foundChars - a.foundChars);\r\n\r\n //newFoundObjs.sort((a, b) => a.fullText.localeCompare(b.fullText));\r\n const newFoundObjs2: Set<SearchWhat> = new Set(newFoundObjs.map(o => o.what));\r\n\r\n /* const queryWords = query.split(' ');\r\n let foundArr: number[];\r\n for(let i = 0; i < queryWords.length; i++) {\r\n const newFound = shortIndexes[queryWords[i].substr(0, 3)];\r\n if(!newFound) {\r\n foundArr = [];\r\n break;\r\n }\r\n \r\n if(foundArr === undefined || foundArr.length > newFound.length) {\r\n foundArr = newFound;\r\n }\r\n }\r\n\r\n for(let j = 0; j < foundArr.length; j++) {\r\n let found = true;\r\n let searchText = fullTexts[foundArr[j]];\r\n for(let i = 0; i < queryWords.length; i++) {\r\n if(searchText.indexOf(queryWords[i]) === -1) {\r\n found = false;\r\n break;\r\n }\r\n }\r\n\r\n if(found) {\r\n newFoundObjs[foundArr[j]] = true;\r\n }\r\n } */\r\n\r\n return newFoundObjs2;\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport lottieLoader, { RLottiePlayer } from \"../../lib/lottieLoader\";\r\nimport PasswordInputField from \"../passwordInputField\";\r\n\r\nexport default class PasswordMonkey {\r\n public container: HTMLElement;\r\n public animation: RLottiePlayer;\r\n public needFrame = 0;\r\n protected loadPromise: Promise<void>;\r\n\r\n constructor(protected passwordInputField: PasswordInputField, protected size: number) {\r\n this.container = document.createElement('div');\r\n this.container.classList.add('media-sticker-wrapper');\r\n }\r\n\r\n public load() {\r\n if(this.loadPromise) return this.loadPromise;\r\n return this.loadPromise = lottieLoader.loadAnimationFromURL({\r\n container: this.container,\r\n loop: false,\r\n autoplay: false,\r\n width: this.size,\r\n height: this.size,\r\n noCache: true\r\n //}, 'assets/img/TwoFactorSetupMonkeyClose.tgs').then(_animation => {\r\n }, 'assets/img/TwoFactorSetupMonkeyPeek.tgs').then(_animation => {\r\n //return;\r\n this.animation = _animation;\r\n this.animation.addEventListener('enterFrame', currentFrame => {\r\n //console.log('enterFrame', currentFrame, this.needFrame);\r\n\r\n if((this.animation.direction === 1 && currentFrame >= this.needFrame) ||\r\n (this.animation.direction === -1 && currentFrame <= this.needFrame)) {\r\n this.animation.setSpeed(1);\r\n this.animation.pause();\r\n } \r\n });\r\n\r\n this.passwordInputField.onVisibilityClickAdditional = () => {\r\n if(this.passwordInputField.passwordVisible) {\r\n this.animation.setDirection(1);\r\n this.animation.curFrame = 0;\r\n this.needFrame = 16;\r\n this.animation.play();\r\n } else {\r\n this.animation.setDirection(-1);\r\n this.animation.curFrame = 16;\r\n this.needFrame = 0;\r\n this.animation.play();\r\n }\r\n };\r\n\r\n return lottieLoader.waitForFirstFrame(_animation);\r\n });\r\n }\r\n\r\n public remove() {\r\n if(this.animation) {\r\n this.animation.remove();\r\n }\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport Config from \"../lib/config\";\r\n\r\nconst badCharsRe = /[`~!@#$%^&*()\\-_=+\\[\\]\\\\|{}'\";:\\/?.>,<]+/g;\r\nconst trimRe = /^\\s+|\\s$/g;\r\n\r\nexport default function cleanSearchText(text: string, latinize = true) {\r\n const hasTag = text.charAt(0) === '%';\r\n text = text.replace(badCharsRe, '').replace(trimRe, '');\r\n if(latinize) {\r\n text = text.replace(/[^A-Za-z0-9]/g, (ch) => {\r\n const latinizeCh = Config.LatinizeMap[ch];\r\n return latinizeCh !== undefined ? latinizeCh : ch;\r\n });\r\n }\r\n \r\n text = text.toLowerCase();\r\n if(hasTag) {\r\n text = '%' + text;\r\n }\r\n\r\n return text;\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\n/**\r\n * Legacy Webogram's format, don't change dcID to camelCase. date is timestamp\r\n */\r\nexport type UserAuth = {dcID: number | string, date: number, id: number};\r\n\r\nexport const REPLIES_PEER_ID = 1271266957;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nexport default function htmlToSpan(html: string) {\r\n const span = document.createElement('span');\r\n span.innerHTML = html;\r\n return span;\r\n}\r\n"],"sourceRoot":""}