1 line
179 KiB
Plaintext
1 line
179 KiB
Plaintext
{"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":""} |